diff --git a/Makefile b/Makefile
index f8649732e840c9546f7bdbdcc11c1e239bf1fc11..6d85b74615d772d09c4e77a3011e49e0790fba21 100644
--- a/Makefile
+++ b/Makefile
@@ -3,15 +3,16 @@ CFLAGS  = -g -Wall -Wextra -Wpedantic
 LDLIBS  = -lm
 LDFLAGS = -fsanitize=address -fsanitize=leak
 
-puissance4: puissance4.c src/board.o
+puissance4: puissance4.c src/board.o src/game.o
 	$(CC) $(CFLAGS) $^ -o $@ $(LDLIBS) $(LDFLAGS)
 
 board.o: src/board.h
+game.o: src/game.h
 
 clean:
 	@echo "this rule must clean everything up (including candidate files in testbed)"
 	$(MAKE) -C testbed clean
-	$(RM) -f puissance4 *.o *.cand
+	$(RM) -rf puissance4 *.o *.cand
 
 run: puissance4 
 	./$< 3 5 6
diff --git a/puissance4.c b/puissance4.c
index 9e91dbc364e1b5a22c45e941c1876046539ae704..85b0e6b03b65c3836192ea7c11d062aeb817297e 100644
--- a/puissance4.c
+++ b/puissance4.c
@@ -1,14 +1,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
-
+#include "src/game.h"
 #include "src/board.h"
 
 #define AI_SEED 0
 #define MIN_COLUMN 4
 #define MIN_ROW 4
 
-bool does_player_win(int col, int row, int rows, int cols, int** board);
 void flush_input();
 bool is_valid_game_mode(int game_mode);
 bool is_valid_board_size(int rows, int cols);
@@ -16,21 +15,6 @@ bool is_column_full(int col, int rows, int** board);
 int select_random_column(int number_of_columns, int number_of_rows, int** board);
 int select_smart_column(int number_of_columns, int number_of_rows, int** board);
 
