One new display function has been added: show_move(...). show_move() displays an 'X', 'O', or blank in each board position.
Three functions have been added to support the tic tac toe game: init_board(), get_move(...), and check_win(...). init_board() simply clears all board positions and sets the winner, x_turn, move_count, and last_move variables to appropriate values. get_move() translates a mouse click into a row and column position. check_win() returns TRUE if a player has won the game; FALSE otherwise.
Finally, new_game() has been implemented. new_game() initializes the board, board window, and status winow.
[...] #define GAME_MENU "game_menu" #define UNDO "undo" #define INSET 5 #define X_WIN "X won!" #define O_WIN "O won!" #define TIE "Tie game." #define X_MOVE "X's turn." #define O_MOVE "O's turn." [...] /* --- Prototypes - display functions --- */ void show_board(); void show_status(); void show_move(int move_x, int move_y); /* */ /* --- Prototypes - game functions --- */ void init_board(); void get_move(int mouse_x, int mouse_y, int *move_x, int *move_y); bool check_win(int move_r, int move_c); /* */ void main(int argc, void *argv[]) { init_board(); GSinterfaceinit(NAME, IFILE, BSTORE, "wc", G640x480x256, argc, argv); GSinterface(); } void init_board() { int i, j; winner = PNONE; x_turn = TRUE; move_count = 0; last_move = NO_MOVE; for (i=0; i<3; i++) for (j=0; j<3; j++) board[i][j] = PNONE; } [...] bool new_game() { init_board(); show_board(); show_status(); GSdisablemenuitem(GAME_MENU, UNDO); return TRUE; } [...] bool make_move(int mouse_x, int mouse_y, DragStatusType status) { int move_r, move_c; if ((status == MOUSE_CLICK) || (status == DRAG_FINAL)) { if ((move_count < MAX_MOVES) && (winner == PNONE)) { get_move(mouse_x, mouse_y, &move_r, &move_c); if (board[move_r][move_c] == PNONE) { move_count++; board[move_r][move_c] = x_turn? X : O; show_move(move_r, move_c); last_move = move_r*3 + move_c; GSenablemenuitem(GAME_MENU, UNDO); if (check_win(move_r, move_c)) winner = x_turn? X : O; x_turn = !x_turn; show_status(); } } } return TRUE; } void show_board() { int x, y, wd, ht; int i, j; GSgetdragareaspecs(GAME_WIND, GAME_DRAG, &x, &y, &wd, &ht, NULL, NULL); GSsetcurrentnamedwindow(GAME_WIND); /* show board */ GSsetlinesize(5); GSsetcolor(GSconvertcolor("black")); GSwdrawline(x+(wd/3), y, x+(wd/3), y+ht); GSwdrawline(x+(2*wd/3), y, x+(2*wd/3), y+ht); GSwdrawline(x, y+(ht/3), x+wd, y+(ht/3)); GSwdrawline(x, y+(2*ht/3), x+wd, y+(2*ht/3)); /* show moves */ for (i=0; i<3; i++) for (j=0; j<3; j++) show_move(i, j); } void show_move(int move_r, int move_c) { int x, y, wd, ht; int bx, by, bwd, bht; GSColor col; GSgetdragareaspecs(GAME_WIND, GAME_DRAG, &x, &y, &wd, &ht, NULL, &col); bx = x + (wd/3)*move_c + INSET; by = y + (ht/3)*move_r + INSET; bwd = wd/3 - 2*INSET; bht = ht/3 - 2*INSET; GSsetcurrentnamedwindow(GAME_WIND); GSsetcolor(GSconvertcolor("black")); if (board[move_r][move_c] == X) { GSwdrawline(bx, by, bx+bwd, by+bht); GSwdrawline(bx+bwd, by, bx, by+bht); } else if (board[move_r][move_c] == O) GSwdrawellipse(bx, by, bwd, bht); else { GSsetcolor(col); GSwfillrect(bx-1, by-1, bwd+2, bht+2); } } [...] void get_move(int mouse_x, int mouse_y, int *move_r, int *move_c) { int wd, ht; GSgetdragareaspecs(GAME_WIND, GAME_DRAG, NULL, NULL, &wd, &ht, NULL, NULL); *move_r = mouse_y / (ht/3); *move_c = mouse_x / (wd/3); } bool check_win(move_r, move_c) { int i, j; if ((board[0][move_c] == board[1][move_c]) && (board[1][move_c] == board[2][move_c]) && (board[0][move_c] != PNONE)) return TRUE; if ((board[move_r][0] == board[move_r][1]) && (board[move_r][1] == board[move_r][2]) && (board[move_r][0] != PNONE)) return TRUE; if (move_r == move_c) { if ((board[0][0] == board[1][1]) && (board[1][1] == board[2][2]) && (board[0][0] != PNONE)) return TRUE; } if (move_r == 2-move_c) { if ((board[0][2] == board[1][1]) && (board[1][1] == board[2][0]) && (board[0][2] != PNONE)) return TRUE; } return FALSE; } [...]