用户:rattler查看:0 回复:2 评论:0 创建时间:2023-04-15T20:35:17
import numpy as np
# 棋盘大小
BOARD_SIZE = 15
# 空位置表示
EMPTY = 0
# 黑色棋子表示
BLACK = 1
# 白色棋子表示
WHITE = -1
# 评估函数中的棋型定义
FIVE = 1e6
FOUR = 1e5
BLOCKED_FOUR = 1e4
THREE = 1e3
BLOCKED_THREE = 1e2
TWO = 10
BLOCKED_TWO = 5
ONE = 1
# alpha-beta搜索深度
SEARCH_DEPTH = 4
class AlphaBetaAI:
def __init__(self, color):
self.color = color
# 获取可放置棋子的位置列表
def get_legal_actions(self, chessboard):
actions = []
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if chessboard[i][j] == EMPTY:
actions.append((i, j))
return actions
# 判断某个位置是否越界
def is_out_of_board(self, x, y):
if x < 0 or y < 0 or x >= BOARD_SIZE or y >= BOARD_SIZE:
return True
return False
# 判断当前局面下是否存在五子连珠
def is_win(self, chessboard, color):
dir = [[0, 1], [1, 0], [1, 1], [1, -1]]
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if chessboard[i][j] == color:
for k in range(4):
x = i + dir[k][0]
y = j + dir[k][1]
if self.is_out_of_board(x, y) or chessboard[x][y] != color:
continue
for l in range(2, 6):
x = i + dir[k][0] * l
y = j + dir[k][1] * l
if self.is_out_of_board(x, y) or chessboard[x][y] != color:
break
if l == 5:
return True
return False
# 获取棋盘上空闲位置的数量
def get_empty_count(self, chessboard):
count = 0
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if chessboard[i][j] == EMPTY:
count += 1
return count
# 评估函数
def evaluate(self, chessboard):
score = 0
dir = [[0, 1], [1, 0], [1, 1], [1, -1]]
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if chessboard[i][j] != EMPTY:
for k in range(4):
color_count = 0
empty_count = 0
blocked_flag = False
for l in range(-5, 6):
x = i + dir[k][0] * l
y = j + dir[k][1] * l
if self.is_out_of_board(x, y):
continue
if chessboard[x][y] == self.color:
color_count += 1
elif chessboard[x][y] == EMPTY:
if empty_count == 0 and l < 0:
blocked_flag = True
empty_count += 1
else:
if l < 0:
blocked_flag = True
break
if color_count == 0:
continue
elif color_count == 1:
if empty_count == 2:
score += TWO
elif empty_count == 3:
score += BLOCKED_TWO if blocked_flag else TWO
elif empty_count == 4:
score += BLOCKED_THREE if blocked_flag else THREE
elif color_count == 2:
if empty_count == 1:
score += BLOCKED_TWO if blocked_flag else TWO
elif empty_count == 2:
score += BLOCKED_THREE if blocked_flag else THREE
elif empty_count == 3:
score += BLOCKED_FOUR if blocked_flag else FOUR
elif color_count == 3:
if empty_count == 1:
score += BLOCKED_THREE
elif empty_count == 2:
score += BLOCKED_FOUR if blocked_flag else FOUR
else:
score += FIVE
return score
# 极大值函数
def max_value(self, chessboard, alpha, beta, depth):
if self.is_win(chessboard, self.color):
return float('inf')
if depth == SEARCH_DEPTH:
return self.evaluate(chessboard)
v = -float('inf')
actions = self.get_legal_actions(chessboard)
for action in actions:
chessboard[action[0]][action[1]] = self.color
v = max(v, self.min_value(chessboard, alpha, beta, depth+1))
chessboard[action[0]][action[1]] = EMPTY
if v >= beta:
return v
alpha = max(alpha, v)
return v
# 极小值函数
def min_value(self, chessboard, alpha, beta, depth):
if self.is_win(chessboard, -self.color):
return -float('inf')
if depth == SEARCH_DEPTH:
return -self.evaluate(chessboard)
v = float('inf')
actions = self.get_legal_actions(chessboard)
for action in actions:
chessboard[action[0]][action[1]] = -self.color
v = min(v, self.max_value(chessboard, alpha, beta, depth+1))
chessboard[action[0]][action[1]] = EMPTY
if v <= alpha:
return v
beta = min(beta, v)
return v
# alpha-beta剪枝搜索
def alpha_beta_search(self, chessboard):
best_action = None
best_score = -float('inf')
alpha = -float('inf')
beta = float('inf')
actions = self.get_legal_actions(chessboard)
if not actions:
return (7, 7)
for action in actions:
chessboard[action[0]][action[1]] = self.color
score = self.min_value(chessboard, alpha, beta, 1)
chessboard[action[0]][action[1]] = EMPTY
if score > best_score:
best_score = score
best_action = action
alpha = max(alpha, best_score)
return best_action
# 初始化棋盘
chessboard = np.zeros((BOARD_SIZE, BOARD_SIZE), dtype=np.int32)
# 初始化AI
ai = AlphaBetaAI(BLACK)
# 主循环
while True:
# 人类玩家下棋
print("请输入你要下棋的坐标,用逗号分隔(如:7,7):")
x, y = map(int, input().split(','))
if chessboard[x][y] != EMPTY:
print("这个位置已经有棋子了!")
continue
chessboard[x][y] = WHITE
# 判断游戏是否结束
if ai.is_win(chessboard, WHITE):
print("你赢了!")
break
elif ai.get_empty_count(chessboard) == 0:
print("平局!")
break
# AI下棋
print("轮到我下棋了...")
x, y = ai.alpha_beta_search(chessboard)
print("我在 (%d, %d) 下了一步" % (x, y))
chessboard[x][y] = BLACK
# 判断游戏是否结束
if ai.is_win(chessboard, BLACK):
print("我赢了!")
break
elif ai.get_empty_count(chessboard) == 0:
print("平局!")
break
注意,坐标是从0开始的