Форум сайта python.su
Захотелось поделится игрой, в моём исполнении.
# python3 # Игра "Крестики - Нолики" from tkinter import * import random class Square(): """ задает квадраты(клетки) """ def __init__(self, master, xi, yi, num, b=5, w=137, h=137, padx=0, pady=160): """ b - border """ self.master = master self.square_num = num self.msg = StringVar() x = padx + xi * (w + b) y = pady + yi * (h + b) self.lbl = Label(self.master, textvariable=self.msg, font="FreeSerifBold 75", bg="white") self.lbl.place(x=x, y=y, width=w, height=h, anchor=NW) def unbind(self): self.lbl.unbind("<Button-1>") def bind(self): self.lbl.bind("<Button-1>", self.choice) def set_msg(self, txt): self.msg.set(txt) def choice(self, event): self.master.turn_user(self.square_num) def cfg(self, color): self.lbl.configure(bg=color) class Application(Frame): def __init__(self, master): super(Application, self).__init__(master, width=421, height=582) self.pack() # константы self.wins = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)) self.board_start = ['_'] * 9 self.free_squares_start = [x for x in range(9)] self.choice_pc1 = [0, 2, 6, 8] self.choice_pc2 = [1, 3, 5, 7] # статистика игры self.drawn_game = 0 self.user_win = 0 self.pc_win = 0 self.create_widgets() def create_widgets(self): self.squares = {} num = 0 for yi in range(0, 3): for xi in range(0, 3): self.squares[num] = Square(self, xi, yi, num) num += 1 # кнопка старт self.btn = Button(self, text="Старт") self.btn.bind("<Button-1>", self.start) self.btn.place(x=290, y=77, width=120, anchor=NW) # Статус игры status = LabelFrame(self, text=" Статус игры ", width=400, height=40) status.place(x=10, y=110, anchor=NW) self.status_msg = StringVar() status_lbl = Label(status, textvariable=self.status_msg) status_lbl.place(x=5, y=0, anchor=NW) self.status_msg.set('Добро пожаловать в игру "Крестики - Нолики"!') # Выбор знака sign_choice = LabelFrame(self, text=" Выбор знака ", width=120, height=60) sign_choice.place(x=290, y=10, anchor=NW) self.user_choice = StringVar() self.user_choice.set('0') sign0 = Radiobutton(sign_choice, text='Ваш знак "0"', variable=self.user_choice, value='0') sign1 = Radiobutton(sign_choice, text='Ваш знак "X"', variable=self.user_choice, value='X') sign0.place(x=0, y=0, anchor=NW) sign1.place(x=0, y=18, anchor=NW) # Выбор хода step_choice = LabelFrame(self, text=" Выбрать ход ", width=120, height=95) step_choice.place(x=160, y=10, anchor=NW) self.step = IntVar() self.step.set(0) step0 = Radiobutton(step_choice, text='Случайным', variable=self.step, value=0) step1 = Radiobutton(step_choice, text='Первым', variable=self.step, value=1) step2 = Radiobutton(step_choice, text='Вторым', variable=self.step, value=2) step0.place(x=0, y=0, anchor=NW) step1.place(x=0, y=25, anchor=NW) step2.place(x=0, y=50, anchor=NW) # статистика statistics = LabelFrame(self, text=" Статистика ", width=140, height=95) statistics.place(x=10, y=10, anchor=NW) self.stat_msg = StringVar() stat_lbl = Label(statistics, textvariable=self.stat_msg, justify=LEFT) stat_lbl.place(x=5, y=0, anchor=NW) self.stat_msg.set( 'Сыграно игр: %s.\nИз них:\n побед - %s;\n поражений - %s;\n ничьих - %s.' % (self.user_win + self.pc_win + self.drawn_game, self.user_win, self.pc_win, self.drawn_game) ) self.widgets = [sign0, sign1, step0, step1, step2, self.btn] def start(self, *args): self.choice_pc = None self.flag_end = False self.free_squares = self.free_squares_start[:] self.board = self.board_start[:] self.status_msg.set('Осторожно! Игра активирована! Удачи!') for square_num in range(9): square = self.squares[square_num] square.bind() square.set_msg('') square.cfg('white') if self.user_choice.get() == '0': self.user_sign, self.pc_sign = '0', 'X' else: self.user_sign, self.pc_sign = 'X', '0' uc = self.step.get() if uc == 2: self.turn_pc() elif uc == 0: rnd = random.choice([1, 2]) if rnd == 2: self.turn_pc() self.widget_state() self.btn.unbind("<Button-1>") def widget_state(self, wst=DISABLED): for widget in self.widgets: widget.config(state=wst) def unbind_squares(self): for square_num in self.free_squares: self.squares[square_num].unbind() def greet_winner(self, sign): """ поздравления """ if sign == self.user_sign: self.status_msg.set('Поздравляю с победой!') self.user_win += 1 else: self.status_msg.set('Победа за компьютером! Ну как так?!!!') self.pc_win += 1 self.flag_end = True def show_win(self, win, sign): if sign == self.user_sign: color = 'green' else: color = 'red' for square_num in win: square = self.squares[square_num] square.cfg(color) def game_over(self): """ окончание игры """ self.stat_msg.set( 'Сыграно игр: %s.\nИз них:\n побед - %s;\n поражений - %s;\n ничьих - %s.' % (self.user_win + self.pc_win + self.drawn_game, self.user_win, self.pc_win, self.drawn_game) ) self.widget_state(NORMAL) self.btn.bind("<Button-1>", self.start) def test_win(self, sign): """ определение исхода игры """ for a, b, c in self.wins: if self.board[a] == sign and self.board[b] == sign and self.board[c] == sign: self.show_win((a, b, c), sign) self.unbind_squares() self.greet_winner(sign) self.game_over() return if not self.free_squares: self.status_msg.set('Ничья. Вы точно можете лучше!') self.flag_end = True self.drawn_game += 1 for square_num in range(9): square = self.squares[square_num] square.cfg('yellow') self.game_over() def is_win(self, sign, iboard): for a, b, c in self.wins: if iboard[a] == sign and iboard[b] == sign and iboard[c] == sign: return True return False def find_best_turn(self, sign): for iturn in self.free_squares: iboard = self.board[:] iboard[iturn] = sign res = self.is_win(sign, iboard) if res: return iturn return None def default_choice(self): if not self.choice_pc: self.choice_pc=[4] random.shuffle(self.choice_pc1) random.shuffle(self.choice_pc2) self.choice_pc.extend(self.choice_pc1) self.choice_pc.extend(self.choice_pc2) for iturn in self.choice_pc: if iturn in self.free_squares: return iturn def turn_pc(self): """ ход пк """ square_num = self.find_best_turn(self.pc_sign) if square_num == None: square_num = self.find_best_turn(self.user_sign) if square_num == None: square_num = self.default_choice() self.turn(square_num, self.pc_sign) def change_board(self, square_num, sign): """ заполнение клетки знаком """ self.board[square_num] = sign self.free_squares.remove(square_num) def turn(self, square_num, sign): square = self.squares[square_num] square.unbind() square.set_msg(sign) self.change_board(square_num, sign) self.test_win(sign) def turn_user(self, square_num): """ ход игрока """ self.turn(square_num, self.user_sign) if not self.flag_end: self.turn_pc() def main(): root = Tk() root.title('Игра "Крестики - Нолики"') root.geometry('421x582') root.resizable(FALSE, FALSE) app = Application(root) root.mainloop() if __name__=='__main__': main()
Отредактировано anickone (Июль 17, 2018 20:58:36)
Офлайн
В целом хорошо. ИИ не давит интелектом и есть возможность выиграть. Нашел две стратегии как обыграть Искуственного Идиота. Первая 100% выигрыш, вторая один раз на 2-3 попытки.
[code python][/code]
Отредактировано PEHDOM (Июль 17, 2018 22:05:04)
Офлайн
Код ещё не смотрел, но внешний вид нужно поправить:
1. рамка “Статус игры” наползает на рамку “Статистика” (нижняя часть не видна)
2. нужно сделать клеточки видимыми (сделать рамки или светло-серый фон)
Офлайн
ramiХЗ рамка никуда не наползает, клетки белые на сером фоне. Хотя я бы добавил по паре пкселов сбоку, чтобы клетки не сливались с краями окна.
1. рамка “Статус игры” наползает на рамку “Статистика” (нижняя часть не видна)
2. нужно сделать клеточки видимыми (сделать рамки или светло-серый фон)
[code python][/code]
Отредактировано PEHDOM (Июль 17, 2018 22:16:21)
Офлайн
У меня на Маке Python 3.7
Прикреплённый файлы:
Снимок.png (40,4 KБ)
Офлайн
ramiСогласен, автору втык за абсолютное позиционирование виджетов.
У меня на Маке Python 3.7
[code python][/code]
Офлайн
PEHDOMЯ удивлен, думал эту стратегию не обыграть. Даже был этим расстроен, т. к. думал что выигрышная часть кода никогда не сработает, а я его писал. И тут такой сюрприз! Стратегия, ясное дело, не моя, она из книжки. Пожалуйста, напишите мне на емайл, ваши выигрышные стратегии, здесь просьба не писать, вдруг все потеряют интерес к этой игре.
В целом хорошо. ИИ не давит интелектом и есть возможность выиграть. Нашел две стратегии как обыграть Искуственного Идиота. Первая 100% выигрыш, вторая один раз на 2-3 попытки.
Отредактировано anickone (Июль 17, 2018 23:41:59)
Офлайн
На linux с интерфейсом тоже беда
Отредактировано Vigi (Июль 18, 2018 09:56:35)
Офлайн
PEHDOM
ХЗ рамка никуда не наползает, клетки белые на сером фоне.
VigiЕсли параметры не заданы, они будут по умолчанию — на linux и Маке шрифт по умолчанию крупнее, поэтому не “лезет ни в какие ворота” , да и фон по умолчанию разный. Нужно задавать шрифт и упаковывать в grid()
На linux с интерфейсом тоже беда
Офлайн
Переписал под grid. У кого в интерфейсе были сползания, посмотрите что сейчас?
from tkinter import * import random class Square(): """ задает квадраты(клетки) """ def __init__(self, master, root, num, row, column): self.master = master self.square_num = num self.msg = StringVar() self.lbl = Label(root, textvariable=self.msg, font="FreeSerifBold 75", bg="white") self.lbl.grid(row=row, column=column, sticky=NSEW, padx=5, pady=5) def unbind(self): self.lbl.unbind("<Button-1>") def bind(self): self.lbl.bind("<Button-1>", self.choice) def set_msg(self, txt): self.msg.set(txt) def choice(self, event): self.master.turn_user(self.square_num) def cfg(self, color): self.lbl.configure(bg=color) class Application(Frame): def __init__(self, master): super(Application, self).__init__(master) self.master = master self.master.config(bg="#D9D9D9") # константы self.wins = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)) self.board_start = ['_'] * 9 self.free_squares_start = [x for x in range(9)] self.choice_pc1 = [0, 2, 6, 8] self.choice_pc2 = [1, 3, 5, 7] # статистика игры self.drawn_game = 0 self.user_win = 0 self.pc_win = 0 self.create_widgets() def create_widgets(self): # блок слева frame_left = Frame(self.master) frame_left.grid(row=0, column=0, padx=5, pady=5, sticky=N) # статистика statistics = LabelFrame(frame_left, text=" Статистика ") statistics.grid() self.stat_msg = StringVar() stat_lbl = Label(statistics, textvariable=self.stat_msg, justify=LEFT, width=15) stat_lbl.grid(padx=0) self.stat_msg.set( 'Сыграно игр: %s.\nИз них:\n побед: %s;\n поражений: %s;\n ничьих: %s.' % (self.user_win + self.pc_win + self.drawn_game, self.user_win, self.pc_win, self.drawn_game) ) # блок в центре frame_center = Frame(self.master) frame_center.grid(row=0, column=1, padx=10, pady=5, sticky=N) step_choice = LabelFrame(frame_center, text=" Выбрать ход ") step_choice.grid(ipadx=5) self.step = IntVar() self.step.set(0) step0 = Radiobutton(step_choice, text='Случайным', variable=self.step, value=0) step1 = Radiobutton(step_choice, text='Первым', variable=self.step, value=1) step2 = Radiobutton(step_choice, text='Вторым', variable=self.step, value=2) step0.grid(ipady=2, sticky=W) step1.grid(ipady=3, sticky=W) step2.grid(ipady=2, sticky=W) # блок справа right_frame = Frame(self.master) right_frame.grid(row=0, column=2, padx=5, pady=5) # Выбор знака sign_choice = LabelFrame(right_frame, text=" Выбор знака ") sign_choice.grid(ipadx=5) self.user_choice = StringVar() self.user_choice.set('0') sign0 = Radiobutton(sign_choice, text='Ваш знак "0"', variable=self.user_choice, value='0') sign1 = Radiobutton(sign_choice, text='Ваш знак "X"', variable=self.user_choice, value='X') sign0.grid() sign1.grid() # кнопка старт self.btn = Button(right_frame, text="Старт") self.btn.bind("<Button-1>", self.start) self.btn.grid(pady=6, sticky=NSEW) # Статус игры status = LabelFrame(self.master, text=" Статус игры ") status.grid(row=1, column=0, columnspan=3, padx=5, sticky=NSEW) self.status_msg = StringVar() status_lbl = Label(status, textvariable=self.status_msg) status_lbl.grid() self.status_msg.set('Добро пожаловать в игру "Крестики - Нолики"!') # squares self.squares = {} num = 0 for row in range(2, 5): for column in range(0, 3): self.squares[num] = Square(self, self.master, num, row, column) num += 1 self.widgets = [sign0, sign1, step0, step1, step2, self.btn] def start(self, *args): self.choice_pc = None self.flag_end = False self.free_squares = self.free_squares_start[:] self.board = self.board_start[:] self.status_msg.set('Осторожно! Игра активирована! Удачи!') for square_num in range(9): square = self.squares[square_num] square.bind() square.set_msg('') square.cfg('white') if self.user_choice.get() == '0': self.user_sign, self.pc_sign = '0', 'X' else: self.user_sign, self.pc_sign = 'X', '0' uc = self.step.get() if uc == 2: self.turn_pc() elif uc == 0: rnd = random.choice([1, 2]) if rnd == 2: self.turn_pc() self.widget_state() self.btn.unbind("<Button-1>") def widget_state(self, wst=DISABLED): for widget in self.widgets: widget.config(state=wst) def unbind_squares(self): for square_num in self.free_squares: self.squares[square_num].unbind() def greet_winner(self, sign): """ поздравления """ if sign == self.user_sign: self.status_msg.set('Поздравляю с победой!') self.user_win += 1 else: self.status_msg.set('Победа за компьютером! Ну как так?!!!') self.pc_win += 1 self.flag_end = True def show_win(self, win, sign): if sign == self.user_sign: color = 'green' else: color = 'red' for square_num in win: square = self.squares[square_num] square.cfg(color) def game_over(self): """ окончание игры """ self.stat_msg.set( 'Сыграно игр: %s.\nИз них:\n побед: %s;\n поражений: %s;\n ничьих: %s.' % (self.user_win + self.pc_win + self.drawn_game, self.user_win, self.pc_win, self.drawn_game) ) self.widget_state(NORMAL) self.btn.bind("<Button-1>", self.start) def test_win(self, sign): """ определение исхода игры """ for a, b, c in self.wins: if self.board[a] == sign and self.board[b] == sign and self.board[c] == sign: self.show_win((a, b, c), sign) self.unbind_squares() self.greet_winner(sign) self.game_over() return if not self.free_squares: self.status_msg.set('Ничья. Вы точно можете лучше!') self.flag_end = True self.drawn_game += 1 for square_num in range(9): square = self.squares[square_num] square.cfg('yellow') self.game_over() def is_win(self, sign, iboard): for a, b, c in self.wins: if iboard[a] == sign and iboard[b] == sign and iboard[c] == sign: return True return False def find_best_turn(self, sign): for iturn in self.free_squares: iboard = self.board[:] iboard[iturn] = sign res = self.is_win(sign, iboard) if res: return iturn return None def default_choice(self): if not self.choice_pc: self.choice_pc = [4] random.shuffle(self.choice_pc1) random.shuffle(self.choice_pc2) self.choice_pc.extend(self.choice_pc1) self.choice_pc.extend(self.choice_pc2) for iturn in self.choice_pc: if iturn in self.free_squares: return iturn def turn_pc(self): """ ход пк """ square_num = self.find_best_turn(self.pc_sign) if square_num == None: square_num = self.find_best_turn(self.user_sign) if square_num == None: square_num = self.default_choice() self.turn(square_num, self.pc_sign) def change_board(self, square_num, sign): """ заполнение клетки знаком """ self.board[square_num] = sign self.free_squares.remove(square_num) def turn(self, square_num, sign): square = self.squares[square_num] square.unbind() square.set_msg(sign) self.change_board(square_num, sign) self.test_win(sign) def turn_user(self, square_num): """ ход игрока """ self.turn(square_num, self.user_sign) if not self.flag_end: self.turn_pc() def main(): root = Tk() root.title('Игра "Крестики - Нолики"') root.resizable(FALSE, FALSE) app = Application(root) root.mainloop() if __name__ == '__main__': main()
Отредактировано anickone (Июль 19, 2018 16:04:14)
Офлайн