ref: cea57785283e17b1a05909860d12e9a7dfe99600
dir: /m.c/
/* note that program isn't well tested on boardx != 6, boardy != 6 */ #include <stdio.h> #define boardx 6 #define boardy 6 #define empty ' ' char board[boardx * boardy]; int pieces[2] = { (boardx / 2 - 1)* boardy, (boardx / 2 - 1) * boardy }; char piece[2] = { '@', '#' }; int player = 0; int direction = -1; typedef struct { int x; int y; } point_t; typedef struct { point_t src; point_t dst; } swap_t; int pindex(int, int); void setupboard(void); void showrules(void); void showboard(void); void showhelp(void); char check(void); int check_put(point_t); int check_move(point_t); int check_swap(swap_t); int put(point_t); int move(point_t); int swap(swap_t); typedef struct { char act; point_t pos1; point_t pos2; } cmd_t; /* why y and x, and not x and y? C does it as YX, doing it otherwise would make code way too complex */ int pindex(int y, int x) { if(x < 0 || x > boardx || y < 0 || y > boardy) { fprintf(stderr, "pindex(%d, %d) out of range\n", x, y); return -1; } return (x * boardy) + y; } void setupboard(void) { for(int x = 0; x < boardx; x++) { for(int y = 0; y < boardy; y++) { if(x == 0) board[pindex(x, y)] = piece[1]; else if(x == boardx - 1) board[pindex(x, y)] = piece[0]; else board[pindex(x, y)] = empty; } } } void showboard(void) { printf("\n"); printf("free %c: %d, free %c: %d\n", piece[0], pieces[0], piece[1], pieces[1]); for(int i = -1; i < boardx; i++) { if(i != -1) // makes top most sqaure ugly printf(" %d |", i); else printf(" * |"); for(int j = 0; j < boardy; j++) { if(i == -1) printf(" %d |", j); else printf(" %c |", board[pindex(i, j)]); } printf("\n"); } } void showrules(void) { printf("The goal is make a 4 in a row, where\n" "at least half (2) of them are other side.\n" "commands:\n" "h: show this help, b: show board, #: comment, NOP \n" "pXY: put a piece on XY, you may only do it for your first two rows.\n" "mXY: move the piece on XY one square forward.\n" "sXYXY: swap first two pieces, only if they are adjecnet.\n"); } void chplayer(void) { player = !player; direction *= -1; } cmd_t getcmd(void) { char string[6]; point_t pos1, pos2; cmd_t cmd; printf("\n%c turn> ", piece[player]); scanf("%s", string); switch(string[0]) { case 'm': case 'p': sscanf(&string[1], "%1d%1d", &pos1.x, &pos1.y); cmd.pos1 = pos1; break; case 's': sscanf(&string[1],"%1d%1d%1d%1d", &pos1.x, &pos1.y, &pos2.x, &pos2.y); cmd.pos1 = pos1; cmd.pos2 = pos2; break; } cmd.act = string[0]; return cmd; } int proccmd(cmd_t cmd) { switch(cmd.act) { case 'm': { if(pindex(cmd.pos1.x, cmd.pos1.y) == -1) return -1; return move(cmd.pos1); } case 's': { if(pindex(cmd.pos1.x, cmd.pos1.y) == -1 || pindex(cmd.pos2.x, cmd.pos2.y) == -1) return -1; swap_t s; s.src = cmd.pos1; s.dst = cmd.pos2; return swap(s); } case 'p': { if(pindex(cmd.pos1.x, cmd.pos1.y) == -1) return -1; return put(cmd.pos1); } case 'b': { showboard(); break; } case 'h': { showrules(); break; } case '#': { break; } default: { fprintf(stderr, "unkown command.\n"); break; } } return -1; } char check(void) { for(int x = 0 ; x < boardx ; x++) { for(int y = 0 ; y < boardy - 3 ; y++) { if(board[pindex(x, y)] != empty) { // horzictal if((board[pindex(x, y)] == piece[0] && x < (boardx / 2 + 1)) || (board[pindex(x, y)] == piece[1] && x >= (boardx / 2))) if(board[pindex(x, y)] == board[pindex(x, y+1)] && board[pindex(x, y)] == board[pindex(x, y+2)] && board[pindex(x, y)] == board[pindex(x, y+3)]) { printf("deb\n"); return board[pindex(x, y)]; } // vertical if((player == 0 && x < ( boardx / 2 + 1 )) || (player == 1 && x >= ( boardx / 2 + 1))) if(board[pindex(x, y)] == board[pindex(x - direction, y)] && board[pindex(x, y)] == board[pindex(x - direction * 2, y)] && board[pindex(x, y)] == board[pindex(x - direction * 3, y)]) return board[pindex(x, y)]; // diagonal rtl if(y == 1 || y == 2) if(board[pindex(x, y)] == board[pindex(x+1, y+1)] && board[pindex(x, y)] == board[pindex(x+2, y+2)] && board[pindex(x, y)] == board[pindex(x+3, y+3)]) return board[pindex(x, y)]; // diagonal ltr if(y == 3 || y == 4) if(board[pindex(x, y)] == board[pindex(x+1, y-1)] && board[pindex(x, y)] == board[pindex(x+2, y-2)] && board[pindex(x, y)] == board[pindex(x+3, y-3)]) return board[pindex(x, y)]; } } } return empty; } int check_swap(swap_t swap) { if((pindex(swap.src.x, swap.src.y) < 0) || (pindex(swap.dst.x, swap.dst.y) < 0)) { fprintf(stderr, "invalid input\n"); return -1; } if(swap.src.x - swap.dst.x > 1 || swap.src.x - swap.dst.x < -1 || swap.src.y - swap.dst.y > 1 || swap.src.y - swap.dst.y < -1) { fprintf(stderr, "src and dst aren't adjecent\n"); return -2; } if(board[pindex(swap.src.x, swap.src.y)] == empty || board[pindex(swap.dst.x, swap.dst.y)] == empty) { fprintf(stderr, "src or dst is empty\n"); return -3; } if(board[pindex(swap.src.x, swap.src.y)] == board[pindex(swap.dst.x, swap.dst.y)]) { fprintf(stderr, "src and dst have the same piece\n"); return -4; } if(pindex(swap.src.x, swap.src.y) == pindex(swap.dst.x, swap.dst.y)) { fprintf(stderr, "src and dst are the same square\n"); return -5; } return 0; } int swap(swap_t swap) { if(check_swap(swap) < 0) return -1; char temp = board[pindex(swap.src.x, swap.src.y)]; board[pindex(swap.src.x, swap.src.y)] = board[pindex(swap.dst.x, swap.dst.y)]; board[pindex(swap.dst.x, swap.dst.y)] = temp; return 0; } int check_move(point_t point) // todo: add checks for last row { if(pindex(point.x, point.y) == -1) { fprintf(stderr, "invalid input\n"); return -1; } if(board[pindex(point.x, point.y)] != piece[player]) { fprintf(stderr, "src is not your piece\n"); return -2; } if(board[pindex(point.x + direction, point.y )] != empty) { fprintf(stderr, "dst is not empty\n"); return -3; } return 0; } int move(point_t point) { if(check_move(point) < 0) return -1; board[pindex(point.x + direction, point.y)] = piece[player]; board[pindex(point.x, point.y)] = empty; return 0; } int check_put(point_t point) { if(pindex(point.x, point.y) == -1) { fprintf(stderr, "invalid input\n"); return -1; } if(board[pindex(point.x, point.y)] != empty) { fprintf(stderr, "dst is not empty\n"); return -2; } if((player == 0 && point.x < 4) || (player == 1 && point.x > 1)) { fprintf(stderr, "it's not on your first two rows\n"); return -3; } return 0; } int put(point_t point) { if(check_put(point) < 0) return -1; board[pindex(point.x, point.y)] = piece[player]; pieces[player]--; return 0; } int main(void) { showrules(); setupboard(); showboard(); while(check() == empty) { if(proccmd(getcmd()) == 0) { chplayer(); showboard(); } } return 0; }