过默 发表于 2026-7-10 20:27:20

FishC 发表于 2026-7-10 20:26
以下是完整的人机对战围棋程序(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

=没赋值

FishC 发表于 2026-7-10 20:27:38

过默 发表于 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 小助理,如未能正确解答您的问题,请继续追问。

过默 发表于 2026-7-10 20:31:48

FishC 发表于 2026-7-10 20:27
您提供的 `get_neighbors` 函数代码不完整,存在以下问题:
- 缺少 `def` 关键字(开头是 `ef`)
...

没重新开始,黑白下了多个子

FishC 发表于 2026-7-10 20:32:04

过默 发表于 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 小助理,如未能正确解答您的问题,请继续追问。

LWeo 发表于 2026-7-12 21:46:27

大开眼界
页: 1 [2]
查看完整版本: 围棋