diff --git a/Makefile b/Makefile
index 6d85b74615d772d09c4e77a3011e49e0790fba21..bc8b3ac47d8df2b91aba7904fe132193722f2067 100644
--- a/Makefile
+++ b/Makefile
@@ -3,11 +3,12 @@ CFLAGS  = -g -Wall -Wextra -Wpedantic
 LDLIBS  = -lm
 LDFLAGS = -fsanitize=address -fsanitize=leak
 
-puissance4: puissance4.c src/board.o src/game.o
+puissance4: puissance4.o src/board.o src/game.o
 	$(CC) $(CFLAGS) $^ -o $@ $(LDLIBS) $(LDFLAGS)
 
 board.o: src/board.h
 game.o: src/game.h
+puissance4.o: puissance4.h
 
 clean:
 	@echo "this rule must clean everything up (including candidate files in testbed)"
@@ -29,8 +30,13 @@ tests_rand_ai: puissance4
 tests_smart_ai: puissance4
 	$(MAKE) -C testbed/smart_ai
 
-generate_board_test: src/test_board.o src/board.o
-	$(CC) $(CFLAGS) $^ -o src/test_board $(LDLIBS) $(LDFLAGS)
+tests_game: src/test_game.o src/game.o src/board.o
+	$(CC) $(CFLAGS) $^ -o tests_game $(LDLIBS) $(LDFLAGS)
+	./tests_game
 
