Beispiel #1
0
 def __init__(self):
     """
     the constactor of the game gui,and creating the first user's menu.
     """
     self._game_modes_options = {
         1: PERSON_VS_COMPUTER,
         2: PERSON_VS_PERSON,
         3: COMP_VS_COMP
     }
     self._player_colors = {1: 'red', 2: 'blue'}
     self._column = 0
     self._root = tk.Tk()
     self._disks = []
     self._game_logic = Game()
     self._choice = tk.StringVar()
     self._choice.set('choose game type, Default game is p vs p')
     self._menu = tk.OptionMenu(self._root, self._choice,
                                PERSON_VS_COMPUTER, PERSON_VS_PERSON,
                                COMP_VS_COMP)
     self._choose_button = tk.Button(self._root,
                                     text='press OK',
                                     command=self.init_single_game)
     self._choose_button.pack()
     self._menu.pack()
     self._ai_first = None
     self._ai_second = None
 def reset(self):
     """this function reset the board"""
     self.__c.delete("all")
     self.__c.create_image(0, 0, image=self.__backgroundimage, anchor=tk.NW)
     self.__game = Game()
     self.__board_state = self.create_board()
     self.__player_display_label.config(image=self.__down)
Beispiel #3
0
    def __init__(self, master):
        """
        Initialize an App object.
        :param master: The main root of the game
        """
        self.__master = master
        self.__master.protocol("WM_DELETE_WINDOW", self.__press_x)
        self.__master.geometry("850x550")
        self.__master.title(self.GAME_TITLE)
        self.__game = Game()

        self.__enter_frame = tk.Frame(self.__master,
                                      height=550,
                                      width=850,
                                      bg=self.BG)
        self.__game_frame = tk.Frame(self.__master,
                                     height=550,
                                     width=850,
                                     bg=self.BG)
        self.__board_canvas = tk.Canvas(self.__game_frame,
                                        height=450,
                                        width=550,
                                        highlightthickness=2,
                                        highlightbackground="black")
        self.__player1_canvas = tk.Canvas(self.__game_frame,
                                          height=130,
                                          width=100,
                                          highlightbackground=self.GOLD,
                                          highlightthickness=4,
                                          bg=self.BG)
        self.__player2_canvas = tk.Canvas(self.__game_frame,
                                          height=130,
                                          width=100,
                                          bg=self.BG,
                                          highlightthickness=2,
                                          highlightbackground="black")

        self.__available_rows = {
            col: self.ROWS_SIZE - 1
            for col in range(self.COLS_SIZE)
        }
        self.__ai_players = {1: None, 2: None}
        self.__circles_dict = {}
        self.__after_id = ""
        self.__entrance_frame()
Beispiel #4
0
 def reset(self):
     """
     the function that is resetting the game if the user chooses to
     play another game. filling the board with empty slots and the
     pointer to player 1 turn.
     and also creating a new game and updating the computers in that game.
     """
     for row in self._disks:
         for element in row:
             self._canvas.itemconfig(element, fill='white')
     self._game_logic = Game()
     self._canvas.itemconfig(
         self._pointer,
         fill=self._player_colors[self._game_logic.get_current_player()])
     if self._choice.get() == COMP_VS_COMP:
         self._ai_first.set_game(self._game_logic)
         self._ai_second.set_game(self._game_logic)
         self.comp_turn(self._ai_first)
     if self._choice.get() == PERSON_VS_COMPUTER:
         self._ai_first.set_game(self._game_logic)
Beispiel #5
0
 def __init__(self, root, users):
     """This function is a constructor for graphic game object"""
     self.__dir_path = os.path.dirname(os.path.realpath(__file__))
     self.__img1 = PhotoImage(file=self.__dir_path + '/EAsportslogo.png')
     self.__img2 = PhotoImage(file=self.__dir_path + '/_board.png')
     self.__cur_game = Game()
     self.__root = root
     if users:
         self.__ai = users
     else:
         self.WANT_PLAY = False
         return
     self.__can = self.create_canvas()
     self.__turns = []
     self.__cur_player = 0
     self.__label_img = self.post_background(self.__img1)
     self.__label_img = self.__root.after(3000, self.post_background,
                                          self.__img2)
     self.__buttons = []
     self.__root.after(3000, self.create_buttons)
     self.__ai_list = self.create_AI()
     self.__root.after(3050, self.whos_begin)
     self.WANT_PLAY = False
     self.__nonvalids = []
