七月二日 python完成简单围棋游戏
第二天
最近,数据结构的小学期,这两天主要是完成我自己的课题设计完成围棋游戏。
【题目43】围棋游戏
设计一个简易的围棋游戏。盘面有纵横各十九条等距离、垂直交叉的平行线,共构成361个交叉点(以下简称为"点")。棋子分黑白两色。对局双方各执一色棋子,黑先白后,交替下子,每次只能下一子。 棋子下在棋盘的点上。棋子下定后,不得向其它点移动。轮流下子是双方的权利,但允许任何一方放弃下子权。谁占据的点位越多谁获胜。
设计要求:
(1) 要求实现图形化界面;
(2) 要求实现棋谱的记录;
(3) 要求实现人人对弈和人机对弈;
今天的代码:
import tkinter as tk from tkinter import messagebox class MainPage(tk.Frame): def __init__(self, parent, controller): super().__init__(parent) self.controller = controller tk.Label(self, text="欢迎来到围棋天地", font=("Arial", 15)).pack(pady=20) tk.Button(self, text="人机对局", command=lambda: controller.show_page(Page1)).pack(pady=10) tk.Button(self, text="双人对局", command=lambda: controller.show_page(Page2)).pack(pady=10) tk.Button(self, text="退出游戏", command=self.quit_game, width=10, height=2).pack(side='bottom', pady=10) def quit_game(self): quit_window = tk.Toplevel(self) # quit_window.title("退出") # 弹窗大小 window_width = 300 window_height = 150 #获取主窗口大小和位置 main_x = self.controller.winfo_x() main_y = self.controller.winfo_y() main_width = self.controller.winfo_width() main_height = self.controller.winfo_height() # 计算弹窗的位置 position_x = main_x + int(main_width/2 - window_width/2) position_y = main_y + int(main_height/2 - window_height/2) quit_window.geometry(f"{window_width}x{window_height}+{position_x}+{position_y}") quit_window.transient(self.controller) quit_window.grab_set() tk.Label(quit_window, text="确定要退出游戏吗?").pack(pady=20) tk.Button(quit_window, text="确定", command=lambda: self.controller.quit_game()).pack(side='left', padx=30, pady=20) tk.Button(quit_window, text="取消", command=quit_window.destroy).pack(side='right', padx=30, pady=20) # 人机对战 class Page1(tk.Frame): def __init__(self, parent, controller): super().__init__(parent) self.controller = controller tk.Label(self, text="人机对局", font=("Arial", 10)).pack(pady=20) tk.Button(self, text="返回", command=lambda: controller.show_page(MainPage)).pack(side='left', anchor='nw', pady=10) # 创建并添加棋盘 self.board = Board(self) self.board.pack(pady=20) # 双人对战 class Page2(tk.Frame): def __init__(self, parent, controller): super().__init__(parent) self.controller = controller tk.Label(self, text="双人对局", font=("Arial", 15)).pack(pady=20) tk.Button(self, text="返回", command=lambda: controller.show_page(MainPage)).pack(side='left', anchor='nw', pady=10) # 创建并添加棋盘 self.board = Board(self) self.board.pack(pady=20) # 窗口位置以及初始化的页面 class GameApp(tk.Tk): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.title("围棋游戏") # 设置窗口大小 window_width = 700 window_height = 700 # 计算屏幕大小 screen_width = self.winfo_screenwidth() screen_height = self.winfo_screenheight() # 计算窗口居中位置 position_x = int((screen_width/2) - (window_width/2)) position_y = int((screen_height/2) - (window_height/2)) self.geometry(f"{window_width}x{window_height}+{position_x}+{position_y}") # self.geometry('500x500') # 全屏 # self.attributes("-fullscreen", True) container = tk.Frame(self) container.pack(fill='both', expand=True) container.grid_rowconfigure(0, weight=1) container.grid_columnconfigure(0, weight=1) self.pages = {} for Page in (MainPage, Page1, Page2): page_instance = Page(container, self) self.pages[Page] = page_instance page_instance.grid(row=0, column=0, sticky='nsew') self.show_page(MainPage) def show_page(self, page): self.pages[page].tkraise() def quit_game(self): self.destroy() # 棋盘 class Board(tk.Frame): def __init__(self, parent, size=19): super().__init__(parent) self.size = size self.board =[['.' for _ in range(size)] for _ in range(size)] self.current_player = "B" self.canvas = tk.Canvas(self, width=600, height=600, bg='saddlebrown') self.canvas.pack() self.cell_size = 600//(self.size+1) self.canvas.bind("<Button-1>", self.handle_click) self.draw_board() # 画棋盘,先画竖线,i表示第条线 def draw_board(self): for i in range(1, self.size + 1): self.canvas.create_line(self.cell_size * i, self.cell_size, self.cell_size * i, 600 - self.cell_size) self.canvas.create_line(self.cell_size, self.cell_size * i, 600 - self.cell_size, self.cell_size * i) self.draw_stones() def draw_stones(self): self.canvas.delete("stone") for x in range(self.size): for y in range(self.size): if self.board[x][y] == 'B': self.draw_stone(x, y, 'black') elif self.board[x][y] == 'W': self.draw_stone(x, y, 'white') def draw_stone(self, x, y, color): self.canvas.create_oval( (x + 1) * self.cell_size - self.cell_size // 2, (y + 1) * self.cell_size - self.cell_size // 2, (x + 1) * self.cell_size + self.cell_size // 2, (y + 1) * self.cell_size + self.cell_size // 2, fill=color, tags="stone" ) # 因为有边框,占了一个格子的宽度 def handle_click(self, event): x = round((event.x - self.cell_size) / self.cell_size) y = round((event.y - self.cell_size) / self.cell_size) if self.is_on_board(x, y) and self.is_empty(x, y): self.board[x][y] = self.current_player # 如果 self.current_player 的值等于 'B',则将 self.current_player 的值设为 'W'。 # 如果 self.current_player 的值不等于 'B'(即为 'W'),则将 self.current_player 的值设为 'B'。 self.current_player = 'W' if self.current_player == 'B' else 'B' self.draw_board() # 棋子在棋盘上,判断是否点击在棋盘上 def is_on_board(self, x, y): return 0 <= x < self.size and 0 <= y < self.size # 判断是否点击的是空的位置 def is_empty(self, x, y): return self.board[x][y] == '.' if __name__ == '__main__': app = GameApp() app.mainloop()
代码主要实现棋盘和两种棋子可以点击到棋盘,还没有实现玩法的控制。还有实现点击退出游戏按钮的防误触功能,弹窗提醒玩家是否退出。