python pygame reversi game

https://github.com/Sohieb/reversi-game

main.py

import pygame
import random
import view
import board
import common
from view import *
from board import *
from common import *


class game_manager:
    """
    The Main class which handle the overall game control
    """

    def __init__(self):
        ## create a veiw and a model objects
        self.window = view.game_interface()
        self.board = board.game_model()

        ## Show the intro screen and get the initial game parameters
        self.game_mode = self.window.intro_screen()
        self.current_playing = 0  # 0 -> player_1, 1 -> player_2

    # The main game function handling the game loop
    def play(self):
        pygame.time.wait(300)
        clock = pygame.time.Clock()
        while True:
            if self.board.is_game_ended():
                count_white, count_black = self.board.get_cell_count()
                if count_black > count_white:
                    self.winner = "BLACK"
                elif count_white > count_black:
                    self.winner = "WHITE"
                else:
                    self.winner = "TIE"
                self.next_action = self.window.result_screen(self.winner)
                pygame.time.wait(300)
                if self.next_action == "Continue":
                    self.board.reset_game_board()
                    self.game_mode = self.window.intro_screen()
                else:
                    break

            if self.game_mode[self.current_playing] == "Human":
                valid_moves = self.board.get_valid_moves(self.current_playing)

                clicked_cell = self.window.game_screen(self.board.grid, True)
                while clicked_cell[0] * 8 + clicked_cell[1] not in valid_moves:
                    clicked_cell = self.window.game_screen(self.board.grid, True)

                self.board.make_move(clicked_cell, self.current_playing)


            else:  ## current player is the computer actor
                pygame.time.wait(300)

                if self.game_mode[2] == "Easy":  # Random move
                    ##########print "Easy"
                    valid_moves = self.board.get_valid_moves(self.current_playing)
                    rand_move = random.randint(0, len(valid_moves) - 1)
                    clicked_cell = (valid_moves[rand_move] // common.SIDE_LEN, \
                                    valid_moves[rand_move] % common.SIDE_LEN)
                    self.board.make_move(clicked_cell, self.current_playing)

            # else:					#TODO	 # Intelligent move
            ##########print "Hard"

            self.current_playing = 1 - self.current_playing  ## switch to te next player
            self.window.game_screen(self.board.grid, False)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()

            pygame.display.update()
            clock.tick(60)


# The main Function
def main():
    game = game_manager()  ## create a game instance
    game.play()  ## run the game


if __name__ == '__main__':
    main()

view.py

import pygame
import time
import common
from common import *