Beispiel #6
0
class Gui:
    def __init__(self):
        """
        the constactor of the game gui,and creating the first user's menu.
        """
        self._game_modes_options = {
            1: PERSON_VS_COMPUTER,
            2: PERSON_VS_PERSON,
            3: COMP_VS_COMP
        }
        self._player_colors = {1: 'red', 2: 'blue'}
        self._column = 0
        self._root = tk.Tk()
        self._disks = []
        self._game_logic = Game()
        self._choice = tk.StringVar()
        self._choice.set('choose game type, Default game is p vs p')
        self._menu = tk.OptionMenu(self._root, self._choice,
                                   PERSON_VS_COMPUTER, PERSON_VS_PERSON,
                                   COMP_VS_COMP)
        self._choose_button = tk.Button(self._root,
                                        text='press OK',
                                        command=self.init_single_game)
        self._choose_button.pack()
        self._menu.pack()
        self._ai_first = None
        self._ai_second = None

    def init_single_game(self):
        """
        the initiator of the first game, creating the game by the user's choices.
        creating the board and the instructions menu and the game itself.
        """
        top = tk.Frame(self._root, bg='burlywood4')
        instruction = tk.Label(
            top,
            text=
            "Move instructions:\n move right- right arrow\nmove left - left arrow\nshoot ball: Space",
            font=('Helvetica', 13))
        instruction.pack(side=tk.RIGHT)
        arba_beshora = tk.Label(top,
                                text="Four in a row",
                                font=('Helvetica', 10))
        arba_beshora.pack(side=tk.TOP)
        top.pack(side=tk.TOP, fill=tk.BOTH)
        self._canvas = tk.Canvas(top, bg='saddle brown', height=700, width=700)
        self._root.bind('<Left>', lambda event: self.move_pointer(-1, True))
        self._root.bind('<Right>', lambda event: self.move_pointer(1, True))
        self._root.bind('<space>', lambda event: self.one_turn(True))
        self._pointer = self._canvas.\
            create_oval(0, 0, 100, 100, fill='red', outline='red')
        self._canvas.pack()
        self.check_if_over()
        self._choose_button.pack_forget()
        self._menu.pack_forget()
        self.create_board()
        # creating the computers according the the user's choice
        if (self._choice.get() == COMP_VS_COMP):
            self._ai_first = AI(self._game_logic, 1)
            self._ai_second = AI(self._game_logic, 2)
            self.comp_turn(self._ai_first)
        elif (self._choice.get() == PERSON_VS_COMPUTER):
            self._ai_first = AI(self._game_logic, 2)

    def comp_turn(self, ai_player_x):
        """
        this function is creating the move of the computer,
        according to the ai, and creates it in a way that it is visible
        for the user if the game is comp vs comp.
        :param ai_player_x: an ai type.
        :return: None
        """
        # so the game wont sleep before its started.
        if not self._game_logic.is_board_empty():
            time.sleep(0.7)
        # finding the computer's move.
        comp_move = ai_player_x.find_legal_move()
        # if the function returns None, the board is full or 1 player won the game.
        if comp_move is None:
            self.check_if_over()
            return
        # moving the pointer to the place that the comp is playing the turn,
        # so we can see the comp turn visible.
        while self._column != comp_move:
            if self._column < comp_move:
                self.move_pointer(1)
            else:
                self.move_pointer(-1)
        self.one_turn()

    def reset(self):
        """
        the function that is resetting the game if the user chooses to
        play another game. filling the board with empty slots and the
        pointer to player 1 turn.
        and also creating a new game and updating the computers in that game.
        """
        for row in self._disks:
            for element in row:
                self._canvas.itemconfig(element, fill='white')
        self._game_logic = Game()
        self._canvas.itemconfig(
            self._pointer,
            fill=self._player_colors[self._game_logic.get_current_player()])
        if self._choice.get() == COMP_VS_COMP:
            self._ai_first.set_game(self._game_logic)
            self._ai_second.set_game(self._game_logic)
            self.comp_turn(self._ai_first)
        if self._choice.get() == PERSON_VS_COMPUTER:
            self._ai_first.set_game(self._game_logic)

    def one_turn(self, clicked=False):
        """
        this function is running one turn in
         the game, both user's turn and computer's
        turn if there are computers playing.
        :param clicked: a bool expression, which shows if the function
        launched from a click by the user, or by the computer.
        True if by user, False if by the computer.
        :return: None, but updates the board.
        """
        # so we wont be able to change the game of the computers.
        if (clicked and self._choice.get() == COMP_VS_COMP) or (
                clicked and self._ai_first
                and self._game_logic.get_current_player() == 2):
            return
        if self._game_logic.is_possible_move(self._column):
            position = self._game_logic.make_move(self._column)
            self._canvas.itemconfigure(self._disks[position[0]][position[1]],
                                       fill=self._canvas.itemcget(
                                           self._pointer, 'fill'))
            self._canvas.itemconfig(self._pointer,
                                    fill=self._player_colors[
                                        self._game_logic.get_current_player()])
            self._root.update()
        if (self._ai_first and self._ai_second) or \
                (self._ai_first and self._game_logic.get_current_player() == 2):
            self.comp_turn(self._ai_first)
        self.check_if_over()

    def check_if_over(self):
        """
        a function that checks if the game is over, if the board is full
        or if there is a winner.
        also this function asks the user if
         he would like to play another game,
        or if he wishes to exit. and the function
        does what the user asked.
        """
        winner = self._game_logic.get_winner()
        if winner is not None:
            if winner == 0:
                result = messagebox.askokcancel\
                    ("Hello ", "Its a tie" +
                     " Would you like to Play again?")
            else:
                result = messagebox.askokcancel(
                    "Hello ", "Player " + str(winner) + ' ' + "Won! " +
                    "Would you like to Play again?")
            if result:
                self.reset()
            else:
                exit()

    def move_pointer(self, direction, clicked=False):
        """
        this function moves the "pointer ball" which is the ball on top
        of the board.
        :param direction: -1 if moves to the left, 1 if moves to the right.
        :param clicked: if the function got called by a user click, or
        if the function called by the computer's turn.
        True if by the user's click, False if by the computer.
        :return: None
        """
        if clicked and self._choice.get() == COMP_VS_COMP:
            return
        if self._ai_first and clicked:
            if self._game_logic.get_current_player() == 2:
                return
        if self._column == 0 and direction == -1 or \
                self._column == 6 and direction == 1:
            return
        else:
            self._column += direction
            self._canvas.move(self._pointer, direction * 100, 0)
            self._root.update()
            time.sleep(0.2)

    def create_board(self):
        """
        this function creates a game board for the four in a row game,
        alse if creates a list of all the empty places in the board,
        and updates the disks list.
        """
        temporary_lst = []
        for i in range(6):
            for j in range(7):
                temporary_lst.append(
                    self._canvas.create_oval(0 + 100 * j,
                                             200 + 100 * i,
                                             100 + 100 * j,
                                             100 + 100 * i,
                                             fill='white',
                                             outline='black'))
            self._disks.append(temporary_lst)
            temporary_lst = []

    def run(self):
        """
        the function that starts the game, by the mainloop.
        :return:
        """
        self._root.mainloop()
