From fb7979ab8fb9131e4fb369ccdcbcdccd15d0413c Mon Sep 17 00:00:00 2001 From: Anthony <bouillant.anthony@gmail.com> Date: Fri, 4 Apr 2025 12:01:24 +0200 Subject: [PATCH] Rework column index --- puissance4.c | 4 +++- src/board/test_board.c | 18 ++++++++--------- src/computer/computer.c | 14 ++++++------- src/computer/test_computer.c | 18 ++++++++--------- src/game/game.c | 4 ++-- src/game/test_game.c | 39 ++++++++++++++++++------------------ src/test_puissance4.c | 1 - src/test_puissance4.h | 5 ++--- 8 files changed, 51 insertions(+), 52 deletions(-) diff --git a/puissance4.c b/puissance4.c index 45b15bb..3792793 100644 --- a/puissance4.c +++ b/puissance4.c @@ -47,12 +47,14 @@ int main(int argc, char const* argv[]) { struct coordinate empty_slot; while (true) { + // selected_column starts at 0 int selected_column = get_selected_column(game_mode, current_turn, col_count, row_count, board); if (!is_valid_column(selected_column, col_count)) { + printf("\nInvalid column number. Please try again.\n"); continue; } - empty_slot = find_empty_slot(selected_column - 1, row_count, board); + empty_slot = find_empty_slot(selected_column, row_count, board); place_token(current_turn % 2, empty_slot, board); print_board(row_count, col_count, board); diff --git a/src/board/test_board.c b/src/board/test_board.c index 4d38562..b92be46 100644 --- a/src/board/test_board.c +++ b/src/board/test_board.c @@ -5,43 +5,43 @@ void test_destroy_board() { int cols = 7; int** board = create_board(rows, cols); if (board == NULL) { - fprintf(stderr, RED "test_destroy_board: FAILED\n" RESET); + fprintf(stderr, "test_destroy_board: FAILED\n"); exit(EXIT_FAILURE); } fill_board(rows, cols, board); - assert(destroy_board(rows, board) == EXIT_SUCCESS && RED "test_destroy_board: FAILED\n" RESET); - printf(GREEN "test_destroy_board: PASSED\n" RESET); + assert(destroy_board(rows, board) == EXIT_SUCCESS && "test_destroy_board: FAILED\n"); + PRINT_SUCCESS("test_destroy_board: PASSED"); } void test_create_board() { int rows = 6; int cols = 7; int** board = create_board(rows, cols); - assert(board != NULL && RED "Board creation failed\n" RESET); + assert(board != NULL && "Board creation failed\n"); for (int i = 0; i < rows; i++) { - assert(board[i] != NULL && RED "Row allocation failed\n" RESET); + assert(board[i] != NULL && "Row allocation failed\n"); } destroy_board(rows, board); - printf(GREEN "test_create_board: PASSED\n" RESET); + PRINT_SUCCESS("test_create_board: PASSED"); } void test_fill_board() { int rows = 6; int cols = 7; int** board = create_board(rows, cols); - assert(board != NULL && RED "Board creation failed\n" RESET); + assert(board != NULL && "Board creation failed\n"); fill_board(rows, cols, board); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { - assert(board[i][j] == EMPTY && RED "test_fill_board: FAILED at board[%d][%d]\n" RESET); + assert(board[i][j] == EMPTY && "test_fill_board: FAILED at board[%d][%d]\n"); } } destroy_board(rows, board); - printf(GREEN "test_fill_board: PASSED\n" RESET); + PRINT_SUCCESS("test_fill_board: PASSED"); } diff --git a/src/computer/computer.c b/src/computer/computer.c index 6f22569..1fd838a 100644 --- a/src/computer/computer.c +++ b/src/computer/computer.c @@ -6,12 +6,12 @@ int select_smart_column(int number_of_columns, int number_of_rows, int** board) // 1. Check if the AI can win in the next move, if so, play it for (int col = 0; col < number_of_columns; col++) { - if (!is_column_full(col + 1, number_of_rows, board)) { + if (!is_column_full(col, number_of_rows, board)) { struct coordinate temp_coordinate = find_empty_slot(col, number_of_rows, board); board[temp_coordinate.x][temp_coordinate.y] = PLAYER2; if (does_player_win(temp_coordinate, number_of_rows, number_of_columns, board)) { - robot_selected_column = col + 1; + robot_selected_column = col; board[temp_coordinate.x][temp_coordinate.y] = EMPTY; break; } @@ -26,13 +26,13 @@ int select_smart_column(int number_of_columns, int number_of_rows, int** board) // 2. Check if the player can win in the next move, if so, block it for (int col = 0; col < number_of_columns; col++) { - if (!is_column_full(col + 1, number_of_rows, board)) { + if (!is_column_full(col, number_of_rows, board)) { struct coordinate temp_coordinate = find_empty_slot(col, number_of_rows, board); // Check if the player can win in the next move board[temp_coordinate.x][temp_coordinate.y] = PLAYER1; if (does_player_win(temp_coordinate, number_of_rows, number_of_columns, board)) { - robot_selected_column = col + 1; + robot_selected_column = col; board[temp_coordinate.x][temp_coordinate.y] = EMPTY; break; } @@ -51,15 +51,15 @@ int select_smart_column(int number_of_columns, int number_of_rows, int** board) int select_random_column(int number_of_columns, int number_of_rows, int** board) { int robot_selected_column = -999; do { - robot_selected_column = rand() % number_of_columns + 1; + robot_selected_column = rand() % number_of_columns; } while (is_column_full(robot_selected_column, number_of_rows, board)); return robot_selected_column; } -bool is_column_full(int col, int rows, int** board) { +bool is_column_full(int x, int rows, int** board) { for (int i = 0; i < rows; i++) { - if (board[i][col - 1] == EMPTY) { + if (board[i][x] == EMPTY) { return false; } } diff --git a/src/computer/test_computer.c b/src/computer/test_computer.c index c23e4ce..de37667 100644 --- a/src/computer/test_computer.c +++ b/src/computer/test_computer.c @@ -5,16 +5,16 @@ void test_is_column_full() { int** board = setup_board(rows, cols); // An empty column should not be considered full - assert(is_column_full(1, rows, board) == false && RED "test_is_column_full: FAILED - column should not be full\n" RESET); + assert(is_column_full(1, rows, board) == false && "test_is_column_full: FAILED - column should not be full\n"); // Fill a column completely and test again for (int i = 0; i < rows; i++) { board[i][0] = PLAYER1; } - assert(is_column_full(1, rows, board) == true && RED "test_is_column_full: FAILED - column should be full\n" RESET); + assert(is_column_full(0, rows, board) == true && "test_is_column_full: FAILED - column should be full\n"); destroy_board(rows, board); - printf(GREEN "test_is_column_full: PASSED\n" RESET); + PRINT_SUCCESS("test_is_column_full: PASSED"); } void test_select_smart_column() { @@ -26,17 +26,17 @@ void test_select_smart_column() { board[4][0] = PLAYER2; board[3][0] = PLAYER2; - assert(select_smart_column(cols, rows, board) == 1 && RED "test_select_smart_column: FAILED - AI should select column 1\n" RESET); + assert(select_smart_column(cols, rows, board) == 0 && "test_select_smart_column: FAILED - AI should select column 0\n"); reset_board(rows, cols, board); // Simulate a situation where the player can win on the next move board[5][1] = PLAYER1; board[4][1] = PLAYER1; board[3][1] = PLAYER1; - assert(select_smart_column(cols, rows, board) == 2 && RED "test_select_smart_column: FAILED - Player should select column 2\n" RESET); + assert(select_smart_column(cols, rows, board) == 1 && "test_select_smart_column: FAILED - Player should select column 1\n"); destroy_board(rows, board); - printf(GREEN "test_select_smart_column: PASSED\n" RESET); + PRINT_SUCCESS("test_select_smart_column: PASSED"); } void test_select_random_column() { @@ -46,7 +46,7 @@ void test_select_random_column() { // Select a random column on an empty board int col = select_random_column(cols, rows, board); - assert(col == 2 && RED "test_select_random_column: FAILED - Expected column 2\n" RESET); + assert(col == 1 && "test_select_random_column: FAILED - Expected column 1\n"); // Fill all columns except one for (int j = 0; j < cols - 1; j++) { @@ -57,8 +57,8 @@ void test_select_random_column() { // The AI should select the only non-full column, which is column 7 (the last one) col = select_random_column(cols, rows, board); - assert(col == 7 && RED "test_select_random_column: FAILED - Expected column 7\n" RESET); + assert(col == 6 && "test_select_random_column: FAILED - Expected column 6\n"); destroy_board(rows, board); - printf(GREEN "test_select_random_column: PASSED\n" RESET); + PRINT_SUCCESS("test_select_random_column: PASSED"); } diff --git a/src/game/game.c b/src/game/game.c index 7c0d6a5..ea55511 100644 --- a/src/game/game.c +++ b/src/game/game.c @@ -22,14 +22,14 @@ struct coordinate find_empty_slot(int x, int rows, int** board) { } bool is_valid_column(int column, int col_count) { - return column >= 1 && column <= col_count; + return column >= 0 && column < col_count; } int get_player_input() { int column; printf("\nColumn number? (starts at 1):"); scanf("%d", &column); - return column; + return column - 1; // Adjust for 0-based indexing } bool is_board_full(int current_turn, int row_count, int col_count) { diff --git a/src/game/test_game.c b/src/game/test_game.c index 30d9631..05dea89 100644 --- a/src/game/test_game.c +++ b/src/game/test_game.c @@ -7,16 +7,16 @@ void test_place_token() { // Player1 struct coordinate coord = { 2, 3 }; place_token(0, coord, board); - assert(board[2][3] == PLAYER1 && RED "test_place_token: FAILED - Expected PLAYER1 at board[2][3]\n" RESET); + assert(board[2][3] == PLAYER1 && "test_place_token: FAILED - Expected PLAYER1 at board[2][3]\n"); // Player2 coord.x = 4; coord.y = 5; place_token(1, coord, board); - assert(board[4][5] == PLAYER2 && RED "test_place_token: FAILED - Expected PLAYER2 at board[4][5]\n" RESET); + assert(board[4][5] == PLAYER2 && "test_place_token: FAILED - Expected PLAYER2 at board[4][5]\n"); destroy_board(rows, board); - printf(GREEN "test_place_token: PASSED\n" RESET); + PRINT_SUCCESS("test_place_token: PASSED"); } void test_find_empty_slot() { @@ -26,34 +26,33 @@ void test_find_empty_slot() { // Search for an empty slot in a column board[5][2] = PLAYER1; struct coordinate coord = find_empty_slot(2, rows, board); - assert(coord.x == 4 && coord.y == 2 && RED "test_find_empty_slot: FAILED - Expected coord (4, 2)\n" RESET); + assert(coord.x == 4 && coord.y == 2 && "test_find_empty_slot: FAILED - Expected coord (4, 2)\n"); // Search for an empty slot in a column with multiple tokens board[4][2] = PLAYER2; coord = find_empty_slot(2, rows, board); - assert(coord.x == 3 && coord.y == 2 && RED "test_find_empty_slot: FAILED - Expected coord (3, 2)\n" RESET); + assert(coord.x == 3 && coord.y == 2 && "test_find_empty_slot: FAILED - Expected coord (3, 2)\n"); destroy_board(rows, board); - printf(GREEN "test_find_empty_slot: PASSED\n" RESET); + PRINT_SUCCESS("test_find_empty_slot: PASSED"); } void test_is_valid_column() { int cols = 7; - assert(is_valid_column(1, cols) == true && RED "test_is_valid_column: FAILED - Column 1 should be valid\n" RESET); - assert(is_valid_column(7, cols) == true && RED "test_is_valid_column: FAILED - Column 7 should be valid\n" RESET); - - assert(is_valid_column(0, cols) == false && RED "test_is_valid_column: FAILED - Column 0 should be invalid\n" RESET); - assert(is_valid_column(8, cols) == false && RED "test_is_valid_column: FAILED - Column 8 should be invalid\n" RESET); - printf(GREEN "test_is_valid_column: PASSED\n" RESET); + assert(is_valid_column(0, cols) == true && "test_is_valid_column: FAILED - Column 1 should be valid\n"); + assert(is_valid_column(6, cols) == true && "test_is_valid_column: FAILED - Column 7 should be valid\n"); + assert(is_valid_column(-1, cols) == false && "test_is_valid_column: FAILED - Column 0 should be invalid\n"); + assert(is_valid_column(7, cols) == false && "test_is_valid_column: FAILED - Column 8 should be invalid\n"); + PRINT_SUCCESS("test_is_valid_column: PASSED"); } void test_is_board_full() { int rows = 6, cols = 7; - assert(is_board_full(41, rows, cols) == true && RED "test_is_board_full: FAILED - Board should be full\n" RESET); - assert(is_board_full(40, rows, cols) == false && RED "test_is_board_full: FAILED - Board should not be full\n" RESET); - printf(GREEN "test_is_board_full: PASSED\n" RESET); + assert(is_board_full(41, rows, cols) == true && "test_is_board_full: FAILED - Board should be full\n"); + assert(is_board_full(40, rows, cols) == false && "test_is_board_full: FAILED - Board should not be full\n"); + PRINT_SUCCESS("test_is_board_full: PASSED"); } void test_does_player_win() { @@ -66,7 +65,7 @@ void test_does_player_win() { board[5][2] = PLAYER1; board[5][3] = PLAYER1; struct coordinate coord = { 5, 3 }; - assert(does_player_win(coord, rows, cols, board) == true && RED "test_does_player_win: FAILED - Horizontal win should be detected\n" RESET); + assert(does_player_win(coord, rows, cols, board) == true && "test_does_player_win: FAILED - Horizontal win should be detected\n"); // Test vertical win fill_board(rows, cols, board); @@ -76,7 +75,7 @@ void test_does_player_win() { board[2][2] = PLAYER2; coord.x = 2; coord.y = 2; - assert(does_player_win(coord, rows, cols, board) == true && RED "test_does_player_win: FAILED - Vertical win should be detected\n" RESET); + assert(does_player_win(coord, rows, cols, board) == true && "test_does_player_win: FAILED - Vertical win should be detected\n"); // Test diagonal win (left to right) fill_board(rows, cols, board); @@ -86,7 +85,7 @@ void test_does_player_win() { board[2][3] = PLAYER1; coord.x = 2; coord.y = 3; - assert(does_player_win(coord, rows, cols, board) == true && RED "test_does_player_win: FAILED - Left-to-right diagonal win should be detected\n" RESET); + assert(does_player_win(coord, rows, cols, board) == true && "test_does_player_win: FAILED - Left-to-right diagonal win should be detected\n"); // Test diagonal win (right to left) fill_board(rows, cols, board); @@ -96,8 +95,8 @@ void test_does_player_win() { board[2][0] = PLAYER2; coord.x = 2; coord.y = 0; - assert(does_player_win(coord, rows, cols, board) == true && RED "test_does_player_win: FAILED - Right-to-left diagonal win should be detected\n" RESET); + assert(does_player_win(coord, rows, cols, board) == true && "test_does_player_win: FAILED - Right-to-left diagonal win should be detected\n"); destroy_board(rows, board); - printf(GREEN "test_does_player_win: PASSED\n" RESET); + PRINT_SUCCESS("test_does_player_win: PASSED"); } diff --git a/src/test_puissance4.c b/src/test_puissance4.c index e3ee464..43facc3 100644 --- a/src/test_puissance4.c +++ b/src/test_puissance4.c @@ -18,7 +18,6 @@ int main() { test_is_board_full(); test_does_player_win(); - printf(GREEN "All tests passed successfully!\n" RESET); return EXIT_SUCCESS; } diff --git a/src/test_puissance4.h b/src/test_puissance4.h index c44495a..16516de 100644 --- a/src/test_puissance4.h +++ b/src/test_puissance4.h @@ -11,9 +11,8 @@ #include "game/test_game.h" #include "computer/test_computer.h" -#define GREEN "\033[1;32m" -#define RED "\033[1;31m" -#define RESET "\033[0m" +// https://stackoverflow.com/questions/1961209/making-some-text-in-printf-appear-in-green-and-red +#define PRINT_SUCCESS(msg) printf("\033[32;1m%s\033[0m\n", msg) int** setup_board(int rows, int cols); void reset_board(int rows, int cols, int** board); -- GitLab