以下是完整的人机对战围棋程序(19×19),AI 采用简单的评分策略(评估落子后提子数及棋子数)。代码 ...
ef get_neighbors(r, c):
dirs =
res =
for dr, dc in dirs:
nr, nc = r + dr, c + dc
if 0 <= nr < SIZE and 0 <= nc < SIZE:
res.append((nr, nc))
return res
def get_group(board, r, c, color):
stack =
visited = {(r, c)}
group =
while stack:
cr, cc = stack.pop()
group.append((cr, cc))
for nr, nc in get_neighbors(cr, cc):
if board == color and (nr, nc) not in visited:
visited.add((nr, nc))
stack.append((nr, nc))
return group
=没赋值 过默 发表于 2026-07-10 20:27
FishC 发表于 2026-7-10 20:26
以下是完整的人机对战 ...
您提供的 `get_neighbors` 函数代码不完整,存在以下问题:
- 缺少 `def` 关键字(开头是 `ef`)
- `dirs` 和 `res` 赋值未完成
- `for` 循环缩进错误
- `if` 条件未闭合
- 缺少 `return` 语句
以下是修正后的正确函数(以 19 路棋盘为例),可直接使用:
def get_neighbors(r, c):
dirs = [(-1,0), (1,0), (0,-1), (0,1)]
res = []
for dr, dc in dirs:
nr, nc = r + dr, c + dc
if 0 <= nr < SIZE and 0 <= nc < SIZE:
res.append((nr, nc))
return res
您需要确保在函数外定义了 `SIZE`(例如 `SIZE = 19`)。
如果希望直接运行完整的人机对战程序,请参考之前提供的新代码(已修正所有语法错误)。请将以下完整代码复制到 Python 文件中运行(建议使用 9 路棋盘测试,速度更快):
import tkinter as tk
import random
SIZE = 9# 可改为 19
def init_board():
return [*SIZE for _ in range(SIZE)]
def get_neighbors(r, c):
dirs = [(-1,0),(1,0),(0,-1),(0,1)]
res = []
for dr, dc in dirs:
nr, nc = r+dr, c+dc
if 0 <= nr < SIZE and 0 <= nc < SIZE:
res.append((nr,nc))
return res
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 == 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
def evaluate_move(board, r, c, color):
if board != 0:
return -999
test_board = for row in board]
if not place_stone(test_board, r, c, color):
return -999
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:
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白", 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:
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)
star = [(3,3),(3,5),(5,3),(5,5),(4,4)] if SIZE==9 else [(3,3),(3,15),(15,3),(15,15),(9,9)]
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 place_stone(self.board, row, col, self.current):
self.draw()
opponent = 3 - self.current
# AI 自动走一步
self.root.after(100, self.ai_move)
def ai_move(self):
opponent = self.current
r, c = ai_play(self.board, opponent)
if r != -1:
if place_stone(self.board, r, c, opponent):
self.draw()
if __name__ == "__main__":
game = GoGame()
game.root.mainloop()
将以上代码另存为 `go_human_vs_ai.py` 运行即可。AI 会执与您当前颜色相反的颜色(即您执黑时 AI 执白,您按2切换白时 AI 执黑)。通过按键盘 1 或 2 可主动切换当前落子颜色。
您还可以通过修改 `SIZE` 为 19 来使用标准棋盘(但 AI 运算会变慢)。提升 AI 强度可改进 `evaluate_move` 中的评分函数(例如加入围地面积、眼位等因素)。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2026-7-10 20:27
您提供的 `get_neighbors` 函数代码不完整,存在以下问题:
- 缺少 `def` 关键字(开头是 `ef`)
...
没重新开始,黑白下了多个子 过默 发表于 2026-07-10 20:31
FishC 发表于 2026-7-10 20:27
您提供的 `get_neighb ...
您的问题是说“黑白下了多个子”没有被交替规则限制,即同一方可以连续落子。这是因为在 `click` 函数中,落子成功后没有自动切换当前颜色。请按以下步骤修改:
### 修改方法
找到 `click` 方法,在 `place_stone` 成功之后添加一行,切换 `self.current` 颜色。
修改后的 `click` 方法(只显示关键部分):
def click(self, event):
cell = 500 // (SIZE + 2)
off = cell
col = round((event.x - off) / cell)
row = round((event.y - off) / cell)
if 0
这样,每次点击成功落子后,`self.current` 会自动变为对方颜色,实现黑白交替。如果您不想自动交替(而是想完全通过键盘切换颜色),可以不添加该行,但那样就需要手动按 1 或 2 来改变颜色。
### 重新开始(重置棋盘)
添加一个“重新开始”按钮,绑定到 `reset` 函数。在 `__init__` 中添加:
self.reset_btn = tk.Button(self.root, text="重新开始", command=self.reset)
self.reset_btn.pack()
并定义 `reset` 方法:
def reset(self):
self.board = init_board()
self.current = 1
self.draw()
self.info.config(text="当前:黑子(按1黑,按2白)")
这样就能随时清空棋盘重新开始对局。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 大开眼界
页:
1
[2]