Reversi Game - Python Code

This is the Python code for a Reversi game.


import tkinter as tk
from tkinter import messagebox

class ReversiGame:
def __init__(self, master):
    self.master = master
    self.master.title("Reversi Game")

    # Board setup (8x8 grid)
    self.board = []  # List to hold button objects (buttons represent the board squares)
    self.current_player = 'red'  # red starts the game
    self.game_over = False  # Flag to check if the game is over

    # Create and place labels for displaying the red and blue piece counts
    self.red_count_label = tk.Label(self.master, text="Red: 2")
    self.red_count_label.grid(row=0, column=0)
    self.blue_count_label = tk.Label(self.master, text="Blue: 2")
    self.blue_count_label.grid(row=0, column=1)

    # Create the game board (8x8)
    self.create_board()

    # Setup initial pieces in the center of the board
    self.setup_initial_pieces()

def create_board(self):
    """
    You need to:
    - Create a 8x8 grid of buttons for the board.
    - Use loops to create buttons and store them in `self.board` (a 2D list).
    - Bind the `on_click` function for each button to handle piece placement.
    
    Variables to use:
    - `row` and `col` to track positions in the board.
    - `button` to represent each individual square.
    - `self.board` stores buttons and pieces in a 2D list.
    """
    for row in range(8):
        row_buttons = []
        for col in range(8):
            button = tk.Button(self.master, width=6, height=3, command=lambda r=row, c=col: self.on_click(r, c))
            button.grid(row=row+1, column=col)
            button.piece = None  # Initially, no piece on the square
            row_buttons.append(button)
        self.board.append(row_buttons)

def setup_initial_pieces(self):
    """
    You need to:
    - Set up the initial pieces in the center of the board.
    - Place two red and two blue pieces in the middle (row 3, col 3, 4, 3, etc.).
    
    Variables to use:
    - `self.board[row][col].piece` to set the initial pieces.
    """
    self.board[3][3].piece = 'red'
    self.board[3][4].piece = 'blue'
    self.board[4][3].piece = 'blue'
    self.board[4][4].piece = 'red'

def on_click(self, row, col):
    """
    You need to:
    - Check if the game is over or if the square is already occupied.
    - Verify if the move is valid, place the current player's piece, and flip the opponent's pieces.
    - Update the counts and check if the game is over.
    - Switch to the next player.
    
    Variables to use:
    - `row`, `col` are the clicked square's coordinates.
    - `self.board[row][col]` is the button for that square.
    - `self.current_player` stores the current player ('red' or 'blue').
    - `self.game_over` is a flag that tracks if the game is over.
    """
    if self.game_over:
        return

    if self.board[row][col].piece is not None:
        return

    if not self.is_valid_move(row, col, self.current_player):
        return

    # Place the piece for the current player
    self.board[row][col].piece = self.current_player
    self.flip_pieces(row, col, self.current_player)

    # Update the piece counts
    self.update_counts()

    # Check if the game is over
    self.check_game_over()

    # Switch to the next player
    self.switch_player()

def is_valid_move(self, row, col, player):
    """
    You need to:
    - Check if the clicked square is empty.
    - Check all 8 directions from the clicked square for valid flips.
    - A valid move should sandwich opponent's pieces between the player's piece.
    
    Variables to use:
    - `row`, `col` are the coordinates of the square the player clicked.
    - `player` is the current player's color ('red' or 'blue').
    
    Logic:
    - If a piece can be flipped, it's a valid move.
    - Return `True` if valid, otherwise `False`.
    """
    pass  # Implement the move validation logic here

def flip_pieces(self, row, col, player):
    """
    You need to:
    - Flip the opponent's pieces after a valid move.
    - For each direction, check if there are opponent's pieces to flip.
    
    Variables to use:
    - `row`, `col` are the coordinates of the clicked square.
    - `player` is the current player's color.
    
    Logic:
    - If opponent's pieces are sandwiched, flip them to the current player's color.
    """
    pass  # Implement the flipping of pieces logic here

def switch_player(self):
    """
    You need to:
    - Switch the turn to the other player.
    
    Variables to use:
    - `self.current_player` stores the current player's turn.
    
    Logic:
    - If it's 'red's turn, switch to 'blue'.
    - If it's 'blue's turn, switch to 'red'.
    """
    pass  # Implement the logic to switch the player here

def update_counts(self):
    """
    You need to:
    - Count the number of red and blue pieces on the board.
    - Update the labels for displaying the counts.
    
    Variables to use:
    - `self.red_count_label` and `self.blue_count_label` to display counts.
    
    Logic:
    - Count the number of 'red' and 'blue' pieces and update the labels.
    """
    pass  # Implement the logic to update the piece counts here

def check_game_over(self):
    """
    You need to:
    - Check if the game is over and announce the result.
    
    Variables to use:
    - `self.game_over` to track if the game is over.
    
    Logic:
    - If no more valid moves for either player, end the game.
    - Declare the winner based on the count of pieces.
    - If there is a tie, announce a draw.
    """
    pass  # Implement the logic to check if the game is over here

