From 6ab989174bca508e8689dec344f383960f7304c6 Mon Sep 17 00:00:00 2001 From: Julia Lange Date: Tue, 16 Jul 2024 01:46:42 -0700 Subject: [PATCH] Add diagonal win checks Adds diagonal win checking, and tests to go along with them --- connect4.c | 64 ++++++++++++++++++++++++++++++++ test_connect4.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) diff --git a/connect4.c b/connect4.c index 0b5c52d..0684ed6 100644 --- a/connect4.c +++ b/connect4.c @@ -74,12 +74,76 @@ int check_for_win_vertical(struct Board *board, size_t pos_i, size_t pos_j) return 0; } +int check_for_win_lr_diagonal(struct Board *board, size_t pos_i, size_t pos_j) +{ + enum Tile current_player = board->next_player * -1; + char in_a_row = 1; + // Down-right + size_t npos_i = pos_i + 1; + size_t npos_j = pos_j + 1; + while (npos_i < board->width && npos_j < board->height && + IDX(npos_i, npos_j, board) == current_player) { + in_a_row++; + npos_i++; + npos_j++; + if (in_a_row >= 4) + return 1; + } + // Up-left + npos_i = pos_i - 1; + npos_j = pos_j - 1; + while (npos_i < board->width && npos_j < board->height && + IDX(npos_i, npos_j, board) == current_player) { + in_a_row++; + npos_i--; + npos_j--; + if (in_a_row >= 4) + return 1; + } + + return 0; +} + +int check_for_win_rl_diagonal(struct Board *board, size_t pos_i, size_t pos_j) +{ + enum Tile current_player = board->next_player * -1; + char in_a_row = 1; + // Down-left + size_t npos_i = pos_i - 1; + size_t npos_j = pos_j + 1; + while (npos_i < board->width && npos_j < board->height && + IDX(npos_i, npos_j, board) == current_player) { + in_a_row++; + npos_i--; + npos_j++; + if (in_a_row >= 4) + return 1; + } + // Up-right + npos_i = pos_i + 1; + npos_j = pos_j - 1; + while (npos_i < board->width && npos_j < board->height && + IDX(npos_i, npos_j, board) == current_player) { + in_a_row++; + npos_i++; + npos_j--; + if (in_a_row >= 4) + return 1; + } + + return 0; +} + int check_for_win(struct Board *board, size_t pos_i, size_t pos_j) { if (check_for_win_horizontal(board, pos_i, pos_j)) return 1; if (check_for_win_vertical(board, pos_i, pos_j)) return 1; + if (check_for_win_lr_diagonal(board, pos_i, pos_j)) + return 1; + if (check_for_win_rl_diagonal(board, pos_i, pos_j)) + return 1; return 0; } diff --git a/test_connect4.c b/test_connect4.c index a49b7e2..cc911a9 100644 --- a/test_connect4.c +++ b/test_connect4.c @@ -49,12 +49,109 @@ void test_middle_horizontal_win(void) free_board(board); } +void test_ul_diagonal_win(void) +{ + struct Board *board = make_board(4,4); + /* X 9 + * OX 87 + * OOX 465 + * OXOX 0123 + */ + int positions[] = {0, 1, 2, 3, 0, 2, 1, 1, 0}; + drop_series(board, positions, 9); + int output = drop_tile(board, 0); + assert(output == 1 && "Upper Left Diagonal Win"); + free_board(board); +} + +void test_ur_diagonal_win(void) +{ + struct Board *board = make_board(4,4); + /* X 9 + * XO 78 + * XOO 564 + * XOXO 3210 + */ + int positions[] = {3, 2, 1, 0, 3, 1, 2, 2, 3}; + drop_series(board, positions, 9); + int output = drop_tile(board, 3); + assert(output == 1 && "Upper Right Diagonal Win"); + free_board(board); +} + + +void test_lr_diagonal_win(void) +{ + struct Board *board = make_board(4,4); + /* X 7 + * OX 69 + * OOX 485 + * OXOX 0123 + */ + int positions[] = {0, 1, 2, 3, 0, 2, 0, 0, 1}; + drop_series(board, positions, 9); + int output = drop_tile(board, 1); + assert(output == 1 && "Left-Right Middle Diagonal Win"); + free_board(board); +} + +void test_rl_diagonal_win(void) +{ + struct Board *board = make_board(4,4); + /* X 7 + * XO 96 + * XOO 584 + * XOXO 3210 + */ + int positions[] = {3, 2, 1, 0, 3, 1, 3, 3, 2}; + drop_series(board, positions, 9); + int output = drop_tile(board, 2); + assert(output == 1 && "Right-Left Middle Diagonal Win"); + free_board(board); +} + +void test_br_diagonal_win(void) +{ + struct Board *board = make_board(4,4); + /* XO 38 + * OXO 27A + * XXX 159 + * OOOX 046B + */ + int positions[] = {0, 0, 0, 0, 1, 1, 2, 1, 1, 2, 2}; + drop_series(board, positions, 11); + int output = drop_tile(board, 3); + assert(output == 1 && "Bottom-Right Diagonal Win"); + free_board(board); +} + +void test_bl_diagonal_win(void) +{ + struct Board *board = make_board(4,4); + /* OX 83 + * OXO A72 + * XOO 951 + * XOXO B640 + */ + int positions[] = {3, 3, 3, 3, 2, 2, 3, 2, 2, 1, 1}; + drop_series(board, positions, 11); + int output = drop_tile(board, 0); + assert(output == 1 && "Bottom-left Diagonal Win"); + free_board(board); +} + int main(int argc, char *argv[]) { test_vertical_win(); test_left_horizontal_win(); test_right_horizontal_win(); test_middle_horizontal_win(); + test_ul_diagonal_win(); + test_bl_diagonal_win(); + test_rl_diagonal_win(); + test_ur_diagonal_win(); + test_br_diagonal_win(); + test_lr_diagonal_win(); return EXIT_SUCCESS; }