Beispiel #7
0
#############################################################
# FILE : four_in_a_row.py
# WRITERs : Nir Amzaleg, Noa Moalem, nir_amzaleg, noamoa 206959686 ,208533554
# EXERCISE : intro2cs ex12 2019
# DESCRIPTION: This file create  GUI object with Game()
# object how run the four in a row game in fact.
#############################################################
from ex12.GUI import Gui
from ex12.game import Game

if __name__ == '__main__':
    game = Game()
    g = Gui(game)
Beispiel #8
0
class Gui:
    """
    this class create object from type gui that include:
    root - the current tkinter root
    users - list of the current players (AI / HUMAN)
    the class manage all the operate of the game and responsible to interface
    with the user
    """
    COLUMNS_DIC = {
        0: "column 1",
        1: "column 2",
        2: "column 3",
        3: "column 4",
        4: "column 5",
        5: "column 6",
        6: "column 7"
    }

    BALL_SIZE = 70
    WIDTH_SPACE = 30
    START_POINT = 25

    def __init__(self, root, users):
        """This function is a constructor for graphic game object"""
        self.__dir_path = os.path.dirname(os.path.realpath(__file__))
        self.__img1 = PhotoImage(file=self.__dir_path + '/EAsportslogo.png')
        self.__img2 = PhotoImage(file=self.__dir_path + '/_board.png')
        self.__cur_game = Game()
        self.__root = root
        if users:
            self.__ai = users
        else:
            self.WANT_PLAY = False
            return
        self.__can = self.create_canvas()
        self.__turns = []
        self.__cur_player = 0
        self.__label_img = self.post_background(self.__img1)
        self.__label_img = self.__root.after(3000, self.post_background,
                                             self.__img2)
        self.__buttons = []
        self.__root.after(3000, self.create_buttons)
        self.__ai_list = self.create_AI()
        self.__root.after(3050, self.whos_begin)
        self.WANT_PLAY = False
        self.__nonvalids = []

    def whos_begin(self):
        """the function checks whos begin. if AI is the first player to play
        so the function give a command to the game to start automatically"""
        if self.__ai:
            if self.__ai[0] is True:
                self.AI_move()

    def create_AI(self):
        """this function responsible for the create of the AI objects"""
        if not self.__ai:
            return
        ai_list = []
        if self.__ai[0] is True:
            ai_list.append(AI(self.__cur_game, 1))
        else:
            ai_list.append(None)
        if self.__ai[1] is True:
            ai_list.append(AI(self.__cur_game, 2))
        else:
            ai_list.append(None)
        return ai_list

    def create_canvas(self):
        """this function create the main canvas of the game screen and post
        him to the window"""
        canvas_width = 650
        canvas_height = 500
        can = Canvas(self.__root, width=canvas_width, height=canvas_height)
        can.grid(row=0, column=0, columnspan=7, rowspan=6, padx=5, pady=5)
        return can

    def create_buttons(self):
        """this function create all the game buttons
         and post them to the game screen"""
        for column in range(7):
            self.__buttons.append(
                Button(self.__root,
                       text=self.COLUMNS_DIC[column],
                       command=self._column_event(column)))
            self.__buttons[column].grid(row=7, column=column, sticky='N')

    def post_background(self, img):
        """this function post image to the canva"""
        self.__can.create_image(10, 5, anchor='nw', image=img)
        return img

    def _column_event(self, column):
        """this function is the command function of all the buttons.
        the function responsible to update the Game object and create
        oval in accordance to the column that pressed"""
        def column_pressed():
            row = self.look_for_row(column)
            self.__cur_game.make_move(column)
            if self.__cur_game.get_player_at(row, column) == 1:
                self.__turns.append(
                    self.__can.create_oval(self.START_POINT + column * 90,
                                           row * 80 + 10,
                                           self.START_POINT + column * 90 +
                                           self.BALL_SIZE,
                                           row * 80 + self.BALL_SIZE + 10,
                                           fill="BLUE"))
            else:
                self.__turns.append(
                    self.__can.create_oval(self.START_POINT + column * 90,
                                           row * 80 + 10,
                                           self.START_POINT + column * 90 +
                                           self.BALL_SIZE,
                                           row * 80 + self.BALL_SIZE + 10,
                                           fill="RED"))
            self.look_for_winner()
            self.__cur_player = (self.__cur_player + 1) % 2
            if self.__ai[self.__cur_player]:
                for button in self.__buttons:
                    button.config(state='disabled', bg="WHITE")
                self.__root.after(500, self.AI_move)

        return column_pressed

    def look_for_winner(self):
        """this function checks with the Game object if someone won the game
        and bold the winning ovals in the screen"""
        win_cor = self.__cur_game.win_cor()
        if win_cor:
            for cor in win_cor:
                column, row = cor[0], cor[1]
                self.__turns.append(
                    self.__can.create_oval(self.START_POINT + column * 90,
                                           row * 80 + 10,
                                           self.START_POINT + column * 90 +
                                           self.BALL_SIZE,
                                           row * 80 + self.BALL_SIZE + 10,
                                           fill="WHITE"))
            self.win_func(self.__cur_game.get_player_at(row, column))
        elif self.__cur_game.get_winner() == 0:
            self.win_func(0)

    def look_for_row(self, column):
        """this function get a column and look for empty row in
        that specific column to update"""
        for row in range(1, self.__cur_game.ROWS + 1):
            if self.__cur_game.get_player_at(self.__cur_game.ROWS - row,
                                             column) is None:
                if row == self.__cur_game.ROWS:
                    self.__nonvalids.append(column)
                    self.__buttons[column].config(state='disabled', bg="WHITE")
                return self.__cur_game.ROWS - row

    def AI_move(self):
        """this function manage the AI moves. the function look for col
        from the ai player and update the game"""
        if self.__cur_game.get_winner() is None:
            if self.__ai_list:
                column = self.__ai_list[self.__cur_player].find_legal_move()
            # row = self.look_for_row(column)
            if column is None:
                return
            column = self.__ai_list[self.__cur_player].find_legal_move()
            self._column_event(column)()
            if self.__ai[0] is False or self.__ai[1] is False:
                for column, button in enumerate(self.__buttons):
                    if column not in self.__nonvalids and\
                            self.__cur_game.get_winner() is None:
                        button.config(state='normal', bg="WHITE")

    def play_again(self):
        """the play again command function"""
        self.__root.destroy()
        self.WANT_PLAY = True

    def exit(self):
        """the exit command function"""
        self.__root.destroy()
        self.WANT_PLAY = False
        quit()

    def win_func(self, winner):
        """this function manage the win (finish) window. the function
        present to the user two optional buttons: play again or exit"""
        self.__ai_list = []
        for button in self.__buttons:
            button.config(state='disabled', bg="WHITE")
        window = Toplevel(self.__root)
        can = Canvas(window, width=435, height=600)
        can.grid(row=0, column=0, columnspan=7, rowspan=6, padx=5, pady=5)
        self.img = PhotoImage(file='ex12/winner_img.png')
        self.label = can.create_image(0, 0, anchor=NW, image=self.img)
        winner_img = self.status_num(window, winner)
        can.create_image(0, 470, anchor=NW, image=winner_img)
        can.photo = winner_img
        can.config(scrollregion=can.bbox(ALL))
        play_again = Button(window, text='PLAY AGAIN', command=self.play_again)
        play_again.grid(row=4, column=0, sticky='N', ipadx=10, ipady=20)
        exit = Button(window, text='I WANT TO GET OUT!', command=self.exit)
        exit.grid(row=4, column=6, sticky='N', ipadx=10, ipady=20)

    def status_num(self, window, winner):
        """this function load the correct img to the winning window in
        accordance to the winner identity"""
        if winner == 1:
            window.wm_title("Player 1 won!")
            winner_img = PhotoImage(file='ex12/player_one_won.png')
        if winner == 2:
            window.wm_title("Player 2 won!")
            winner_img = PhotoImage(file='ex12/player_two_won.png')
        if winner == 0:
            window.wm_title("It was a draw!")
            winner_img = PhotoImage(file='ex12/draw.png')
        return winner_img
