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:
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);
}