-struct coordinate {
-    int x;
-    int y;
-};
-
-enum GAME_MODE {
-    PLAYER_VS_RANDOM_AI = 1,
-    PLAYER_VS_SMART_AI = 2,
-    PLAYER_VS_PLAYER = 3
-};
-
-
-void place_token(int player, struct coordinate coordinate, int** board);
-struct coordinate find_empty_slot(int col, int rows, int** board);
-
 int main(int argc, char const* argv[]) {
     if (argc != 4 || !is_valid_game_mode(atoi(argv[1])) || !is_valid_board_size(atoi(argv[2]), atoi(argv[3]))) {
         printf("Usage: %s <mode> <row> <col>\n", argv[0]);
@@ -41,66 +25,11 @@ int main(int argc, char const* argv[]) {
         return EXIT_FAILURE;
     }
 
-    int game_mode = atoi(argv[1]);
+    enum GAME_MODE game_mode = atoi(argv[1]);
     int rows = atoi(argv[2]);
     int cols = atoi(argv[3]);
     srand(AI_SEED);
-
-    int** board = create_board(rows, cols);
-    if (board == NULL) {
-        fprintf(stderr, "Error: Unable to allocate memory for the board.\n");
-        return EXIT_FAILURE;
-    }
-
-    fill_board(rows, cols, board);
-    printf("Board size is %dx%d (rows x col)", rows, cols);
-    print_board(rows, cols, board);
-
-    int player_selected_column, player;
-    struct coordinate coordinate;
-
-    while (true) {
-        if (game_mode == PLAYER_VS_PLAYER || player % 2 == 0) {
-            printf("\nColumn number? (starts at 1):");
-            scanf("%d", &player_selected_column);
-        } else {
-            if (game_mode == PLAYER_VS_RANDOM_AI) {
-                player_selected_column = select_random_column(cols, rows, board);
-            } else if (game_mode == PLAYER_VS_SMART_AI) {
-                player_selected_column = select_smart_column(cols, rows, board);
-            }
-        }
-
-        if (player_selected_column < 1 || player_selected_column > cols) {
-            continue;
-        }
-
-        coordinate = find_empty_slot(player_selected_column, rows, board);
-        if (coordinate.x != -1 && coordinate.y != -1) {
-            place_token(player % 2, coordinate, board);
-        }
-
-        print_board(rows, cols, board);
-        if (does_player_win(coordinate.x, coordinate.y, rows, cols, board)) {
-            if (game_mode == PLAYER_VS_PLAYER) {
-                printf("\nPlayer %s won!\n", player % 2 == 0 ? "one" : "two");
-            } else {
-                printf("\n%s won!\n", player % 2 == 0 ? "Player one" : "Computer");
-            }
-            break;
-        }
-        if (player + 1 == rows * cols) {
-            printf("\nIt is a draw.\n");
-            break;
-        }
-
-        player++;
-    }
-    if (destroy_board(rows, board) == EXIT_FAILURE) {
-        fprintf(stderr, "Error: Unable to free memory for the board.\n");
-        return EXIT_FAILURE;
-    }
-    return EXIT_SUCCESS;
+    return play_game(game_mode, rows, cols);
 }
 
 bool is_valid_game_mode(int game_mode) {
@@ -126,10 +55,10 @@ int select_smart_column(int number_of_columns, int number_of_rows, int** board)
     // 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)) {
-            struct coordinate temp_coordinate = find_empty_slot(col + 1, 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.x, temp_coordinate.y, number_of_rows, number_of_columns, board)) {
+            if (does_player_win(temp_coordinate, number_of_rows, number_of_columns, board)) {
                 robot_selected_column = col + 1;
                 board[temp_coordinate.x][temp_coordinate.y] = EMPTY;
                 break;
@@ -146,11 +75,11 @@ int select_smart_column(int number_of_columns, int number_of_rows, int** board)
     // 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)) {
-            struct coordinate temp_coordinate = find_empty_slot(col + 1, 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.x, temp_coordinate.y, number_of_rows, number_of_columns, board)) {
+            if (does_player_win(temp_coordinate, number_of_rows, number_of_columns, board)) {
                 robot_selected_column = col + 1;
                 board[temp_coordinate.x][temp_coordinate.y] = EMPTY;
                 break;
@@ -176,73 +105,7 @@ bool is_column_full(int col, int rows, int** board) {
     return true;
 }
 
-struct coordinate find_empty_slot(int col, int rows, int** board) {
-    struct coordinate coordinate = { -1, -1 };
-    for (int i = rows - 1; i >= 0; i--) {
-        if (board[i][col - 1] == EMPTY) {
-            coordinate.x = i;
-            coordinate.y = col - 1;
-            break;
-        }
-    }
-    return coordinate;
-}
-
-void place_token(int player, struct coordinate coordinate, int** board) {
-    if (coordinate.x != -1 && coordinate.y != -1) {
-        board[coordinate.x][coordinate.y] = player == 0 ? PLAYER1 : PLAYER2;
-    }
-}
-
 void flush_input() {
     int c;
     while ((c = getchar()) != '\n' && c != EOF);
 }
-
-bool does_player_win(int row, int col, int rows, int cols, int** board) {
-    int current_piece = board[row][col];
-    for (int i = 0; i < rows - 3; i++) {
-
-        if (board[i][col] == current_piece
-            && board[i + 1][col] == current_piece
-            && board[i + 2][col] == current_piece
-            && board[i + 3][col] == current_piece)
-        {
-            return true;
-        }
-
-    }
-
-    for (int i = 0; i < cols - 3; i++) {
-        if (board[row][i] == current_piece
-            && board[row][i + 1] == current_piece
-            && board[row][i + 2] == current_piece
-            && board[row][i + 3] == current_piece) {
-            return true;
-        }
-    }
-
-    for (int i = 0; i < rows - 3; i++) {
-        for (int j = 0; j < cols - 3; j++) {
-            if (board[i][j] == current_piece &&
-                board[i + 1][j + 1] == current_piece &&
-                board[i + 2][j + 2] == current_piece &&
-                board[i + 3][j + 3] == current_piece) {
-                return true;
-            }
-        }
-    }
-
-    // Diagonale droite à gauche
-    for (int i = 0; i < rows - 3; i++) {
-        for (int j = 3; j < cols; j++) {
-            if (board[i][j] == current_piece &&
-                board[i + 1][j - 1] == current_piece &&
-                board[i + 2][j - 2] == current_piece &&
-                board[i + 3][j - 3] == current_piece) {
-                return true;
-            }
-        }
-    }
-    return false;
-}
diff --git a/src/board.c b/src/board.c
index 4072590dc6d363adef67282e906b9cacc9be070b..f8d640fc251f252a81bf7bbdbd1717c9f1717e4a 100644
--- a/src/board.c
+++ b/src/board.c
@@ -1,6 +1,6 @@
-#include "board.h"
 #include <stdlib.h>
 #include <stdio.h>
+#include "board.h"
 
 void fill_board(int rows, int cols, int** board) {
     for (int i = 0; i < rows; i++) {
diff --git a/src/board.h b/src/board.h
index 38ea7654c4bfb02080e145567adf7defdcfc052d..588bd0dca6a16cf4c83c9ce3ea94b7bd79a4ba32 100644
--- a/src/board.h
+++ b/src/board.h
@@ -1,4 +1,5 @@
 #ifndef _BOARD_H_
+#define _BOARD_H_
 
 enum BOARD_STATE {
     EMPTY = 0,
diff --git a/src/game.c b/src/game.c
new file mode 100644
index 0000000000000000000000000000000000000000..b80875a4cf01a921d8426d1fa4b8b073e5512be7
--- /dev/null
+++ b/src/game.c
@@ -0,0 +1,133 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "game.h"
+
+void place_token(int player, struct coordinate coordinate, int** board) {
+    if (coordinate.x != -1 && coordinate.y != -1) {
+        board[coordinate.x][coordinate.y] = player == 0 ? PLAYER1 : PLAYER2;
+    }
+}
+
+struct coordinate find_empty_slot(int x, int rows, int** board) {
+    struct coordinate coordinate = { -1, -1 };
+    if (x < 0 || x > rows) {
+        return coordinate;
+    }
+    for (int i = rows - 1; i >= 0; i--) {
+        if (board[i][x] == EMPTY) {
+            coordinate.x = i;
+            coordinate.y = x;
+            break;
+        }
+    }
+    return coordinate;
+}
+
+int play_game(enum GAME_MODE game_mode, int rows, int cols) {
+    int** board = create_board(rows, cols);
+    if (board == NULL) {
+        fprintf(stderr, "Error: Unable to allocate memory for the board.\n");
+        return EXIT_FAILURE;
+    }
+
+    fill_board(rows, cols, board);
+    printf("Board size is %dx%d (rows x col)", rows, cols);
+    print_board(rows, cols, board);
+
+    int player_selected_column, player = 0;
+    struct coordinate coordinate;
+
+    while (true) {
+        if (game_mode == PLAYER_VS_PLAYER || player % 2 == 0) {
+            printf("\nColumn number? (starts at 1):");
+            scanf("%d", &player_selected_column);
+        } else {
+            if (game_mode == PLAYER_VS_RANDOM_AI) {
+                player_selected_column = select_random_column(cols, rows, board);
+            } else if (game_mode == PLAYER_VS_SMART_AI) {
+                player_selected_column = select_smart_column(cols, rows, board);
+            }
+        }
+
+        if (player_selected_column < 1 || player_selected_column > cols) {
+            continue;
+        }
+
+        coordinate = find_empty_slot(player_selected_column - 1, rows, board);
+        place_token(player % 2, coordinate, board);
+
+        print_board(rows, cols, board);
+        if (does_player_win(coordinate, rows, cols, board)) {
+            if (game_mode == PLAYER_VS_PLAYER) {
+                printf("\nPlayer %s won!\n", player % 2 == 0 ? "one" : "two");
+            } else {
+                printf("\n%s won!\n", player % 2 == 0 ? "Player one" : "Computer");
+            }
+            break;
+        }
+        if (player + 1 == rows * cols) {
+            printf("\nIt is a draw.\n");
+            break;
+        }
+
+        player++;
+    }
+    if (destroy_board(rows, board) == EXIT_FAILURE) {
+        fprintf(stderr, "Error: Unable to free memory for the board.\n");
+        return EXIT_FAILURE;
+    }
+    return EXIT_SUCCESS;
+}
+
+bool does_player_win(struct coordinate coordinate, int rows, int cols, int** board) {
+    if (coordinate.x < 0 || coordinate.y < 0) {
+        return false;
+    }
+
+    int current_piece = board[coordinate.x][coordinate.y];
+    for (int i = 0; i < rows - 3; i++) {
+
+        if (board[i][coordinate.y] == current_piece
+            && board[i + 1][coordinate.y] == current_piece
+            && board[i + 2][coordinate.y] == current_piece
+            && board[i + 3][coordinate.y] == current_piece)
+        {
+            return true;
+        }
+
+    }
+
+    for (int i = 0; i < cols - 3; i++) {
+        if (board[coordinate.x][i] == current_piece
+            && board[coordinate.x][i + 1] == current_piece
+            && board[coordinate.x][i + 2] == current_piece
+            && board[coordinate.x][i + 3] == current_piece) {
+            return true;
+        }
+    }
+
+    // Diagonale gauche à droite
+    for (int i = 0; i < rows - 3; i++) {
+        for (int j = 0; j < cols - 3; j++) {
+            if (board[i][j] == current_piece &&
+                board[i + 1][j + 1] == current_piece &&
+                board[i + 2][j + 2] == current_piece &&
+                board[i + 3][j + 3] == current_piece) {
+                return true;
+            }
+        }
+    }
+
+    // Diagonale droite à gauche
+    for (int i = 0; i < rows - 3; i++) {
+        for (int j = 3; j < cols; j++) {
+            if (board[i][j] == current_piece &&
+                board[i + 1][j - 1] == current_piece &&
+                board[i + 2][j - 2] == current_piece &&
+                board[i + 3][j - 3] == current_piece) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
\ No newline at end of file
diff --git a/src/game.h b/src/game.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9dc934b3cfe154183c9bbd75e1d2d9bb178a2a6
--- /dev/null
+++ b/src/game.h
@@ -0,0 +1,23 @@
+#ifndef GAME_H
+#define GAME_H
+
+#include <stdbool.h>
+#include "board.h"
+
+enum GAME_MODE {
+    PLAYER_VS_RANDOM_AI = 1,
+    PLAYER_VS_SMART_AI = 2,
+    PLAYER_VS_PLAYER = 3
+};
+
+struct coordinate {
+    int x;
+    int y;
+};
+
+int play_game(enum GAME_MODE game_mode, int rows, int cols);
+struct coordinate find_empty_slot(int x, int rows, int** board);
+bool does_player_win(struct coordinate coordinate, int rows, int cols, int** board);
+void place_token(int player, struct coordinate coordinate, int** board);
+
+#endif