Beispiel #9
0
class App:
    ROWS_SIZE = 6
    COLS_SIZE = 7
    PLAYERS = {1: "red4", 2: "blue4"}
    FONT = "Tex Gyre Schola Math"
    BG = "papaya whip"
    GOLD = "dark goldenrod"
    GAME_TITLE = "four in a row"
    QUIT_TITLE = "Game Over"
    GAME_M = "** FOUR IN A ROW **"
    CHOOSE_M = "CHOOSE PLAYERS:"
    GOODLUCK_M = "GOOD LUCK!"
    DRAW = "IT'S A TIE!"
    PLAY_AGAIN_M = "PLAY AGAIN"
    QUIT_M = "QUIT"
    PLAYER1_M = "PLAYER \n      1"
    PLAYER2_M = "PLAYER \n      2"
    MENU_M = "MAIN MENU"
    COMP_VS_COMP = "ex12/compVsComp.jpg"
    COMP_VS_MAN = "ex12/compVsMan.jpg"
    MAN_VS_MAN = "ex12/manVsMan.jpg"
    MAN_VS_COMP = "ex12/manVsComp.jpg"
    WOOD_BG = "ex12/woodBG.jpg"

    def __init__(self, master):
        """
        Initialize an App object.
        :param master: The main root of the game
        """
        self.__master = master
        self.__master.protocol("WM_DELETE_WINDOW", self.__press_x)
        self.__master.geometry("850x550")
        self.__master.title(self.GAME_TITLE)
        self.__game = Game()

        self.__enter_frame = tk.Frame(self.__master,
                                      height=550,
                                      width=850,
                                      bg=self.BG)
        self.__game_frame = tk.Frame(self.__master,
                                     height=550,
                                     width=850,
                                     bg=self.BG)
        self.__board_canvas = tk.Canvas(self.__game_frame,
                                        height=450,
                                        width=550,
                                        highlightthickness=2,
                                        highlightbackground="black")
        self.__player1_canvas = tk.Canvas(self.__game_frame,
                                          height=130,
                                          width=100,
                                          highlightbackground=self.GOLD,
                                          highlightthickness=4,
                                          bg=self.BG)
        self.__player2_canvas = tk.Canvas(self.__game_frame,
                                          height=130,
                                          width=100,
                                          bg=self.BG,
                                          highlightthickness=2,
                                          highlightbackground="black")

        self.__available_rows = {
            col: self.ROWS_SIZE - 1
            for col in range(self.COLS_SIZE)
        }
        self.__ai_players = {1: None, 2: None}
        self.__circles_dict = {}
        self.__after_id = ""
        self.__entrance_frame()

    def __entrance_frame(self):
        """
        Adds all the labels and buttons to the entrance frame, in the window
        that opens at the beginning of the game.
        :return: None
        """
        self.__enter_frame.pack(expand=True, fill=tk.BOTH)
        welcome_label = tk.Label(self.__enter_frame,
                                 text=self.GAME_M,
                                 bg=self.BG,
                                 font=(self.FONT, 55, "bold"))
        welcome_label.place(relx=0.5, rely=0.02, anchor=tk.N)

        choose_label = tk.Label(self.__enter_frame,
                                text=self.CHOOSE_M,
                                bg=self.BG,
                                font=(self.FONT, 35))
        choose_label.place(relx=0.5, rely=0.18, anchor=tk.N)

        goodluck_label = tk.Label(self.__enter_frame,
                                  text=self.GOODLUCK_M,
                                  bg=self.BG,
                                  font=(self.FONT, 35))
        goodluck_label.place(relx=0.5, rely=0.88, anchor=tk.N)

        comp_vs_comp = Image.open(self.COMP_VS_COMP).resize((220, 140),
                                                            Image.ANTIALIAS)
        comp_vs_comp = ImageTk.PhotoImage(comp_vs_comp)
        cvsc_button = tk.Button(self.__enter_frame,
                                image=comp_vs_comp,
                                bg="black",
                                command=self.__change_to_gamescreen(
                                    True, True))
        cvsc_button.photo = comp_vs_comp
        cvsc_button.place(relx=0.18, rely=0.44, anchor=tk.W)

        comp_vs_man = Image.open(self.COMP_VS_MAN).resize((220, 140),
                                                          Image.ANTIALIAS)
        comp_vs_man = ImageTk.PhotoImage(comp_vs_man)
        cvsm_button = tk.Button(self.__enter_frame,
                                image=comp_vs_man,
                                bg="black",
                                command=self.__change_to_gamescreen(
                                    False, True))
        cvsm_button.photo = comp_vs_man
        cvsm_button.place(relx=0.18, rely=0.72, anchor=tk.W)

        man_vs_man = Image.open(self.MAN_VS_MAN).resize((220, 140),
                                                        Image.ANTIALIAS)
        man_vs_man = ImageTk.PhotoImage(man_vs_man)
        mvsm_button = tk.Button(self.__enter_frame,
                                image=man_vs_man,
                                bg="black",
                                command=self.__change_to_gamescreen(
                                    False, False))
        mvsm_button.photo = man_vs_man
        mvsm_button.place(relx=0.82, rely=0.44, anchor=tk.E)

        man_vs_comp = Image.open(self.MAN_VS_COMP).resize((220, 140),
                                                          Image.ANTIALIAS)
        man_vs_comp = ImageTk.PhotoImage(man_vs_comp)
        mvsc_button = tk.Button(self.__enter_frame,
                                image=man_vs_comp,
                                bg="black",
                                command=self.__change_to_gamescreen(
                                    True, False))
        mvsc_button.photo = man_vs_comp
        mvsc_button.place(relx=0.82, rely=0.72, anchor=tk.E)

    def __change_to_gamescreen(self, player1, player2):
        """
        This functions changes the screen from the entrance frame to the game
        frame, and create AI object for every player that supposed to be AI.
        :param player1: True if player 1 supposed to be AI, and False if not.
        :param player2: True if player 2 supposed to be AI, and False if not.
        :return: The function "gamescreen".
        """
        def gamescreen():
            self.__enter_frame.destroy()
            if player1:
                self.__ai_players[1] = AI(self.__game, 1)
            if player2:
                self.__ai_players[2] = AI(self.__game, 2)
            self.game_frame()

        return gamescreen

    def game_frame(self):
        """
        Adds the board canvas, the two players canvases and the "main menu"
        button to the game frame.
        :return: None
        """
        self.__game_frame.pack(expand=True, fill=tk.BOTH)
        game_label = tk.Label(self.__game_frame,
                              text=self.GAME_M,
                              bg=self.BG,
                              font=(self.FONT, 35, "bold"))
        game_label.place(relx=0.5, rely=0.01, anchor=tk.N)

        self.__player1_canvas.place(relx=0.97, rely=0.3, anchor=tk.E)
        self.__player2_canvas.place(relx=0.03, rely=0.3, anchor=tk.W)
        self.__player1_canvas.create_text((57, 30),
                                          text=self.PLAYER1_M,
                                          font=(self.FONT, 15, "bold"))
        self.__player1_canvas.create_oval(23,
                                          60,
                                          83,
                                          120,
                                          fill=self.PLAYERS[1])
        self.__player2_canvas.create_text((57, 30),
                                          text=self.PLAYER2_M,
                                          font=(self.FONT, 15, "bold"))
        self.__player2_canvas.create_oval(23,
                                          60,
                                          83,
                                          120,
                                          fill=self.PLAYERS[2])

        self.__board_canvas.place(relx=0.5, rely=0.15, anchor=tk.N)
        wood_bg = Image.open(self.WOOD_BG).resize((560, 460), Image.ANTIALIAS)
        wood_bg = ImageTk.PhotoImage(wood_bg)
        self.__board_canvas.photo = wood_bg
        self.__board_canvas.create_image(0, 0, image=wood_bg, anchor=tk.NW)
        self.__make_circles(self.ROWS_SIZE, self.COLS_SIZE)
        restart_button = tk.Button(self.__game_frame,
                                   width=11,
                                   height=2,
                                   text=self.MENU_M,
                                   bg=self.BG,
                                   font=(self.FONT, 10),
                                   command=self.__play_again(
                                       self.__game_frame))

        restart_button.place(relx=0.02, rely=0.9, anchor=tk.SW)

        if self.__ai_players[1]:
            self.__put_disk_in_col(self.__ai_players[1].find_legal_move())
        self.__board_canvas.bind("<Motion>", self.__move_cursor)
        self.__board_canvas.bind("<Button-1>", self.__put_disc)

    def __make_circles(self, rows_size, cols_size):
        """
        Adds circles to the board canvas, and to the circles dictionary.
        :param rows_size: The cols' amount in the board.
        :param cols_size: The rows' amount in the board.
        :return: None
        """
        for row in range(rows_size):
            for col in range(cols_size):
                circle = self.__board_canvas.create_oval(35 + col * 70,
                                                         25 + row * 70,
                                                         95 + col * 70,
                                                         85 + row * 70,
                                                         fill=self.BG)
                self.__circles_dict[(row, col)] = circle

    def __play_again(self, trans_root):
        """
        This function cancels the after' if there is one at the time, destroys
        the trans root and the main root (to start the game from the
        beginning).
        :param trans_root: The transport root to destroy
        :return: The "play_again_h" function
        """
        def play_again_h():
            if self.__after_id:
                self.__master.after_cancel(self.__after_id)
            trans_root.destroy()
            self.__master.destroy()

        return play_again_h

    def __move_cursor(self, event):
        """
        Checks if the cursor is on one of the columns. If it is, the function
        will fill the first available circle with the color of the current
        player.
        :param event: The event of the cursor moving on the board canvas
        :return: None
        """
        if not self.__ai_players[self.__game.get_current_player()] \
                and not self.__game.get_winner():
            x_coor, y_coor = event.x, event.y
            # check if it's not in the margins or between the columns.
            if y_coor in range(25, 435) or x_coor % 70 in range(26, 35):
                col = (x_coor - 35) // 70
            else:
                col = -1
            cur_color = self.PLAYERS[self.__game.get_current_player()]
            if col in range(self.COLS_SIZE) and col not in [-1, 7]:
                row = self.__available_rows[col]
                if row >= 0:
                    circ = self.__circles_dict[(row, col)]
                    self.__board_canvas.itemconfig(circ, fill=cur_color)

            # fill all the other circles with the background color.
            for c, av_row in self.__available_rows.items():
                if c != col and av_row >= 0:
                    self.__board_canvas.itemconfig(self.__circles_dict[(av_row,
                                                                        c)],
                                                   fill=self.BG)

    def __put_disc(self, event):
        """
        If the current player is not an AI player, the function will put the
        disc in the column that was pressed.
        :param event: The event of clicking on the mouse
        :return: None
        """
        if not self.__ai_players[self.__game.get_current_player()]:
            x_coor = event.x
            col = (x_coor - 35) // 70
            if col in range(self.COLS_SIZE) or x_coor % 70 not in \
                    range(26, 35):
                self.__put_disk_in_col(col)

    def __put_disk_in_col(self, col):
        """
        If it's legal to put a disc in the given column, the function will fill
        the first available circle in the given color with the color of the
        current player. If no one won in this turn and the next player is an AI
        player, the function will call itself after 700 ms.
        :param col: The col that the player want to put the disc in
        :return: None
        """
        cur_player = self.__game.get_current_player()
        cur_color = self.PLAYERS[cur_player]
        row = self.ROWS_SIZE - 1
        try:
            while self.__game.get_player_at(row, col):
                row -= 1
            self.__game.make_move(col)
        except:
            return
        self.__board_canvas.itemconfig(self.__circles_dict[(row, col)],
                                       fill=cur_color)
        self.__available_rows[col] -= 1
        self.__check_win()

        cur_player = self.__game.get_current_player()
        self.__current_player(cur_player)
        if self.__ai_players[cur_player]:
            af_id = self.__master.after(700, self.__ai_turn(cur_player))
            self.__after_id = af_id

    def __ai_turn(self, player):
        """
        If there are legal moves (no one won and the board isn't full), the
        function will col the "put_disc_in_col" function with the col the AI
        gave.
        :param player: The current player
        :return: The "ai_helper" function
        """
        def ai_helper():
            try:
                self.__put_disk_in_col(
                    self.__ai_players[player].find_legal_move())
            except:
                pass

        return ai_helper

    def __current_player(self, player):
        """
        This function markers the canvas of the current player.
        :param player: The current player
        :return: None
        """
        if player == 1:
            self.__player1_canvas.config(highlightbackground=self.GOLD,
                                         highlightthickness=4)
            self.__player2_canvas.config(highlightbackground="black",
                                         highlightthickness=2)
        else:
            self.__player2_canvas.config(highlightbackground=self.GOLD,
                                         highlightthickness=4)
            self.__player1_canvas.config(highlightbackground="black",
                                         highlightthickness=2)

    def __check_win(self):
        """
        Checks if the game is over and if one of the players won, or the board
        is empty. If there is a winner, the function will marker the circles
        that gave the win. After that, it will open the transport window.
        :return: None
        """
        winner = self.__game.get_winner()
        if winner in [0, 1, 2]:
            if winner in self.PLAYERS:
                win_coor = self.__game.get_win_coordinates()
                for coor in win_coor:
                    self.__board_canvas.itemconfig(self.__circles_dict[coor],
                                                   width=3,
                                                   outline=self.GOLD)
            self.__trans_window()

    def __trans_window(self):
        """
        Create a new window, that say why the game is over, and asks the player
        if he want to play again or to quit.
        :return: None
        """
        trans_window = tk.Tk()
        trans_window.protocol("WM_DELETE_WINDOW", trans_window)
        trans_window.geometry("300x150")
        trans_window.title(self.QUIT_TITLE)
        winner = self.__game.get_winner()
        if winner in self.PLAYERS:
            txt = "PLAYER " + str(winner) + " HAS WON!"
            color = self.PLAYERS[winner]
        else:
            txt = self.DRAW
            color = "black"
        trans_frame = tk.Frame(trans_window, width=300, height=200, bg=color)
        trans_frame.pack(expand=True, fill=tk.BOTH)
        trans_label = tk.Label(trans_frame,
                               text=txt,
                               bg=color,
                               font=(self.FONT, 15, "bold"),
                               fg=self.BG)
        trans_label.place(relx=0.5, rely=0.01, anchor=tk.N)
        play_again_button = tk.Button(trans_frame,
                                      width=11,
                                      height=2,
                                      text=self.PLAY_AGAIN_M,
                                      bg=self.BG,
                                      font=(self.FONT, 10),
                                      command=self.__play_again(trans_window))

        quit_button = tk.Button(trans_frame,
                                width=11,
                                height=2,
                                text=self.QUIT_M,
                                bg=self.BG,
                                font=(self.FONT, 10),
                                command=quit)
        play_again_button.place(relx=0.45, rely=0.8, anchor=tk.SE)
        quit_button.place(relx=0.55, rely=0.8, anchor=tk.SW)

    def __press_x(self):
        """
        Create a new window that asks the player if he is sure he want to exit
        the game.
        :return: None
        """
        if messagebox.askokcancel("Quit", "Do you want to quit?"):
            exit()
 def move():
     self.__mainscreen.destroy()
     self.__game = Game()
     MyConnectFour(self.__root, self.__game, num)
Beispiel #11
0
import tkinter as tk