# Main loop to run the game
if __name__ == "__main__":
root = tk.Tk()
game = ReversiGame(root)
root.mainloop()

Solution


                
                    
import tkinter as tk
from tkinter import messagebox

class ReversiGame:
    def __init__(self, master):
        self.master = master
        self.master.title("Reversi Game")
        self.board = []
        self.current_player = 'red'  # red starts the game
        self.game_over = False
        
        # Create the labels for displaying the piece counts
        self.red_count_label = tk.Label(self.master, text="Red: 2")
        self.red_count_label.grid(row=0, column=0)
        self.blue_count_label = tk.Label(self.master, text="Blue: 2")
        self.blue_count_label.grid(row=0, column=1)

        self.create_board()
        self.setup_initial_pieces()

    def create_board(self):
        """Creates the game board GUI."""
        for row in range(8):
            row_list = []
            for col in range(8):
                button = tk.Button(self.master, width=6, height=3, command=lambda r=row, c=col: self.on_click(r, c))
                button.grid(row=row+1, column=col)
                button.piece = None  # Set the initial piece to None
                row_list.append(button)
            self.board.append(row_list)

    def setup_initial_pieces(self):
        """Sets up the initial pieces in the center."""
        self.board[3][3].config(bg='blue')
        self.board[3][3].piece = 'blue'
        self.board[3][4].config(bg='red')
        self.board[3][4].piece = 'red'
        self.board[4][3].config(bg='red')
        self.board[4][3].piece = 'red'
        self.board[4][4].config(bg='blue')
        self.board[4][4].piece = 'blue'
        
        self.update_counts()

    def on_click(self, row, col):
        """Handles the logic when a button (board square) is clicked."""
        if self.game_over:
            return  # If the game is over, do nothing
        
        button = self.board[row][col]
        if button.piece is not None:  # If the square is already occupied
            return
        
        if not self.is_valid_move(row, col, self.current_player):  # If the move is not valid
            return
        
        # Place the piece
        button.piece = self.current_player
        button.config(bg=self.current_player)
        
        # Flip the opponent's pieces
        self.flip_pieces(row, col, self.current_player)
        
        # Update the counts
        self.update_counts()
        
        # Switch players
        self.switch_player()
        
        # Check if the game is over
        self.check_game_over()

    def is_valid_move(self, row, col, player):
        """Checks if the move made by the player is valid."""
        if self.board[row][col].piece is not None:
            return False
        
        opponent = 'blue' if player == 'red' else 'red'
        
        directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (1, 1), (-1, 1), (1, -1)]
        for dr, dc in directions:
            r, c = row + dr, col + dc
            flip_found = False
            while 0 <= r < 8 and 0 <= c < 8:
                if self.board[r][c].piece == opponent:
                    flip_found = True
                elif self.board[r][c].piece == player:
                    if flip_found:
                        return True
                    else:
                        break
                else:
                    break
                r += dr
                c += dc
        return False

    def flip_pieces(self, row, col, player):
        """Flips the opponent's pieces after a valid move."""
        opponent = 'blue' if player == 'red' else 'red'
        directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (1, 1), (-1, 1), (1, -1)]
        for dr, dc in directions:
            r, c = row + dr, col + dc
            flip_pieces = []
            while 0 <= r < 8 and 0 <= c < 8:
                if self.board[r][c].piece == opponent:
                    flip_pieces.append((r, c))
                elif self.board[r][c].piece == player:
                    for fr, fc in flip_pieces:
                        self.board[fr][fc].piece = player
                        self.board[fr][fc].config(bg=player)
                    break
                else:
                    break
                r += dr
                c += dc

    def switch_player(self):
        """Switches the turn to the other player."""
        self.current_player = 'blue' if self.current_player == 'red' else 'red'

    def update_counts(self):
        """Updates the count of red and blue pieces on the board."""
        red_count = 0
        blue_count = 0
        for row in self.board:
            for button in row:
                if button.piece == 'red':
                    red_count += 1
                elif button.piece == 'blue':
                    blue_count += 1
        self.red_count_label.config(text=f"Red: {red_count}")
        self.blue_count_label.config(text=f"Blue: {blue_count}")

    def check_game_over(self):
        """Checks if the game is over and announces the winner."""
        red_count = 0
        blue_count = 0
        for row in self.board:
            for button in row:
                if button.piece == 'red':
                    red_count += 1
                elif button.piece == 'blue':
                    blue_count += 1

        # Check if any player has no valid moves
        if red_count + blue_count == 64 or red_count == 0 or blue_count == 0:
            self.game_over = True
            if red_count > blue_count:
                winner = "Red wins!"
            elif blue_count > red_count:
                winner = "Blue wins!"
            else:
                winner = "It's a draw!"
            messagebox.showinfo("Game Over", winner)

# Main loop to run the game
if __name__ == "__main__":
    root = tk.Tk()
    game = ReversiGame(root)
    root.mainloop()