예제 #1
0
class WindowUserInterface:
    def __init__(self):
        player1 = Player('Helen', 'P')
        player2 = Player('Bob', 'M')
        self.font_color = 'AntiqueWhite2'
        self.game = ChessGame(player1, player2)
        self.main_window = Tk()
        self.main_window.configure(background=self.font_color)
        self.main_window.title("Chess")
        self.CHESS_PIECE_IMAGES = {}
        self.empty_image = ImageTk.PhotoImage(Image.open('Empty_Image.png'))
        for piece_type in ChessPieceType:
            for color in ChessColor:
                self.CHESS_PIECE_IMAGES[str(color)+'_'+str(piece_type)] = Image.open(str(color)+'_'+str(piece_type)+'.png')
        self.first_chose_was_done = False
        self.source_coordinates = None
        self.check_shown = False
        # self.result_notation_text = ''

    def get_image(self, chess_piece):
        return self.CHESS_PIECE_IMAGES[str(chess_piece)]

    def get_square_tk_color(self, i, j):
        if self.game.board.get_square_color(i, j) == ChessColor.Black:
            return 'sienna'
        else:
            return 'khaki'

    def set_boards(self):
        for x in range(1, BOARD_SIZE+1):
            top_letter = Label(self.main_window, text=LETTERS_ON_BOARD[x-1], bg=self.font_color)
            top_letter.grid(row=0, column=x)
            down_letter = Label(self.main_window, text=LETTERS_ON_BOARD[x-1], bg=self.font_color)
            down_letter.grid(row=9, column=x)
        for y in range(BOARD_SIZE, 0, -1):
            left_letter = Label(self.main_window, text=y, bg=self.font_color)
            left_letter.grid(row=abs(y-BOARD_SIZE)+1, column=0)
            right_letter = Label(self.main_window, text=y, bg=self.font_color)
            right_letter.grid(row=abs(y-BOARD_SIZE)+1, column=BOARD_SIZE+1)

    def set_or_destroy_check_message(self):
        if self.was_mate():
            return 0
        for color in ChessColor:
            if self.game.is_check(color) and self.check_shown == False:
                self.check_message = Label(self.frame_for_data, text='Check for '+str(color), bg=self.font_color, width=20, height=1, font="Verdana 13 bold")
                self.check_message.grid(row=0, column=1)
                self.check_shown = True
        if self.check_shown and not (self.game.is_white_check or self.game.is_black_check):
            self.check_message.destroy()
            self.check_shown = False

    def was_mate(self):
        for color in ChessColor:
            if self.game.is_mate(color):
                self.end_of_game(color.get_another_color())
                return True

    def save_notation(self):
        # with open("notation.txt", "w") as out:
        #     print(self.game.result_notation_text, file=out)
        self.save_file(self.game.result_notation_text)

    def open_new_game(self):
        self.main_window.destroy()
        new = WindowUserInterface()
        new.show()

    def end_of_game(self, winner_color):
        frame_for_mate_message = Frame(self.main_window, bg='', height=50)
        frame_for_mate_message.grid(row=1, column=1, columnspan=8, rowspan=8)

        mate_message = Label(frame_for_mate_message, text=str(winner_color)+' win!', padx=80, font="Verdana 40 bold")
        mate_message.pack(side='top')

        # save_button = Button(frame_for_mate_message, text='Save notation', command=self.save_notation)
        # save_button.pack(side='left')
        #
        # new_game_button = Button(frame_for_mate_message, text='New game', command=self.open_new_game)
        # new_game_button.pack(side='right')

        for i in range(BOARD_SIZE):
            for j in range(BOARD_SIZE):
                self.labels[i+1][j+1].unbind("<Button 1>")

    def click_handler(self, x, y):
        if self.first_chose_was_done:
            (source_x, source_y) = self.source_coordinates
            destination_x, destination_y = (x, y)

            if (source_x, source_y) == (destination_x, destination_y):
                self.source_coordinates = None
                self.first_chose_was_done = False
                return 0

            if not (self.game.board.is_empty(source_x, source_y) or self.game.board.is_empty(destination_x, destination_y)):
                if self.game.board.get_piece(source_x, source_y).get_color() == self.game.board.get_piece(destination_x, destination_y).get_color():
                    self.source_coordinates = (destination_x, destination_y)
                    self.first_chose_was_done = True
                    return 0

            if self.game.is_move_correct(source_x, source_y, destination_x, destination_y):
                self.first_chose_was_done = False
                self.game.previous_board = copy.deepcopy(self.game.board)
                self.game.move(source_x, source_y, destination_x, destination_y)
                self.set_or_destroy_check_message()
                self.show_this_squares(self.game.squares_changed_last_move())
                self.show_whose_turn()
                # print('From '+str(source_x)+str(source_y)+'to'+str(destination_x)+str(destination_y))
            else:
                self.source_coordinates = None
                self.first_chose_was_done = False
                self.show_mistake('Wrong move!')
        else:
            if self.game.board.is_empty(x, y):
                self.show_mistake('You can\'t go from empty square')
            else:
                if self.game.whose_turn() != self.game.board.get_piece(x, y).get_color():
                    self.show_mistake(str(self.game.whose_turn())+' player\'s turn!')
                else:
                    self.first_chose_was_done = True
                    self.source_coordinates = (x, y)

    def show_mistake(self, message):
        mistake_window = Toplevel()
        mistake_message = Label(mistake_window, text=message)
        mistake_message.pack()
        mistake_window.geometry('200x90+700+355')

    def show_whose_turn(self):
        self.area_whose_turn['text'] = 'Turn for ' + str(self.game.whose_turn())

    def save_file(self, saving_text):
        file = tkFileDialog.SaveAs(self.main_window, filetypes=[('*.txt files', '.txt')]).show()
        if file == '':
            return
        if not file.endswith(".txt"):
            file += ".txt"
        open(file, 'wt').write(saving_text)

    def save_game(self):
        encoded_game = jsonpickle.encode(self.game)
        # file = tkFileDialog.SaveAs(self.main_window, filetypes=[('*.txt files', '.txt')]).show()
        # if file == '':
        #     return
        # if not file.endswith(".txt"):
        #     file += ".txt"
        # open(file, 'wt').write(encoded_game)
        self.save_file(encoded_game)

    def recursive_function_for_fields(self, pending_object, object_in_normal_game):
        a = {}
        try:
            a = object_in_normal_game.__dict__.keys()
        except AttributeError:
            pass
        for field in a:
            if field.startswith('__') and field.endswith('__'):
                continue
            try:
                if type(getattr(pending_object, field)) != type(getattr(object_in_normal_game, field)):
                    print('False1')
                    return False
            except AttributeError:
                print('False2')
                return False
            print(field)
            if not self.recursive_function_for_fields(getattr(pending_object, field), getattr(object_in_normal_game, field)):
                return False
        return True

    def check_board(self, pending_board):
        for i in range(BOARD_SIZE):
            for j in range(BOARD_SIZE):
                if not pending_board.is_empty(i, j):
                    pending_piece = pending_board.get_piece(i, j)
                    if not self.recursive_function_for_fields(pending_piece, ChessPiece(ChessColor.White, ChessPieceType.Bishop)):
                        print('False8')
                        return False
        return True

    def loaded_game_is_correct(self):
        game_for_check = ChessGame(Player('A', 'B'), Player('C', 'D'))
        if type(self.game) != ChessGame:
            return False

        if not self.recursive_function_for_fields(self.game, game_for_check):
            return False

        if not self.check_board(self.game.board):
            return False

        if type(self.game.board) != ChessBoard or type(self.game.previous_board) != ChessBoard:
            print('False5')
            return False
        if type(self.game.player_black) != Player or type(self.game.player_white) != Player:
            print('False6')
            return False
        return True

    def load_game(self):
        encoded_game = self.load_file()
        if encoded_game is None:
            return
        try:
            self.game = jsonpickle.decode(encoded_game)
        except Exception:
            self.show_mistake('Can\'t open game file')
            return
        if not self.loaded_game_is_correct():
            self.show_mistake('Object in file is not a chess game')
            return
        try:
            self.start_frame.destroy()
        except AttributeError:
            pass

        self.show()

    def load_file(self):
        file = tkFileDialog.Open(self.main_window, filetypes=[('*.txt files', '.txt')]).show()
        if file == '':
            return
        return open(file, 'r').read()

    def place_main_window(self, width, height):
        screen_width = self.main_window.winfo_screenwidth()
        screen_height = self.main_window.winfo_screenheight()
        x_coordinate = screen_width/2-width/2
        y_coordinate = screen_height/2 - height/2-20
        self.main_window.geometry('%dx%d+%d+%d' % (width, height, x_coordinate, y_coordinate))

    def show_this_squares(self, array):
        for (i, j) in array:
            if not self.game.board.is_empty(i, j):
                piece = self.game.board.get_piece(i, j)
                img = self.get_image(piece)
                img = ImageTk.PhotoImage(img)
                self.labels[i+1][j+1]['image'] = img
                self.labels[i+1][j+1].image = img
            else:
                self.labels[i+1][j+1]['image'] = self.empty_image
                self.labels[i+1][j+1].image = self.empty_image

    def show(self):
        self.frames = [[Frame(self.main_window, height=SQUARE_SIZE, width=SQUARE_SIZE, bd=0) for j in range(BOARD_SIZE + 1)] for i in
                      range(BOARD_SIZE + 1)]
        self.labels = [[Label(self.frames[i][j], width=SQUARE_SIZE-10, height=SQUARE_SIZE-10) for j in range(BOARD_SIZE + 1)] for i in range(BOARD_SIZE+1)]
        self.set_boards()
        for i in range(BOARD_SIZE):
            for j in range(BOARD_SIZE):
                handler = lambda g, ii=i, jj=j: self.click_handler(ii, jj)

                self.frames[i+1][j+1]['bg'] = self.get_square_tk_color(i, j)
                self.frames[i+1][j+1].bind("<Button-1>", handler)
                self.frames[i+1][j+1].grid(row=abs(j+1-BOARD_SIZE)+1, column=i+1, sticky=S+W+N+E)

                self.labels[i+1][j+1]['bg'] = self.get_square_tk_color(i, j)
                self.labels[i+1][j+1].bind("<Button-1>", handler)
                self.labels[i+1][j+1].pack(fill='both')

        self.frame_for_data = Frame(self.main_window, bd=1, bg=self.font_color)
        self.frame_for_data.grid(column=1, row=10, columnspan=12, sticky=N)

        self.area_whose_turn = Label(self.frame_for_data, text='Turn for ' + str(self.game.whose_turn()), bg=self.font_color, width=59)
        self.area_whose_turn.grid(row=1, column=1, rowspan=1)

        self.save_button = Button(self.frame_for_data, text='Save game', command=self.save_game, width=11)
        self.save_button.grid(row=0, column=2)

        self.open_new_button = Button(self.frame_for_data, text='Open new game', command=self.open_new_game)
        self.open_new_button.grid(row=1, column=0, rowspan=1)

        self.place_main_window(618, 720)

        self.load_game_button = Button(self.frame_for_data, text='Load game', command=self.load_game, width=11)
        self.load_game_button.grid(row=1, column=2)

        self.save_notation_button = Button(self.frame_for_data, text='Save notation', command=self.save_notation, width=11)
        self.save_notation_button.grid(row=2, column=2)

        squares_array = []
        for i in range(BOARD_SIZE):
            for j in range(BOARD_SIZE):
                squares_array.append((i, j))
        self.show_this_squares(squares_array)

    def show_start_view(self):
        self.start_frame = Frame(self.main_window, bg=self.font_color, bd=16)
        self.place_main_window(220, 60)
        self.start_frame.grid(row=0, column=0)
        load_button = Button(self.start_frame, text='load saved game', command=self.load_game)
        load_button.grid(row=1, column=2)
        new_game_button = Button(self.start_frame, text='start new game', command=self.open_new_game)
        new_game_button.grid(row=1, column=1)

    def loop(self):
        self.main_window.mainloop()
        pass
