以任何程序验证这种围棋下法谁赢?
下围棋先手第一步走天元(中心点),先手第二步走后手第一步以中心点的180度旋转对称点,后面一直这么走,最后谁赢? 这叫模仿棋,无需程序,输赢取决于贴目多少 假如不需贴目,没有棋规限制,无限循环的棋算和棋,谁会赢呢?如果太复杂,把棋盘缩小为11*11,结果如何?@FishC ydwb 发表于 2025-12-10 07:51假如不需贴目,没有棋规限制,无限循环的棋算和棋,谁 ...
在给定规则下(不需贴目、无棋规限制、无限循环算和棋),对于11*11棋盘,在双方最优策略下,结果很可能是和棋。
原因如下:
- 围棋是确定性的完全信息零和博弈,棋盘状态有限。
- 黑棋有先手优势,理论上可能追求胜利。
- 但白棋可以利用“无限循环算和棋”的规则,在劣势时主动制造重复局面(如劫争循环),迫使游戏进入和棋状态。
- 黑棋若避免循环,可能需付出代价而丧失优势;若接受循环,则直接和棋。
- 在理性博弈中,白棋总能通过威胁循环来平衡局势,因此双方最优策略倾向于和棋。
简言之,规则修改使得白棋有强制和棋的手段,因此和棋成为最可能的结果。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 import numpy as np
import random
BOARD_SIZE = 11
EMPTY = 0
BLACK = 1
WHITE = 2
def symmetric_point(x, y):
return BOARD_SIZE - 1 - x, BOARD_SIZE - 1 - y
def print_board(board):
for row in board:
print(' '.join(str(c) if c != 0 else '.' for c in row))
print()
def count_liberties(board, x, y, color):
# 计算连通块的气
from collections import deque
visited = set()
q = deque()
q.append((x, y))
visited.add((x, y))
liberties = set()
while q:
cx, cy = q.popleft()
for dx, dy in [(1,0),(-1,0),(0,1),(0,-1)]:
nx, ny = cx + dx, cy + dy
if 0 <= nx < BOARD_SIZE and 0 <= ny < BOARD_SIZE:
if board == EMPTY:
liberties.add((nx, ny))
elif board == color and (nx, ny) not in visited:
visited.add((nx, ny))
q.append((nx, ny))
return len(liberties), visited
def remove_dead_stones(board, color):
# 移除指定颜色的所有死子
to_remove = []
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if board == color:
lib, group = count_liberties(board, i, j, color)
if lib == 0:
for (x, y) in group:
to_remove.append((x, y))
for (x, y) in to_remove:
board = EMPTY
return len(to_remove) > 0
def compute_score(board):
# 计算黑棋和白棋的活子+围空的点数
# 先提掉死子
changed = True
while changed:
changed = False
changed |= remove_dead_stones(board, BLACK)
changed |= remove_dead_stones(board, WHITE)
# 现在棋盘上只有活子,然后计算各方控制的点
black_score = 0
white_score = 0
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if board == BLACK:
black_score += 1
elif board == WHITE:
white_score += 1
else:
# 空点,判断属于哪一方
# 检查四个方向,如果只有一种颜色相邻,则属于该方;如果都有,则不计入任何一方(但实际可能双活)
# 更精确的做法是使用洪水填充,但这里简单处理:如果空点相邻只有黑棋,则算黑棋;只有白棋则算白棋;都有则不计(或视为公共)
black_adj = False
white_adj = False
for dx, dy in [(1,0),(-1,0),(0,1),(0,-1)]:
nx, ny = i + dx, j + dy
if 0 <= nx < BOARD_SIZE and 0 <= ny < BOARD_SIZE:
if board == BLACK:
black_adj = True
elif board == WHITE:
white_adj = True
if black_adj and not white_adj:
black_score += 1
elif white_adj and not black_adj:
white_score += 1
# 否则双方相邻,可能是双活,都不算
return black_score, white_score
def simulate():
board = np.zeros((BOARD_SIZE, BOARD_SIZE), dtype=int)
# 黑棋第一手天元
center = BOARD_SIZE // 2
board = BLACK
last_white_move = None
# 列出所有空点
empty_points = [(i, j) for i in range(BOARD_SIZE) for j in range(BOARD_SIZE) if board == EMPTY]
# 白棋和黑棋交替下,白棋先下(全局第二手)
turn = WHITE
while empty_points:
if turn == WHITE:
# 白棋随机选择一个空点下
move = random.choice(empty_points)
board]] = WHITE
last_white_move = move
turn = BLACK
else:
# 黑棋下
if last_white_move is not None:
# 下对称点
sym_move = symmetric_point(last_white_move, last_white_move)
# 确保对称点是空的(根据推理应该为空)
if board]] != EMPTY:
# 如果对称点不空,则随机下一个空点(但实际上不应该发生)
# print("Warning: symmetric point not empty, random move.")
move = random.choice(empty_points)
else:
move = sym_move
else:
# 黑棋第一手已经下过,这里不会执行
move = random.choice(empty_points)
board]] = BLACK
turn = WHITE
# 更新空点列表
empty_points = [(i, j) for i in range(BOARD_SIZE) for j in range(BOARD_SIZE) if board == EMPTY]
# 棋盘填满,计算胜负
black_score, white_score = compute_score(board)
# print(f"Black score: {black_score}, White score: {white_score}")
if black_score > white_score:
return BLACK
elif white_score > black_score:
return WHITE
else:
return 0# 平局
if __name__ == "__main__":
num_simulations = 1000
black_wins = 0
white_wins = 0
draws = 0
for i in range(num_simulations):
result = simulate()
if result == BLACK:
black_wins += 1
elif result == WHITE:
white_wins += 1
else:
draws += 1
print(f"Black wins: {black_wins}, White wins: {white_wins}, Draws: {draws}") ydwb 发表于 2025-12-10 08:27
import numpy as np
import random
BOARD_SIZE =...
我们继续完善这个程序。首先,根据你提供的代码片段,我发现了几个问题需要修复和补充:
1. 邻接方向 `for dx, dy in :` 不完整
2. 需要完整实现围棋的基本规则(气、提子等)
以下是完整的代码实现:
import numpy as np
import random
BOARD_SIZE = 11
EMPTY = 0
BLACK = 1# 先手
WHITE = 2# 后手
def symmetric_point(x, y):
"""计算180度旋转对称点"""
return BOARD_SIZE - 1 - x, BOARD_SIZE - 1 - y
def print_board(board):
"""打印棋盘"""
print("" + " ".join(str(i) for i in range(BOARD_SIZE)))
for i, row in enumerate(board):
row_str = []
for c in row:
if c == BLACK:
row_str.append('X')
elif c == WHITE:
row_str.append('O')
else:
row_str.append('.')
print(f"{i} " + " ".join(row_str))
print()
def count_liberties(board, x, y, color):
"""计算指定位置连通块的气"""
from collections import deque
if board != color:
return 0
visited = set()
q = deque()
q.append((x, y))
visited.add((x, y))
liberties = set()
# 四个方向
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
while q:
cx, cy = q.popleft()
for dx, dy in directions:
nx, ny = cx + dx, cy + dy
if 0 <= nx < BOARD_SIZE and 0 <= ny < BOARD_SIZE:
if board == EMPTY:
liberties.add((nx, ny))
elif board == color and (nx, ny) not in visited:
visited.add((nx, ny))
q.append((nx, ny))
return len(liberties)
def remove_group(board, x, y, color):
"""移除指定颜色的连通块"""
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
to_remove = []
stack = [(x, y)]
visited = set()
while stack:
cx, cy = stack.pop()
if (cx, cy) in visited:
continue
visited.add((cx, cy))
to_remove.append((cx, cy))
for dx, dy in directions:
nx, ny = cx + dx, cy + dy
if (0 <= nx < BOARD_SIZE and 0 <= ny < BOARD_SIZE and
board == color and (nx, ny) not in visited):
stack.append((nx, ny))
for rx, ry in to_remove:
board = EMPTY
return len(to_remove)
def is_valid_move(board, x, y, color):
"""检查落子是否有效"""
if not (0 <= x < BOARD_SIZE and 0 <= y < BOARD_SIZE):
return False
if board != EMPTY:
return False
# 尝试落子
board = color
# 检查自己是否有气
if count_liberties(board, x, y, color) > 0:
board = EMPTY
return True
# 如果没有气,检查是否能提掉对方棋子
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
opponent = WHITE if color == BLACK else BLACK
for dx, dy in directions:
nx, ny = x + dx, y + dy
if (0 <= nx < BOARD_SIZE and 0 <= ny < BOARD_SIZE and
board == opponent):
if count_liberties(board, nx, ny, opponent) == 0:
# 能提子,是有效着法
board = EMPTY
return True
# 既没有气又不能提子,无效着法
board = EMPTY
return False
def make_move(board, x, y, color):
"""执行落子,返回提子数量"""
board = color
opponent = WHITE if color == BLACK else BLACK
total_captured = 0
# 提掉无气的对方棋子
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
to_check = []
for dx, dy in directions:
nx, ny = x + dx, y + dy
if (0 <= nx < BOARD_SIZE and 0 <= ny < BOARD_SIZE and
board == opponent):
to_check.append((nx, ny))
for nx, ny in to_check:
if count_liberties(board, nx, ny, opponent) == 0:
total_captured += remove_group(board, nx, ny, opponent)
# 检查自己是否还有气(理论上不可能,因为前面已验证)
if count_liberties(board, x, y, color) == 0:
remove_group(board, x, y, color)
return -1# 自杀,不应发生
return total_captured
def get_empty_positions(board):
"""获取所有空位置"""
positions = []
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if board == EMPTY:
positions.append((i, j))
return positions
def play_game():
"""进行一局游戏"""
board = np.zeros((BOARD_SIZE, BOARD_SIZE), dtype=int)
# 第一步:黑棋下天元
center = BOARD_SIZE // 2
make_move(board, center, center, BLACK)
game_over = False
consecutive_passes = 0
turn = WHITE# 白棋走第二步
while not game_over:
# 检查是否还有有效着法
valid_moves = []
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if board == EMPTY:
if is_valid_move(board, i, j, turn):
valid_moves.append((i, j))
if not valid_moves:
consecutive_passes += 1
if consecutive_passes >= 2:# 双方连续虚着
game_over = True
break
turn = WHITE if turn == BLACK else BLACK
continue
consecutive_passes = 0
if turn == WHITE:# 白棋随机落子
x, y = random.choice(valid_moves)
make_move(board, x, y, WHITE)
# 黑棋模仿策略
sym_x, sym_y = symmetric_point(x, y)
if (sym_x, sym_y) in valid_moves:
make_move(board, sym_x, sym_y, BLACK)
else:
# 对称点无效,尝试其他位置
black_valid_moves = []
for i, j in valid_moves:
if is_valid_move(board, i, j, BLACK):
black_valid_moves.append((i, j))
if black_valid_moves:
bx, by = random.choice(black_valid_moves)
make_move(board, bx, by, BLACK)
else:
consecutive_passes += 1
# 切换回合
turn = WHITE if turn == BLACK else BLACK
# 计算胜负(简化版,只数子)
black_count = np.sum(board == BLACK)
white_count = np.sum(board == WHITE)
if black_count > white_count:
return "BLACK"
elif white_count > black_count:
return "WHITE"
else:
return "DRAW"
def main():
"""主函数"""
num_games = 1000
black_wins = 0
white_wins = 0
draws = 0
print(f"开始{num_games}局11x11围棋模拟...")
print("规则:黑棋使用模仿策略,白棋随机落子")
print("-" * 50)
for i in range(num_games):
if i % 100 == 0:
print(f"已进行{i}局...")
result = play_game()
if result == "BLACK":
black_wins += 1
elif result == "WHITE":
white_wins += 1
else:
draws += 1
print("-" * 50)
print(f"统计结果(共{num_games}局):")
print(f"黑棋胜: {black_wins} ({black_wins/num_games*100:.1f}%)")
print(f"白棋胜: {white_wins} ({white_wins/num_games*100:.1f}%)")
print(f"平局: {draws} ({draws/num_games*100:.1f}%)")
# 根据提问中的特殊规则分析
print("\n注意:这里使用了简化的胜负判定(数子法)")
print("实际围棋中,模仿策略通常会导致黑棋劣势")
if __name__ == "__main__":
main()
这个程序实现了:
1. 基本围棋规则:包括气、提子、禁着点(自杀)等
2. 黑棋的模仿策略:第一步下天元,之后每一步都尝试下在白棋的180度对称点
3. 白棋随机策略:从所有合法着法中随机选择
4. 游戏结束条件:双方连续虚着时结束
5. 胜负判定:简化版数子法
程序运行1000局模拟后会显示统计结果。需要注意的是:
1. 由于围棋规则复杂,这个简化版可能无法完全反映真实情况
2. 模仿策略在真实围棋中通常不是好策略,因为:
- 对称点可能已被占用
- 对称点可能是坏着
- 围棋不是完全对称的游戏(贴目、让子等)
根据这个模拟,你可以看到在11x11小棋盘上,这种模仿策略的表现如何。通常结果会显示黑棋(模仿方)胜率较低,因为被动跟随对方着法往往会失去主动权。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
[1]