|
|
-
- import tkinter as tk
- import random
- SIZE = 19
- def init_board():
- return [[0]*SIZE for _ in range(SIZE)]
- def get_neighbors(r, c):
- dirs = [(-1,0),(1,0),(0,-1),(0,1)]
- return [(r+dr, c+dc) for dr, dc in dirs if 0 <= r+dr < SIZE and 0 <= c+dc < SIZE]
- def get_group(board, r, c, color):
- stack = [(r,c)]
- visited = {(r,c)}
- group = []
- while stack:
- cr, cc = stack.pop()
- group.append((cr,cc))
- for nr, nc in get_neighbors(cr, cc):
- if board[nr][nc] == color and (nr,nc) not in visited:
- visited.add((nr,nc))
- stack.append((nr,nc))
- return group
- def get_liberties(board, group):
- libs = set()
- for r, c in group:
- for nr, nc in get_neighbors(r, c):
- if board == 0:
- libs.add((nr,nc))
- return libs
- def place_stone(board, r, c, color):
- if board != 0:
- return False
- board = color
- opponent = 3 - color
- for nr, nc in get_neighbors(r, c):
- if board == opponent:
- group = get_group(board, nr, nc, opponent)
- if len(get_liberties(board, group)) == 0:
- for gr, gc in group:
- board = 0
- my_group = get_group(board, r, c, color)
- if len(get_liberties(board, my_group)) == 0:
- board = 0
- return False
- return True
- # ---------- 简单AI:根据落子后的得分选择 ----------
- def evaluate_move(board, r, c, color):
- # 模拟落子后得分(提子数 + 围地变化量,简化)
- # 返回分数,越高越优
- if board != 0:
- return -999
- test_board = [[board] for _ in board]
- if not place_stone(test_board, r, c, color):
- return -999
- # 计算当前test_board中color的棋子数 + 空点中属于color的(粗糙)
- # 简单:数color的棋子数
- count = 0
- for rr in range(SIZE):
- for cc in range(SIZE):
- if test_board == color:
- count += 1
- return count
- def ai_play(board, color):
- best_score = -1000
- best_moves = []
- for r in range(SIZE):
- for c in range(SIZE):
- score = evaluate_move(board, r, c, color)
- if score > best_score:
- best_score = score
- best_moves = [(r,c)]
- elif score == best_score:
- best_moves.append((r,c))
- if best_moves:
- return random.choice(best_moves)
- else:
- # 无合法落子,返回pass(用(-1,-1)表示)
- return (-1, -1)
- class GoGame:
- def __init__(self):
- self.board = init_board()
- self.current = 1 # 黑先
- self.root = tk.Tk()
- self.root.title("围棋 人机对战")
- self.info = tk.Label(self.root, text="当前:黑子(你) 按1切换黑,2切换白(AI自动走)", font=('Arial',12))
- self.info.pack()
- self.canvas = tk.Canvas(self.root, width=500, height=500, bg="#DEB887")
- self.canvas.pack(padx=10, pady=10)
- self.canvas.bind("<Button-1>", self.click)
- self.root.bind('1', lambda e: self.set_color(1))
- self.root.bind('2', lambda e: self.set_color(2))
- self.draw()
- def set_color(self, color):
- self.current = color
- name = "黑子" if color == 1 else "白子"
- self.info.config(text="当前:"+name+"(按1黑,按2白)")
- if color == 2: # AI执黑时可让AI先走
- self.root.after(100, self.ai_move)
- def draw(self):
- self.canvas.delete("all")
- cell = 500 // (SIZE + 2)
- off = cell
- for i in range(SIZE):
- x = off + i * cell
- self.canvas.create_line(off, x, off + (SIZE-1)*cell, x)
- self.canvas.create_line(x, off, x, off + (SIZE-1)*cell)
- # 星位(19路常见)
- star = [(3,3),(3,9),(3,15),(9,3),(9,9),(9,15),(15,3),(15,9),(15,15)]
- for r, c in star:
- x = off + c * cell
- y = off + r * cell
- self.canvas.create_oval(x-3, y-3, x+3, y+3, fill='black')
- radius = cell//2 - 2
- for r in range(SIZE):
- for c in range(SIZE):
- if self.board != 0:
- x = off + c * cell
- y = off + r * cell
- color = "black" if self.board == 1 else "white"
- outline = "white" if self.board == 1 else "black"
- self.canvas.create_oval(x-radius, y-radius, x+radius, y+radius,
- fill=color, outline=outline, width=1)
- def click(self, event):
- cell = 500 // (SIZE + 2)
- off = cell
- col = round((event.x - off) / cell)
- row = round((event.y - off) / cell)
- if 0 <= row < SIZE and 0 <= col < SIZE:
- if self.current == 1:
- if place_stone(self.board, row, col, 1):
- self.draw()
- # 切换到AI(白棋)
- self.root.after(200, self.ai_move)
- def ai_move(self):
- color = 2 if self.current == 2 else 2 # AI始终执白?可根据需要修改
- # 若当前是玩家回合,AI不应走。这里简单:AI只在轮到白棋时走
- if self.current == 2:
- r, c = ai_play(self.board, 2)
- if r == -1:
- # pass
- pass
- else:
- place_stone(self.board, r, c, 2)
- self.draw()
- self.current = 1
- self.info.config(text="当前:黑子(你) 按1黑,按2白")
- if __name__ == "__main__":
- game = GoGame()
- game.root.mainloop()
复制代码
下不了 |
|