-tests_board: generate_board_test
-	./src/test_board
\ No newline at end of file
+tests_board: src/test_board.o src/board.o
+	$(CC) $(CFLAGS) $^ -o tests_board $(LDLIBS) $(LDFLAGS)
+	./tests_board
+
+run_tests: tests_game tests_board
+	@echo "All tests executed successfully."
\ No newline at end of file
diff --git a/puissance4.c b/puissance4.c
index 85b0e6b03b65c3836192ea7c11d062aeb817297e..f21647932014dfca9c3b2971c793d710655d792d 100644
--- a/puissance4.c
+++ b/puissance4.c
@@ -1,19 +1,16 @@
-#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
-
-void flush_input();
-bool is_valid_game_mode(int game_mode);
-bool is_valid_board_size(int rows, int cols);
-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);
+#include "puissance4.h"
+
+// #define AI_SEED 0
+// #define MIN_COLUMN 4
+// #define MIN_ROW 4
+
+// void flush_input();
+// bool is_valid_game_mode(int game_mode);
+// bool is_valid_board_size(int rows, int cols);
+// 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);
+// void announce_winner(enum GAME_MODE game_mode, int current_turn);
 
 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]))) {
@@ -26,10 +23,63 @@ int main(int argc, char const* argv[]) {
     }
 
     enum GAME_MODE game_mode = atoi(argv[1]);
-    int rows = atoi(argv[2]);
-    int cols = atoi(argv[3]);
+    int row_count = atoi(argv[2]);
+    int col_count = atoi(argv[3]);
     srand(AI_SEED);
-    return play_game(game_mode, rows, cols);
+
+    int** board = create_board(row_count, col_count);
+    if (board == NULL) {
+        fprintf(stderr, "Error: Unable to allocate memory for the board.\n");
+        return EXIT_FAILURE;
+    }
+
+    fill_board(row_count, col_count, board);
+    printf("Board size is %dx%d (rows x col)", row_count, col_count);
+    print_board(row_count, col_count, board);
+
+    int current_turn = 0;
+    struct coordinate empty_slot;
+
+    while (true) {
+        int selected_column = get_selected_column(game_mode, current_turn, col_count, row_count, board);
+        if (!is_valid_column(selected_column, col_count)) {
+            continue;
+        }
+
+        empty_slot = find_empty_slot(selected_column - 1, row_count, board);
+        place_token(current_turn % 2, empty_slot, board);
+        print_board(row_count, col_count, board);
+
+        if (does_player_win(empty_slot, row_count, col_count, board)) {
+            announce_winner(game_mode, current_turn);
+            break;
+        }
+
+        if (is_board_full(current_turn, row_count, col_count)) {
+            printf("\nIt is a draw.\n");
+            break;
+        }
+
+        current_turn++;
+    }
+
+    if (destroy_board(row_count, board) == EXIT_FAILURE) {
+        fprintf(stderr, "Error: Unable to free memory for the board.\n");
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+void announce_winner(enum GAME_MODE game_mode, int current_turn) {
+    const char* winner = (current_turn % 2 == 0) ? "Player one" : "Computer";
+
+    if (game_mode == PLAYER_VS_PLAYER) {
+        winner = (current_turn % 2 == 0) ? "one" : "two";
+        printf("\nPlayer %s won!\n", winner);
+    } else {
+        printf("\n%s won!\n", winner);
+    }
 }
 
 bool is_valid_game_mode(int game_mode) {
diff --git a/puissance4.h b/puissance4.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba2d9ccb9749cea6a931cdc432d516c0c4b53d85
--- /dev/null
+++ b/puissance4.h
@@ -0,0 +1,29 @@
+#ifndef _PUSSIANCE4_h_
+#define _PUSSIANCE4_h_
+
+#include <stdbool.h>
+#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
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include "src/game.h"
+#include "src/board.h"
+
+void announce_winner(enum GAME_MODE game_mode, int current_turn);
+bool is_valid_game_mode(int game_mode);
+bool is_valid_board_size(int rows, int cols);
+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);
+bool is_column_full(int col, int rows, int** board);
+void flush_input();
+
+#endif
diff --git a/src/actual_output.txt b/src/actual_output.txt
deleted file mode 100644
index 8885cb0d6e401e3a28108ea54c3f63c656356eea..0000000000000000000000000000000000000000
--- a/src/actual_output.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-
-┌─┬─┬─┬─┬─┬─┬─┐
-│ │ │ │ │ │ │ │
-├─┼─┼─┼─┼─┼─┼─┤
-│ │ │ │ │ │ │ │
-├─┼─┼─┼─┼─┼─┼─┤
-│ │ │ │ │ │ │ │
-├─┼─┼─┼─┼─┼─┼─┤
-│ │ │ │ │ │ │ │
-├─┼─┼─┼─┼─┼─┼─┤
-│ │ │ │ │ │ │ │
-├─┼─┼─┼─┼─┼─┼─┤
-│ │ │ │ │ │ │ │
-└─┴─┴─┴─┴─┴─┴─┘
- 1 2 3 4 5 6 7
\ No newline at end of file
diff --git a/src/game.c b/src/game.c
index b80875a4cf01a921d8426d1fa4b8b073e5512be7..530c90f372a503d68e8631658d165e188131abfd 100644
--- a/src/game.c
+++ b/src/game.c
@@ -23,60 +23,41 @@ struct coordinate find_empty_slot(int x, int rows, int** board) {
     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;
+bool is_valid_column(int column, int col_count) {
+    return column >= 1 && column <= col_count;
+}
 
-    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);
-            }
-        }
+int get_player_input() {
+    int column;
+    printf("\nColumn number? (starts at 1):");
+    scanf("%d", &column);
+    return column;
+}
 
-        if (player_selected_column < 1 || player_selected_column > cols) {
-            continue;
-        }
+bool is_board_full(int current_turn, int row_count, int col_count) {
+    return current_turn + 1 == row_count * col_count;
+}
 