class game_interface:
    """
    The GUI class responsible for the game graphics
    and all (input / output) interactions.
    """

    def __init__(self):

        pygame.init()

        # main colors
        self.BLACK_COLOR = (0, 0, 0)
        self.WHITE_COLOR = (255, 255, 255)
        self.BACKGROUND_COLOR = (0, 140, 90)
        self.BUTTON_INACTIVE_COLOR = (0, 250, 150)
        self.BUTTON_ACTIVE_COLOR = (0, 100, 100)
        self.BORDER_COLOR = (205, 133, 63)  ## peru -> #CD853F

        # display parameters
        self.SCREEN_SIZE = (700, 500)
        self.BOARD_SIZE = 400
        self.BORDER_SIZE = 20
        self.CELL_SIZE = 50

        # start the game screen
        self.game_display = pygame.display.set_mode(self.SCREEN_SIZE)
        pygame.display.set_caption("Reversi GAME")

    def intro_screen(self):
        """
        Show the intro screen and return either
        user choose 1 player or two players mode
        """

        while True:
            self.game_display.fill(self.BACKGROUND_COLOR)

            game_title_font = pygame.font.SysFont('comicsansms', 100)
            game_title = game_title_font.render("Reversi Game", True, self.WHITE_COLOR)
            game_title_pos = game_title.get_rect()
            game_title_pos.center = (self.SCREEN_SIZE[0] // 2, self.SCREEN_SIZE[1] // 2 - 50)

            self.game_display.blit(game_title, game_title_pos)

            mode1_clicked = self.add_button("1 Player", 100, 350, 100, 50, \
                                            self.BUTTON_INACTIVE_COLOR, self.BUTTON_ACTIVE_COLOR)
            mode2_clicked = self.add_button("2 Player", 300, 350, 100, 50, \
                                            self.BUTTON_INACTIVE_COLOR, self.BUTTON_ACTIVE_COLOR)
            exit_game_clicked = self.add_button("Exit", 500, 350, 100, 50, \
                                                self.BUTTON_INACTIVE_COLOR, self.BUTTON_ACTIVE_COLOR)

            if mode1_clicked == True:
                diff_level = self.get_diff_level()
                return ("Human", "Computer", diff_level)

            if mode2_clicked == True:
                return ("Human", "Human", "NONE")

            if exit_game_clicked == True:
                pygame.quit()
                quit()

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()

            pygame.display.update()

    def result_screen(self, winner):
        """
        Show the result screen and return either
        continue or it exits the game
        """

        while True:
            self.game_display.fill(self.BACKGROUND_COLOR)

            game_title_font = pygame.font.SysFont('comicsansms', 100)
            if winner != "TIE":
                game_title = game_title_font.render(winner + " Wins", True, self.WHITE_COLOR)
            else:
                game_title = game_title_font.render("TIE", True, self.WHITE_COLOR)
            game_title_pos = game_title.get_rect()
            game_title_pos.center = (self.SCREEN_SIZE[0] // 2, self.SCREEN_SIZE[1] // 2 - 50)

            self.game_display.blit(game_title, game_title_pos)

            mode1_clicked = self.add_button("Continue", 200, 350, 100, 50, \
                                            self.BUTTON_INACTIVE_COLOR, self.BUTTON_ACTIVE_COLOR)
            exit_game_clicked = self.add_button("Exit", 400, 350, 100, 50, \
                                                self.BUTTON_INACTIVE_COLOR, self.BUTTON_ACTIVE_COLOR)

            if mode1_clicked == True:
                return "Continue"

            if exit_game_clicked == True:
                return "Exit"

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()

            pygame.display.update()

    def get_diff_level(self):
        """
        Show the diff levels and return the selected
        """

        while True:
            self.game_display.fill(self.BACKGROUND_COLOR)

            game_title_font = pygame.font.SysFont('comicsansms', 100)
            game_title = game_title_font.render("Reversi Game", True, self.WHITE_COLOR)
            game_title_pos = game_title.get_rect()
            game_title_pos.center = (self.SCREEN_SIZE[0] // 2, self.SCREEN_SIZE[1] // 2 - 50)

            self.game_display.blit(game_title, game_title_pos)

            diff_easy = self.add_button("Easy", 300, 300, 100, 50, \
                                        self.BUTTON_INACTIVE_COLOR, self.BUTTON_ACTIVE_COLOR)
            diff_hard = self.add_button("Hard", 300, 400, 100, 50, \
                                        self.BUTTON_INACTIVE_COLOR, self.BUTTON_ACTIVE_COLOR)

            if diff_easy == True:
                return "Easy"
            if diff_hard == True:
                return "Hard"

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()

            pygame.display.update()

    def add_button(self, message, start_X, start_Y, width, height, inactive_col, active_col):
        mouse_pos = pygame.mouse.get_pos()
        mouse_click = pygame.mouse.get_pressed()
        is_clicked = False

        draw_color = inactive_col
        if start_X + width > mouse_pos[0] > start_X and start_Y + height > mouse_pos[1] > start_Y:
            draw_color = active_col
            if mouse_click[0] == 1:
                is_clicked = True

        pygame.draw.rect(self.game_display, draw_color, (start_X, start_Y, width, height))

        button_text_font = pygame.font.SysFont('comicsansms', 20)
        button_text = button_text_font.render(message, True, self.BLACK_COLOR)
        button_text_pos = button_text.get_rect()
        button_text_pos.center = (start_X + width // 2, start_Y + height // 2)

        self.game_display.blit(button_text, button_text_pos)

        return is_clicked

    def get_pressed_cell(self):
        pygame.event.get()  ## To flush
        mouse_pos = pygame.mouse.get_pos()
        mouse_click = pygame.mouse.get_pressed()
        if mouse_click[0] == 0:
            return (-1, -1)

        if 150 + self.BOARD_SIZE > mouse_pos[0] > 150 and 50 + self.BOARD_SIZE > mouse_pos[1] > 50:
            pos_X = mouse_pos[0] - 150
            pos_Y = mouse_pos[1] - 50
            pos_X = pos_X // self.CELL_SIZE
            pos_Y = pos_Y // self.CELL_SIZE
            return (pos_X, pos_Y)

        return (-1, -1)

    def game_screen(self, grid, need_click):
        """
      Main game screen
        """

        ## (start_X, start_Y, width, height)
        upper_border = (150 - self.BORDER_SIZE, 50 - self.BORDER_SIZE, \
                        self.BOARD_SIZE + 2 * self.BORDER_SIZE, self.BORDER_SIZE)
        right_border = (self.SCREEN_SIZE[0] - 150, 50 - self.BORDER_SIZE, \
                        self.BORDER_SIZE, self.BOARD_SIZE + 2 * self.BORDER_SIZE)
        lower_border = (150 - self.BORDER_SIZE, self.SCREEN_SIZE[1] - 50, \
                        self.BOARD_SIZE + 2 * self.BORDER_SIZE, self.BORDER_SIZE)
        left_border = (150 - self.BORDER_SIZE, 50 - self.BORDER_SIZE, \
                       self.BORDER_SIZE, self.BOARD_SIZE + 2 * self.BORDER_SIZE)

        horizontal_lines_start_X = 150
        horizontal_lines_start_Y = 100
        horizontal_lines_end_X = 700 - 150
        horizontal_lines_end_Y = 100

        vertical_lines_start_X = 200
        vertical_lines_start_Y = 50
        vertical_lines_end_X = 200
        vertical_lines_end_Y = 500 - 50

        while True:
            self.game_display.fill(self.BACKGROUND_COLOR)

            my_line_start_X = horizontal_lines_start_X
            my_line_start_Y = horizontal_lines_start_Y
            my_line_end_X = horizontal_lines_end_X
            my_line_end_Y = horizontal_lines_end_Y

            for i in range(common.SIDE_LEN - 1):
                pygame.draw.line(self.game_display, self.BLACK_COLOR, \
                                 (my_line_start_X, my_line_start_Y), (my_line_end_X, my_line_end_Y), 2)
                my_line_start_Y += self.CELL_SIZE
                my_line_end_Y += self.CELL_SIZE

            my_line_start_X = vertical_lines_start_X
            my_line_start_Y = vertical_lines_start_Y
            my_line_end_X = vertical_lines_end_X
            my_line_end_Y = vertical_lines_end_Y

            for i in range(common.SIDE_LEN - 1):
                pygame.draw.line(self.game_display, self.BLACK_COLOR, \
                                 (my_line_start_X, my_line_start_Y), (my_line_end_X, my_line_end_Y), 2)
                my_line_start_X += self.CELL_SIZE
                my_line_end_X += self.CELL_SIZE

            pygame.draw.rect(self.game_display, self.BORDER_COLOR, upper_border)
            pygame.draw.rect(self.game_display, self.BORDER_COLOR, right_border)
            pygame.draw.rect(self.game_display, self.BORDER_COLOR, lower_border)
            pygame.draw.rect(self.game_display, self.BORDER_COLOR, left_border)

            for i in range(common.SIDE_LEN):
                for j in range(common.SIDE_LEN):
                    if grid[i][j] == common.EMPTY_CELL:
                        continue
                    circle_color = self.BLACK_COLOR
                    if grid[i][j] == common.WHITE_CELL:
                        circle_color = self.WHITE_COLOR
                    pos_X = 150 + self.CELL_SIZE * i + self.CELL_SIZE / 2
                    pos_Y = 50 + self.CELL_SIZE * j + self.CELL_SIZE / 2
                    pygame.draw.circle(self.game_display, circle_color, (pos_X, pos_Y), 20)

            exit_game_clicked = self.add_button("Exit", 585, 400, 100, 50, \
                                                self.BUTTON_INACTIVE_COLOR, self.BUTTON_ACTIVE_COLOR)

            if exit_game_clicked == True:
                pygame.quit()
                quit()

            clicked_cell = self.get_pressed_cell()

            if clicked_cell[0] != -1 and clicked_cell[1] != -1:
                return clicked_cell

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()

            pygame.display.update()

            if need_click == False:
                break

board.py

import common
from common import *


class game_model:
    """
    The game structure, data and logic
    """

    def __init__(self):

        ## common parameters
        self.BLACK_CELL = common.BLACK_CELL
        self.WHITE_CELL = common.WHITE_CELL
        self.EMPTY_CELL = common.EMPTY_CELL
        self.SIDE_LEN = common.SIDE_LEN

        ## create the game grid & initialize it with empty cells
        self.grid = [[0 for x in range(self.SIDE_LEN)] for y in range(self.SIDE_LEN)]
        for i in range(self.SIDE_LEN):
            for j in range(self.SIDE_LEN):
                self.grid[i][j] = self.EMPTY_CELL

        ## set the initial 4 center cells
        self.grid[3][3] = self.WHITE_CELL
        self.grid[4][4] = self.WHITE_CELL
        self.grid[3][4] = self.BLACK_CELL
        self.grid[4][3] = self.BLACK_CELL

        self.valid_moves = []

    def reset_game_board(self):

        ## create the game grid & initialize it with empty cells
        self.grid = [[0 for x in range(self.SIDE_LEN)] for y in range(self.SIDE_LEN)]
        for i in range(self.SIDE_LEN):
            for j in range(self.SIDE_LEN):
                self.grid[i][j] = self.EMPTY_CELL

        ## set the initial 4 center cells
        self.grid[3][3] = self.WHITE_CELL
        self.grid[4][4] = self.WHITE_CELL
        self.grid[3][4] = self.BLACK_CELL
        self.grid[4][3] = self.BLACK_CELL

    def set_cell(self, pos, color):
        self.grid[pos[0]][pos[1]] = color

    def get_grid(self):
        return self.grid

    def get_valid_moves(self, turn):
        """
        Get and return the valid moves for the current player.
        Each move is represented as a one integer value which
        range from 0 to 63, where this number equals i * 8 + j
        """

        valid_moves = []
        for i in range(self.SIDE_LEN):
            for j in range(self.SIDE_LEN):
                if self.grid[i][j] != self.EMPTY_CELL:
                    continue
                for k in range(common.DIR_COUNT):
                    count_my_cells = 0
                    count_other_cells = 0
                    cur_X = i + common.dx[k]
                    cur_Y = j + common.dy[k]
                    while self.SIDE_LEN > cur_X >= 0 and self.SIDE_LEN > cur_Y >= 0:
                        if self.grid[cur_X][cur_Y] == 1 - turn:
                            count_other_cells += 1
                            cur_X += dx[k]
                            cur_Y += dy[k]
                        elif self.grid[cur_X][cur_Y] == turn:
                            count_my_cells += 1
                            break
                        else:
                            break
                    if count_my_cells > 0 and count_other_cells > 0:
                        valid_moves.append(i * self.SIDE_LEN + j)
                        break
        self.valid_moves = valid_moves
        return self.valid_moves

    def is_game_ended(self):
        """
        Returns true if the game already ended and false otherwise
        """

        count_white, count_black = self.get_cell_count()

        # One of them already lost all his cells
        if count_white == 0 or count_black == 0:
            return True

        # The board all is full (no empty cells)
        if count_white + count_black == self.SIDE_LEN * self.SIDE_LEN:
            return True

        # If no one can do any more moves
        if self.get_valid_moves(self.WHITE_CELL) == [] and self.get_valid_moves(self.BLACK_CELL) == []:
            return True

        # Otherwise the game still running
        return False

    def get_cell_count(self):
        """
        Returns 2 parameters, which is the number of 
        white and the number of black cells exists on the board
        """

        white = 0
        black = 0
        for i in range(self.SIDE_LEN):
            for j in range(self.SIDE_LEN):
                if self.grid[i][j] == self.WHITE_CELL:
                    white += 1
                elif self.grid[i][j] == self.BLACK_CELL:
                    black += 1
        return white, black

    def make_move(self, move_pos, turn):
        # TO DO
        i = move_pos[0]
        j = move_pos[1]
        for k in range(common.DIR_COUNT):
            count_my_cells = 0
            count_other_cells = 0
            cur_X = i + common.dx[k]
            cur_Y = j + common.dy[k]
            while self.SIDE_LEN > cur_X >= 0 and self.SIDE_LEN > cur_Y >= 0:
                if self.grid[cur_X][cur_Y] == 1 - turn:
                    count_other_cells += 1
                    cur_X += dx[k]
                    cur_Y += dy[k]
                elif self.grid[cur_X][cur_Y] == turn:
                    count_my_cells += 1
                    break
                else:
                    break
            if count_my_cells > 0 and count_other_cells > 0:
                cur_X = i + common.dx[k]
                cur_Y = j + common.dy[k]
                while self.SIDE_LEN > cur_X >= 0 and self.SIDE_LEN > cur_Y >= 0:
                    if self.grid[cur_X][cur_Y] == 1 - turn:
                        self.grid[cur_X][cur_Y] = turn
                        cur_X += dx[k]
                        cur_Y += dy[k]
                    else:
                        break
        self.grid[i][j] = turn

common.py

## common parameters used in the game
BLACK_CELL = 0
WHITE_CELL = 1
EMPTY_CELL = -1
SIDE_LEN = 8

## parameters allow the board class to get the 
## valid moves and update the grid after a move
DIR_COUNT = 8
dx = [-1, -1, -1, 0, 0, 1, 1, 1]
dy = [-1, 0, 1, -1, 1, -1, 0, 1]

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值