tictactoe

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 586c25883c6322d0fd0e0fd47305f074dadc6837
parent 106ccb207c60f0b4f26af0aa3772e44a96750ea2
Author: Wilson Gheen <wilson@wilsonrgheen.com>
Date:   Sun, 18 Dec 2022 08:38:08 -0600

WIP -- refactor to prevent repeating code in blocking/non-blocking "AIs"

Diffstat:
Mtictactoe.c | 2+-
Mtictactoe.h | 62++++++++++++++++++++++++++++----------------------------------
2 files changed, 29 insertions(+), 35 deletions(-)

diff --git a/tictactoe.c b/tictactoe.c @@ -33,7 +33,7 @@ char play(char (*get_move)(char*, char), char (*get_move_2)(char*, char)) { print_board(board); for(int turns=0; !winner && turns < 9; turns++) { winner = (turns & 1) ? get_move(board, player) : get_move_2(board, player); - player = (player == 'O' ? 'X' : 'O'); + player = OPPONENT; if(SIDE_BY_SIDE) print_board_offset(board, turns * 10, 0, 0); else diff --git a/tictactoe.h b/tictactoe.h @@ -3,6 +3,8 @@ #include <string.h> #include <time.h> +/*#define NO_PRINT_BOARD*/ + #define SCRATCH_BOARD "XXOOOXXOX" #define X_WINS_COLUMN "XXOXOOXOX" #define X_WINS_DIAG "XOO XOOXX" @@ -12,7 +14,8 @@ #define O_WINS_ROW " XXXOXOOO" #define scase(s1, s2) if (!strcmp(s1, s2)) -/*#define NO_PRINT_BOARD*/ + +#define OPPONENT (player == 'O' ? 'X' : 'O') /*typedef void (*board_fn)(char *, char);*/ static char the_desired_board[32]; @@ -137,43 +140,34 @@ char get_random_move(char *board, char player) { board[legal_moves[get_rand(lm_ind)]] = player; return get_winner_or_winning_moves(board, NULL); } -static char try_get_winning_move(char *board, char player) { - char winning_moves[9] = ""; - int my_winning_moves[5]; - int mwm_ind = 0; - get_winner_or_winning_moves(board, winning_moves); - for(int i=0; i < 9; i++) - if((winning_moves[i] & player) == player) - my_winning_moves[mwm_ind++] = i; - if(mwm_ind) { - board[my_winning_moves[get_rand(mwm_ind)]] = player; +static char try_make_winning_move(char *board, char player, _Bool block_opponent) { + char all_winning_moves[9] = ""; + get_winner_or_winning_moves(board, all_winning_moves); + int my_winning_moves_inds[5], his_winning_moves_inds[5]; + int mwm_ind_ind = 0, hwm_ind_ind = 0; + for(int i=0; i < 9; i++) { + /* Get all possible winning moves, including optionally the opponent's; + * add indices of each to an array ... */ + if((all_winning_moves[i] & player) == player) + my_winning_moves_inds[mwm_ind_ind++] = i; + else if(block_opponent && all_winning_moves[i] == OPPONENT) + his_winning_moves_inds[hwm_ind_ind++] = i; + } + /* ...then choose one at random, mine if possible, else the opponent's (if opted for) */ + if(mwm_ind_ind) { + board[my_winning_moves_inds[get_rand(mwm_ind_ind)]] = player; return player; } - return 0; + if(hwm_ind_ind) { + board[his_winning_moves_inds[get_rand(hwm_ind_ind)]] = player; + /* N.B. This will not be reached if the move is a winning move for both players */ + return 0; + } + return get_random_move(board, player); } char get_winning_move_else_random(char *board, char player) { - char winner = try_get_winning_move(board, player); - if(winner) - return winner; - else - return get_random_move(board, player); + return try_make_winning_move(board, player, 0); } char get_winning_move_else_block_else_random(char *board, char player) { - char winner = try_get_winning_move(board, player); - if(winner) return winner; - char winning_moves[9] = ""; - int his_winning_moves[5]; - int hwm_ind = 0; - char opponent = (player == 'O' ? 'X' : 'O'); - get_winner_or_winning_moves(board, winning_moves); - for(int i=0; i < 9; i++) - if(winning_moves[i] == opponent) - his_winning_moves[hwm_ind++] = i; - if(hwm_ind) { - board[his_winning_moves[get_rand(hwm_ind)]] = player; - /*N.B. This will not be reached if the move is a winning move for both players */ - return 0; - } - else - return get_random_move(board, player); + return try_make_winning_move(board, player, 1); }