diff --git a/__pycache__/puissance4.cpython-310.pyc b/__pycache__/puissance4.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b1015cf425bb15d7419ab92b9e42e8f458fbe8b6
Binary files /dev/null and b/__pycache__/puissance4.cpython-310.pyc differ
diff --git a/__pycache__/test_puissance4.cpython-310.pyc b/__pycache__/test_puissance4.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..68241a7089fc93ded2a8e6c79ab4c72b6010ec30
Binary files /dev/null and b/__pycache__/test_puissance4.cpython-310.pyc differ
diff --git a/puissance4.py b/puissance4.py
new file mode 100644
index 0000000000000000000000000000000000000000..c0600bba7b77e8a7e5edb12ab5e7c338fe2419b2
--- /dev/null
+++ b/puissance4.py
@@ -0,0 +1,140 @@
+import numpy as np
+
+def create_board():
+    return np.zeros((6, 7), dtype=int)
+
+def print_board(board):
+    for row in board:
+        print("|", end="")
+        for col in row:
+            if col == 0:
+                print("   ", end="|")
+            elif col == 1:
+                print(" X ", end="|")
+            elif col == 2:
+                print(" O ", end="|")
+        print()
+        print("+---" * 7)
+
+def is_valid_location(board, col):
+    return board[0, col - 1] == 0 if 1 <= col <= 7 else False
+
+def drop_piece(board, col, player):
+    for row in range(5, -1, -1):
+        if board[row, col - 1] == 0:
+            board[row, col - 1] = player
+            break
+
+def winning_move(board, player):
+    for col in range(4):
+        for row in range(6):
+            if (
+                board[row, col] == player
+                and board[row, col + 1] == player
+                and board[row, col + 2] == player
+                and board[row, col + 3] == player
+            ):
+                return True
+
+    for col in range(7):
+        for row in range(3):
+            if (
+                board[row, col] == player
+                and board[row + 1, col] == player
+                and board[row + 2, col] == player
+                and board[row + 3, col] == player
+            ):
+                return True
+
+    for col in range(4):
+        for row in range(3):
+            if (
+                board[row, col] == player
+                and board[row + 1, col + 1] == player
+                and board[row + 2, col + 2] == player
+                and board[row + 3, col + 3] == player
+            ):
+                return True
+
+    for col in range(4):
+        for row in range(3, 6):
+            if (
+                board[row, col] == player
+                and board[row - 1, col + 1] == player
+                and board[row - 2, col + 2] == player
+                and board[row - 3, col + 3] == player
+            ):
+                return True
+
+    return False
+
+def reverse_column(board, col, turn):
+    board[:, col - 1] = np.flip(board[:, col - 1])
+
+    for col_index in range(col - 1, col):
+        col_data = board[:, col_index]
+        non_zero_elements = col_data[col_data != 0]
+        num_zeros = 6 - len(non_zero_elements)
+        new_col = np.concatenate((np.zeros(num_zeros, dtype=int), non_zero_elements))
+        board[:, col_index] = new_col
+
+    return 3 - turn
+
+
+def play_game():
+    board = create_board()
+    game_over = False
+    turn = 1
+
+    while not game_over:
+        print_board(board)
+
+        if turn == 1:
+            user_input = input("Joueur 1 (X), choisissez une colonne (1-7, -1 pour quitter, r1 pour inverser verticalement la colonne 1) : ")
+        else:
+            print("Tour de l'IA :")
+            col_input = str(np.random.randint(1, 8))
+
+            if np.random.rand() < 0.2:
+                available_cols = [col for col in range(1, 8) if board[5, col - 1] != 0]
+                if available_cols:
+                    col_to_reverse = np.random.choice(available_cols)
+                    turn = reverse_column(board, col_to_reverse, turn)
+                    print(f"Colonne {col_to_reverse} inversée (IA).")
+                    continue
+
+            user_input = col_input
+
+        try:
+            if user_input.startswith("r") and 1 <= int(user_input[1:]) <= 7:
+                col_to_reverse = int(user_input[1:])
+                turn = reverse_column(board, col_to_reverse, turn)
+                print(f"Colonne {col_to_reverse} inversée.")
+            else:
+                col = int(user_input)
+
+                if col == -1:
+                    print("Partie interrompue.")
+                    game_over = True
+                elif is_valid_location(board, col):
+                    drop_piece(board, col, turn)
+
+                    if winning_move(board, turn):
+                        print_board(board)
+                        print(f"Joueur {turn} a gagné!")
+                        game_over = True
+                    else:
+                        turn = 3 - turn
+
+                    if np.all(board != 0):
+                        print_board(board)
+                        print("Match nul!")
+                        game_over = True
+                else:
+                    print("Colonne invalide. Choisissez à nouveau.")
+        except ValueError:
+            print("Entrée invalide. Veuillez saisir un nombre de colonne (1-7, -1 pour quitter, r1 pour inverser la colonne 1).")
+
+
+if __name__ == "__main__":
+    play_game()
diff --git a/test_puissance4.py b/test_puissance4.py
new file mode 100644
index 0000000000000000000000000000000000000000..dfc534b5ff1b45b36710bf81b28a747753981447
--- /dev/null
+++ b/test_puissance4.py
@@ -0,0 +1,51 @@
+import unittest
+import numpy as np
+from puissance4 import create_board, is_valid_location, drop_piece, reverse_column, winning_move
+
+class TestPuissance4(unittest.TestCase):
+    def test_create_board(self):
+        board = create_board()
+        self.assertEqual(board.shape, (6, 7))
+        self.assertTrue((board == 0).all())
+
+    def test_is_valid_location(self):
+        board = create_board()
+        self.assertTrue(is_valid_location(board, 1))
+        self.assertFalse(is_valid_location(board, 8))
+
+    def test_drop_piece(self):
+        board = create_board()
+        drop_piece(board, 1, 1)
+        self.assertEqual(board[5, 0], 1)
+
+    def test_winning_move(self):
+        board = create_board()
+        for _ in range(4):
+            drop_piece(board, 1, 1)
+        self.assertTrue(winning_move(board, 1))
+
+    def test_reverse_column(self):
+        board = np.array([
+            [0, 0, 0, 0, 0, 0, 0],
+            [0, 2, 0, 0, 0, 0, 0],
+            [0, 1, 0, 0, 0, 0, 0],
+            [0, 2, 0, 0, 0, 0, 0],
+            [0, 1, 0, 0, 0, 0, 0],
+            [0, 1, 0, 0, 0, 0, 0]
+        ])
+
+        reverse_column(board, 2)
+
+        expected_result = np.array([
+            [0, 0, 0, 0, 0, 0, 0],
+            [0, 1, 0, 0, 0, 0, 0],
+            [0, 1, 0, 0, 0, 0, 0],
+            [0, 2, 0, 0, 0, 0, 0],
+            [0, 1, 0, 0, 0, 0, 0],
+            [0, 2, 0, 0, 0, 0, 0]
+        ])
+
+        self.assertTrue(np.array_equal(board, expected_result))
+
+if __name__ == '__main__':
+    unittest.main()