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