-        coordinate = find_empty_slot(player_selected_column - 1, rows, board);
-        place_token(player % 2, coordinate, board);
+int get_selected_column(enum GAME_MODE game_mode, int current_turn, int col_count, int row_count, int** board) {
+    if (is_human_turn(game_mode, current_turn)) {
+        return get_player_input();
+    }
+    return get_ai_move(game_mode, col_count, row_count, 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;
-        }
+bool is_human_turn(enum GAME_MODE game_mode, int current_turn) {
+    return game_mode == PLAYER_VS_PLAYER || current_turn % 2 == 0;
+}
 
-        player++;
-    }
-    if (destroy_board(rows, board) == EXIT_FAILURE) {
-        fprintf(stderr, "Error: Unable to free memory for the board.\n");
-        return EXIT_FAILURE;
+int get_ai_move(enum GAME_MODE game_mode, int col_count, int row_count, int** board) {
+    switch (game_mode) {
+    case PLAYER_VS_RANDOM_AI:
+        return select_random_column(col_count, row_count, board);
+    case PLAYER_VS_SMART_AI:
+        return select_smart_column(col_count, row_count, board);
+    default:
+        return -1;
     }
-    return EXIT_SUCCESS;
 }
 
 bool does_player_win(struct coordinate coordinate, int rows, int cols, int** board) {
diff --git a/src/game.h b/src/game.h
index f9dc934b3cfe154183c9bbd75e1d2d9bb178a2a6..75d431c01f90e91b85e815801471681b93969170 100644
--- a/src/game.h
+++ b/src/game.h
@@ -1,5 +1,5 @@
-#ifndef GAME_H
-#define GAME_H
+#ifndef _GAME_H
+#define _GAME_H
 
 #include <stdbool.h>
 #include "board.h"
@@ -15,9 +15,14 @@ struct coordinate {
     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);
+bool is_valid_column(int column, int col_count);
+bool is_board_full(int current_turn, int row_count, int col_count);
+int get_selected_column(enum GAME_MODE game_mode, int current_turn, int col_count, int row_count, int** board);
+bool is_human_turn(enum GAME_MODE game_mode, int current_turn);
+int get_ai_move(enum GAME_MODE game_mode, int col_count, int row_count, int** board);
+int get_player_input();
 
 #endif
diff --git a/src/test_board.c b/src/test_board.c
index 050c064b11949e16bf50090020636f65816cfafd..018c4936d89f519b02371112cdf2f43fa3542ed3 100644
--- a/src/test_board.c
+++ b/src/test_board.c
@@ -4,23 +4,18 @@
 #include <string.h>
 #include "../src/board.h"
 
-#define EXPECTED_OUTPUT "src/expected_output.txt"
-#define ACTUAL_OUTPUT "src/actual_output.txt"
-
 #define GREEN "\033[1;32m"
 #define RED "\033[1;31m"
 #define RESET "\033[0m"
 
 void test_destroy_board();
 void test_fill_board();
-// void test_print_board();
 void test_create_board();
 
 int main() {
     test_create_board();
     test_fill_board();
     test_destroy_board();
-    // test_print_board();
     return EXIT_SUCCESS;
 }
 
@@ -38,43 +33,6 @@ void test_destroy_board() {
     printf(GREEN "test_destroy_board: PASSED\n" RESET);
 }
 
-// void test_print_board() {
-//     int rows = 6;
-//     int cols = 7;
-//     int** board = create_board(rows, cols);
-//     assert(board != NULL && "Board creation failed");
-
-//     fill_board(rows, cols, board);
-
-//     FILE* expected_output_file = fopen(EXPECTED_OUTPUT, "w");
-//     assert(expected_output_file != NULL && "Failed to open expected output file");
-//     freopen(EXPECTED_OUTPUT, "w", stdout);
-//     print_board(rows, cols, board);
-//     fclose(expected_output_file);
-
-//     freopen("/dev/tty", "w", stdout);
-
-//     FILE* actual_output_file = fopen(EXPECTED_OUTPUT, "r");
-//     assert(actual_output_file != NULL && "Failed to open actual output file");
-
-//     char actual_output[1024] = { 0 };
-//     fread(actual_output, sizeof(char), 1024, actual_output_file);
-//     fclose(actual_output_file);
-
-//     FILE* expected_output_file_read = fopen(EXPECTED_OUTPUT, "r");
-//     assert(expected_output_file_read != NULL && "Failed to open expected output file for reading");
-
-//     char expected_output[1024] = { 0 };
-//     fread(expected_output, sizeof(char), 1024, expected_output_file_read);
-//     fclose(expected_output_file_read);
-
-//     assert(strncmp(actual_output, expected_output, strlen(expected_output)) == 0
-//         && "Output does not match expected output");
-
-//     printf(GREEN "test_print_board: PASSED\n" RESET);
-//     destroy_board(rows, board);
-// }
-
 void test_create_board() {
     int rows = 6;
     int cols = 7;
diff --git a/src/test_game.c b/src/test_game.c
new file mode 100644
index 0000000000000000000000000000000000000000..3cd6b996ae61696cbc15c3eac97b2fc91b94ad1a
--- /dev/null
+++ b/src/test_game.c
@@ -0,0 +1,128 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "game.h"
+
+int** setup_board(int rows, int cols, int default_value) {
+    int** board = create_board(rows, cols);
+    if (board == NULL) {
+        fprintf(stderr, "Error: Unable to allocate memory for the board.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    for (int i = 0; i < rows; i++) {
+        for (int j = 0; j < cols; j++) {
+            board[i][j] = default_value;
+        }
+    }
+
+    return board;
+}
+
+void test_place_token() {
+    int rows = 6, cols = 7;
+    int** board = setup_board(rows, cols, EMPTY);
+
+    // Player1
+    struct coordinate coord = { 2, 3 };
+    place_token(0, coord, board);
+    assert(board[2][3] == PLAYER1);
+
+    // Player2
+    coord.x = 4;
+    coord.y = 5;
+    place_token(1, coord, board);
+    assert(board[4][5] == PLAYER2);
+
+    destroy_board(rows, board);
+}
+
+void test_find_empty_slot() {
+    int rows = 6, cols = 7;
+    int** board = setup_board(rows, cols, EMPTY);
+
+    // 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);
+
+    // 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);
+
+    destroy_board(rows, board);
+}
+
+void test_is_valid_column() {
+    int cols = 7;
+
+    assert(is_valid_column(1, cols) == true);
+    assert(is_valid_column(7, cols) == true);
+
+    assert(is_valid_column(0, cols) == false);
+    assert(is_valid_column(8, cols) == false);
+}
+
+void test_is_board_full() {
+    int rows = 6, cols = 7;
+
+    assert(is_board_full(41, rows, cols) == true);  // Full board
+    assert(is_board_full(40, rows, cols) == false); // Not full board
+}
+
+void test_does_player_win() {
+    int rows = 6, cols = 7;
+    int** board = setup_board(rows, cols, EMPTY);
+
+    // Test horizontal win
+    board[5][0] = PLAYER1;
+    board[5][1] = PLAYER1;
+    board[5][2] = PLAYER1;
+    board[5][3] = PLAYER1;
+    struct coordinate coord = { 5, 3 };
+    assert(does_player_win(coord, rows, cols, board) == true);
+
+    // Test vertical win
+    fill_board(rows, cols, board);
+    board[5][2] = PLAYER2;
+    board[4][2] = PLAYER2;
+    board[3][2] = PLAYER2;
+    board[2][2] = PLAYER2;
+    coord.x = 2;
+    coord.y = 2;
+    assert(does_player_win(coord, rows, cols, board) == true);
+
+    // Test diagonal win (left to right)
+    fill_board(rows, cols, board);
+    board[5][0] = PLAYER1;
+    board[4][1] = PLAYER1;
+    board[3][2] = PLAYER1;
+    board[2][3] = PLAYER1;
+    coord.x = 2;
+    coord.y = 3;
+    assert(does_player_win(coord, rows, cols, board) == true);
+
+    // Test diagonal win (right to left)
+    fill_board(rows, cols, board);
+    board[5][3] = PLAYER2;
+    board[4][2] = PLAYER2;
+    board[3][1] = PLAYER2;
+    board[2][0] = PLAYER2;
+    coord.x = 2;
+    coord.y = 0;
+    assert(does_player_win(coord, rows, cols, board) == true);
+
+    destroy_board(rows, board);
+}
+
+int main() {
+    test_place_token();
+    test_find_empty_slot();
+    test_is_valid_column();
+    test_is_board_full();
+    test_does_player_win();
+
+    printf("All tests passed successfully.\n");
+    return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/tests_board b/tests_board
new file mode 100755
index 0000000000000000000000000000000000000000..74e2f07dd6600edda11e746f20c1c567898064ad
Binary files /dev/null and b/tests_board differ