import numpy as np
BOARD_SIZE = 15
EMPTY = 0
PLAYER = 1
AI = 2
class GobangGame:
def __init__(self):
self.board = np.zeros((BOARD_SIZE, BOARD_SIZE), dtype=int)
def is_win(self, x, y, chess_type):
directions = [[1, 0], [0, 1], [1, 1], [1, -1]]
for dx, dy in directions:
count = 1
cx, cy = x + dx, y + dy
while 0 <= cx < BOARD_SIZE and 0 <= cy < BOARD_SIZE and self.board[cx][cy] == chess_type:
count += 1
cx += dx
cy += dy
cx, cy = x - dx, y - dy
while 0 <= cx < BOARD_SIZE and 0 <= cy < BOARD_SIZE and self.board[cx][cy] == chess_type:
count += 1
cx -= dx
cy -= dy
if count >= 5:
return True
return False
def get_continuous(self, start_x, start_y, dx, dy, chess_type):
"""获取连续棋子数量,并且判断两端是否有空位,返回(连子数量,左边空位,右边空位)"""
cnt = 1
left_empty, right_empty = False, False
# 往反方向查找
x1, y1 = start_x - dx, start_y - dy
if 0 <= x1 < BOARD_SIZE and 0 <= y1 < BOARD_SIZE and self.board[x1][y1] == EMPTY:
left_empty = True
while 0 <= x1 < BOARD_SIZE and 0 <= y1 < BOARD_SIZE and self.board[x1][y1] == chess_type:
cnt += 1
x1 -= dx
y1 -= dy
# 正方向查找
x2, y2 = start_x + dx, start_y + dy
if 0 <= x2 < BOARD_SIZE and 0 <= y2 < BOARD_SIZE and self.board[x2][y2] == EMPTY:
right_empty = True
while 0 <= x2 < BOARD_SIZE and 0 <= y2 < BOARD_SIZE and self.board[x2][y2] == chess_type:
cnt += 1
x2 += dx
y2 += dy
return cnt, left_empty, right_empty
def get_score(self, x, y):
"""修正后的打分函数,只判断连续棋子"""
if self.board[x][y] != EMPTY:
return -1
score = 0
directions = [[1, 0], [0, 1], [1, 1], [1, -1]]
# 模拟落子
self.board[x][y] = AI
for dx, dy in directions:
ai_num, ai_left, ai_right = self.get_continuous(x, y, dx, dy, AI)
if ai_num == 4:
if ai_left and ai_right:
score += 100000 # AI活四优先级最高
else:
score += 10000 # AI冲四
elif ai_num == 3:
if ai_left and ai_right:
score += 5000
else:
score += 800
elif ai_num == 2:
if ai_left and ai_right:
score += 300
else:
score += 50
self.board[x][y] = EMPTY
# 评估玩家威胁,AI防守
self.board[x][y] = PLAYER
for dx, dy in directions:
p_num, p_left, p_right = self.get_continuous(x, y, dx, dy, PLAYER)
if p_num == 4:
if p_left and p_right:
score += 80000 # 玩家活四必须堵
else:
score += 9000
elif p_num == 3:
if p_left and p_right:
score += 4000
else:
score += 700
elif p_num == 2:
if p_left and p_right:
score += 200
self.board[x][y] = EMPTY
# 棋盘中心位置加分
distance = abs(x - 7) + abs(y - 7)
score += (14 - distance) * 6
return score
def ai_choose(self):
max_score = -1
best_x, best_y = 7, 7
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if self.board[i][j] == EMPTY:
current_score = self.get_score(i, j)
if current_score > max_score:
max_score = current_score
best_x, best_y = i, j
return best_x, best_y
def is_board_full(self):
"""判断棋盘已满,平局"""
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if self.board[i][j] == EMPTY:
return False
return True
def print_board(self):
print(" ", end="")
for idx in range(BOARD_SIZE):
print(f"{idx:2d}", end=" ")
print()
for i in range(BOARD_SIZE):
print(f"{i:2d}", end=" ")
line = []
for j in range(BOARD_SIZE):
val = self.board[i][j]
if val == PLAYER:
line.append("●")
elif val == AI:
line.append("○")
else:
line.append(".")
print(" ".join(line))
def start_game(self):
print("====五子棋人机对战====")
print("你执黑棋●先行,输入坐标 x y 例如:7 7")
while True:
self.print_board()
# 玩家落子
while True:
try:
x, y = map(int, input("请输入落子坐标(x y):").split())
if 0 <= x < BOARD_SIZE and 0 <= y < BOARD_SIZE and self.board[x][y] == EMPTY:
break
else:
print("坐标越界或者该位置已有棋子,请重新输入!")
except Exception:
print("输入格式错误,示例:7 7")
self.board[x][y] = PLAYER
if self.is_win(x, y, PLAYER):
self.print_board()
print("恭喜你战胜AI!游戏结束")
break
if self.is_board_full():
self.print_board()
print("棋盘已满,本局平局!")
break
# AI落子
ai_x, ai_y = self.ai_choose()
self.board[ai_x][ai_y] = AI
print(f"\nAI落子位置:{ai_x} {ai_y}")
if self.is_win(ai_x, ai_y, AI):
self.print_board()
print("AI获胜,游戏结束!")
break
if self.is_board_full():
self.print_board()
print("棋盘已满,本局平局!")
break
if __name__ == "__main__":
game = GobangGame()
game.start_game()