예제 #2
0
class WindowUserInterface:
    def __init__(self):
        player1 = Player('Helen', 'P')
        player2 = Player('Bob', 'M')
        self.font_color = 'AntiqueWhite2'
        self.game = ChessGame(player1, player2)
        self.main_window = Tk()
        self.main_window.configure(background=self.font_color)
        self.main_window.title("Chess")
        self.CHESS_PIECE_IMAGES = {}
        self.empty_image = ImageTk.PhotoImage(Image.open('Empty_Image.png'))
        for piece_type in ChessPieceType:
            for color in ChessColor:
                self.CHESS_PIECE_IMAGES[str(color) + '_' +
                                        str(piece_type)] = Image.open(
                                            str(color) + '_' +
                                            str(piece_type) + '.png')
        self.first_chose_was_done = False
        self.source_coordinates = None
        self.check_shown = False
        # self.result_notation_text = ''

    def get_image(self, chess_piece):
        return self.CHESS_PIECE_IMAGES[str(chess_piece)]

    def get_square_tk_color(self, i, j):
        if self.game.board.get_square_color(i, j) == ChessColor.Black:
            return 'sienna'
        else:
            return 'khaki'

    def set_boards(self):
        for x in range(1, BOARD_SIZE + 1):
            top_letter = Label(self.main_window,
                               text=LETTERS_ON_BOARD[x - 1],
                               bg=self.font_color)
            top_letter.grid(row=0, column=x)
            down_letter = Label(self.main_window,
                                text=LETTERS_ON_BOARD[x - 1],
                                bg=self.font_color)
            down_letter.grid(row=9, column=x)
        for y in range(BOARD_SIZE, 0, -1):
            left_letter = Label(self.main_window, text=y, bg=self.font_color)
            left_letter.grid(row=abs(y - BOARD_SIZE) + 1, column=0)
            right_letter = Label(self.main_window, text=y, bg=self.font_color)
            right_letter.grid(row=abs(y - BOARD_SIZE) + 1,
                              column=BOARD_SIZE + 1)

    def set_or_destroy_check_message(self):
        if self.was_mate():
            return 0
        for color in ChessColor:
            if self.game.is_check(color) and self.check_shown == False:
                self.check_message = Label(self.frame_for_data,
                                           text='Check for ' + str(color),
                                           bg=self.font_color,
                                           width=20,
                                           height=1,
                                           font="Verdana 13 bold")
                self.check_message.grid(row=0, column=1)
                self.check_shown = True
        if self.check_shown and not (self.game.is_white_check
                                     or self.game.is_black_check):
            self.check_message.destroy()
            self.check_shown = False

    def was_mate(self):
        for color in ChessColor:
            if self.game.is_mate(color):
                self.end_of_game(color.get_another_color())
                return True

    def save_notation(self):
        # with open("notation.txt", "w") as out:
        #     print(self.game.result_notation_text, file=out)
        self.save_file(self.game.result_notation_text)

    def open_new_game(self):
        self.main_window.destroy()
        new = WindowUserInterface()
        new.show()

    def end_of_game(self, winner_color):
        frame_for_mate_message = Frame(self.main_window, bg='', height=50)
        frame_for_mate_message.grid(row=1, column=1, columnspan=8, rowspan=8)

        mate_message = Label(frame_for_mate_message,
                             text=str(winner_color) + ' win!',
                             padx=80,
                             font="Verdana 40 bold")
        mate_message.pack(side='top')

        # save_button = Button(frame_for_mate_message, text='Save notation', command=self.save_notation)
        # save_button.pack(side='left')
        #
        # new_game_button = Button(frame_for_mate_message, text='New game', command=self.open_new_game)
        # new_game_button.pack(side='right')

        for i in range(BOARD_SIZE):
            for j in range(BOARD_SIZE):
                self.labels[i + 1][j + 1].unbind("<Button 1>")

    def click_handler(self, x, y):
        if self.first_chose_was_done:
            (source_x, source_y) = self.source_coordinates
            destination_x, destination_y = (x, y)

            if (source_x, source_y) == (destination_x, destination_y):
                self.source_coordinates = None
                self.first_chose_was_done = False
                return 0

            if not (self.game.board.is_empty(source_x, source_y)
                    or self.game.board.is_empty(destination_x, destination_y)):
                if self.game.board.get_piece(
                        source_x,
                        source_y).get_color() == self.game.board.get_piece(
                            destination_x, destination_y).get_color():
                    self.source_coordinates = (destination_x, destination_y)
                    self.first_chose_was_done = True
                    return 0

            if self.game.is_move_correct(source_x, source_y, destination_x,
                                         destination_y):
                self.first_chose_was_done = False
                self.game.previous_board = copy.deepcopy(self.game.board)
                self.game.move(source_x, source_y, destination_x,
                               destination_y)
                self.set_or_destroy_check_message()
                self.show_this_squares(self.game.squares_changed_last_move())
                self.show_whose_turn()
                # print('From '+str(source_x)+str(source_y)+'to'+str(destination_x)+str(destination_y))
            else:
                self.source_coordinates = None
                self.first_chose_was_done = False
                self.show_mistake('Wrong move!')
        else:
            if self.game.board.is_empty(x, y):
                self.show_mistake('You can\'t go from empty square')
            else:
                if self.game.whose_turn() != self.game.board.get_piece(
                        x, y).get_color():
                    self.show_mistake(
                        str(self.game.whose_turn()) + ' player\'s turn!')
                else:
                    self.first_chose_was_done = True
                    self.source_coordinates = (x, y)

    def show_mistake(self, message):
        mistake_window = Toplevel()
        mistake_message = Label(mistake_window, text=message)
        mistake_message.pack()
        mistake_window.geometry('200x90+700+355')

    def show_whose_turn(self):
        self.area_whose_turn['text'] = 'Turn for ' + str(
            self.game.whose_turn())

    def save_file(self, saving_text):
        file = tkFileDialog.SaveAs(self.main_window,
                                   filetypes=[('*.txt files', '.txt')]).show()
        if file == '':
            return
        if not file.endswith(".txt"):
            file += ".txt"
        open(file, 'wt').write(saving_text)

    def save_game(self):
        encoded_game = jsonpickle.encode(self.game)
        # file = tkFileDialog.SaveAs(self.main_window, filetypes=[('*.txt files', '.txt')]).show()
        # if file == '':
        #     return
        # if not file.endswith(".txt"):
        #     file += ".txt"
        # open(file, 'wt').write(encoded_game)
        self.save_file(encoded_game)

    def recursive_function_for_fields(self, pending_object,
                                      object_in_normal_game):
        a = {}
        try:
            a = object_in_normal_game.__dict__.keys()
        except AttributeError:
            pass
        for field in a:
            if field.startswith('__') and field.endswith('__'):
                continue
            try:
                if type(getattr(pending_object, field)) != type(
                        getattr(object_in_normal_game, field)):
                    print('False1')
                    return False
            except AttributeError:
                print('False2')
                return False
            print(field)
            if not self.recursive_function_for_fields(
                    getattr(pending_object, field),
                    getattr(object_in_normal_game, field)):
                return False
        return True

    def check_board(self, pending_board):
        for i in range(BOARD_SIZE):
            for j in range(BOARD_SIZE):
                if not pending_board.is_empty(i, j):
                    pending_piece = pending_board.get_piece(i, j)
                    if not self.recursive_function_for_fields(
                            pending_piece,
                            ChessPiece(ChessColor.White,
                                       ChessPieceType.Bishop)):
                        print('False8')
                        return False
        return True

    def loaded_game_is_correct(self):
        game_for_check = ChessGame(Player('A', 'B'), Player('C', 'D'))
        if type(self.game) != ChessGame:
            return False

        if not self.recursive_function_for_fields(self.game, game_for_check):
            return False

        if not self.check_board(self.game.board):
            return False

        if type(self.game.board) != ChessBoard or type(
                self.game.previous_board) != ChessBoard:
            print('False5')
            return False
        if type(self.game.player_black) != Player or type(
                self.game.player_white) != Player:
            print('False6')
            return False
        return True

    def load_game(self):
        encoded_game = self.load_file()
        if encoded_game is None:
            return
        try:
            self.game = jsonpickle.decode(encoded_game)
        except Exception:
            self.show_mistake('Can\'t open game file')
            return
        if not self.loaded_game_is_correct():
            self.show_mistake('Object in file is not a chess game')
            return
        try:
            self.start_frame.destroy()
        except AttributeError:
            pass

        self.show()

    def load_file(self):
        file = tkFileDialog.Open(self.main_window,
                                 filetypes=[('*.txt files', '.txt')]).show()
        if file == '':
            return
        return open(file, 'r').read()

    def place_main_window(self, width, height):
        screen_width = self.main_window.winfo_screenwidth()
        screen_height = self.main_window.winfo_screenheight()
        x_coordinate = screen_width / 2 - width / 2
        y_coordinate = screen_height / 2 - height / 2 - 20
        self.main_window.geometry('%dx%d+%d+%d' %
                                  (width, height, x_coordinate, y_coordinate))

    def show_this_squares(self, array):
        for (i, j) in array:
            if not self.game.board.is_empty(i, j):
                piece = self.game.board.get_piece(i, j)
                img = self.get_image(piece)
                img = ImageTk.PhotoImage(img)
                self.labels[i + 1][j + 1]['image'] = img
                self.labels[i + 1][j + 1].image = img
            else:
                self.labels[i + 1][j + 1]['image'] = self.empty_image
                self.labels[i + 1][j + 1].image = self.empty_image

    def show(self):
        self.frames = [[
            Frame(self.main_window,
                  height=SQUARE_SIZE,
                  width=SQUARE_SIZE,
                  bd=0) for j in range(BOARD_SIZE + 1)
        ] for i in range(BOARD_SIZE + 1)]
        self.labels = [[
            Label(self.frames[i][j],
                  width=SQUARE_SIZE - 10,
                  height=SQUARE_SIZE - 10) for j in range(BOARD_SIZE + 1)
        ] for i in range(BOARD_SIZE + 1)]
        self.set_boards()
        for i in range(BOARD_SIZE):
            for j in range(BOARD_SIZE):
                handler = lambda g, ii=i, jj=j: self.click_handler(ii, jj)

                self.frames[i + 1][j + 1]['bg'] = self.get_square_tk_color(
                    i, j)
                self.frames[i + 1][j + 1].bind("<Button-1>", handler)
                self.frames[i + 1][j + 1].grid(row=abs(j + 1 - BOARD_SIZE) + 1,
                                               column=i + 1,
                                               sticky=S + W + N + E)

                self.labels[i + 1][j + 1]['bg'] = self.get_square_tk_color(
                    i, j)
                self.labels[i + 1][j + 1].bind("<Button-1>", handler)
                self.labels[i + 1][j + 1].pack(fill='both')

        self.frame_for_data = Frame(self.main_window, bd=1, bg=self.font_color)
        self.frame_for_data.grid(column=1, row=10, columnspan=12, sticky=N)

        self.area_whose_turn = Label(self.frame_for_data,
                                     text='Turn for ' +
                                     str(self.game.whose_turn()),
                                     bg=self.font_color,
                                     width=59)
        self.area_whose_turn.grid(row=1, column=1, rowspan=1)

        self.save_button = Button(self.frame_for_data,
                                  text='Save game',
                                  command=self.save_game,
                                  width=11)
        self.save_button.grid(row=0, column=2)

        self.open_new_button = Button(self.frame_for_data,
                                      text='Open new game',
                                      command=self.open_new_game)
        self.open_new_button.grid(row=1, column=0, rowspan=1)

        self.place_main_window(618, 720)

        self.load_game_button = Button(self.frame_for_data,
                                       text='Load game',
                                       command=self.load_game,
                                       width=11)
        self.load_game_button.grid(row=1, column=2)

        self.save_notation_button = Button(self.frame_for_data,
                                           text='Save notation',
                                           command=self.save_notation,
                                           width=11)
        self.save_notation_button.grid(row=2, column=2)

        squares_array = []
        for i in range(BOARD_SIZE):
            for j in range(BOARD_SIZE):
                squares_array.append((i, j))
        self.show_this_squares(squares_array)

    def show_start_view(self):
        self.start_frame = Frame(self.main_window, bg=self.font_color, bd=16)
        self.place_main_window(220, 60)
        self.start_frame.grid(row=0, column=0)
        load_button = Button(self.start_frame,
                             text='load saved game',
                             command=self.load_game)
        load_button.grid(row=1, column=2)
        new_game_button = Button(self.start_frame,
                                 text='start new game',
                                 command=self.open_new_game)
        new_game_button.grid(row=1, column=1)

    def loop(self):
        self.main_window.mainloop()
        pass