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()