[Python] 纯文本查看 复制代码
import turtle
import random
# 设置屏幕
screen = turtle.Screen()
screen.title("五子棋小游戏 - 玩家 vs AI")
screen.setup(width=650, height=650)
screen.tracer(0)
# 常量定义
board_size = 15 # 棋盘大小 15x15
cell_size = 40 # 每个格子宽度和高度
offset_x = -cell_size * (board_size - 1) / 2
offset_y = -cell_size * (board_size - 1) / 2
# 棋盘矩阵
board = [[0 for _ in range(board_size)] for _ in range(board_size)] # 0为空,1为玩家,2为AI
# 当前回合
player_turn = True
# 棋子画笔
pen = turtle.Turtle()
pen.hideturtle()
pen.speed(0)
# 绘制棋盘
def draw_board():
pen.penup()
pen.color("black")
# 画横线
for i in range(board_size):
y = offset_y + i * cell_size
pen.goto(offset_x, y)
pen.pendown()
pen.goto(offset_x + (board_size - 1) * cell_size, y)
pen.penup()
# 画竖线
for j in range(board_size):
x = offset_x + j * cell_size
pen.goto(x, offset_y)
pen.pendown()
pen.goto(x, offset_y + (board_size - 1) * cell_size)
pen.penup()
# 画星位
star_positions = [
(3, 3), (11, 3), (3, 11), (11, 11), (7, 7)
]
for x, y in star_positions:
pen.goto(offset_x + x * cell_size, offset_y + y * cell_size)
pen.dot(10, "black")
# 绘制棋子
def draw_piece(x, y, color):
pen.penup()
screen_x = offset_x + x * cell_size
screen_y = offset_y + y * cell_size
pen.goto(screen_x, screen_y - cell_size * 0.4)
pen.dot(cell_size * 0.8, color)
# 检查胜负
def check_winner(x, y, player):
"""检查某个点是否形成五子连珠"""
directions = [
(1, 0), # 水平
(0, 1), # 垂直
(1, 1), # 主对角线
(1, -1) # 副对角线
]
for dx, dy in directions:
count = 1 # 当前点计为1
for step in range(1, 5): # 向一个方向延伸
nx, ny = x + dx * step, y + dy * step
if 0 <= nx < board_size and 0 <= ny < board_size and board[nx][ny] == player:
count += 1
else:
break
for step in range(1, 5): # 向反方向延伸
nx, ny = x - dx * step, y - dy * step
if 0 <= nx < board_size and 0 <= ny < board_size and board[nx][ny] == player:
count += 1
else:
break
if count >= 5: # 连续5个
return True
return False
# 玩家回合
def on_click(x, y):
global player_turn
if not player_turn: # 若不是玩家回合,忽略点击
return
# 将屏幕坐标转换为棋盘坐标
board_x = round((x - offset_x) / cell_size)
board_y = round((y - offset_y) / cell_size)
# 检查是否在棋盘范围内
if 0 <= board_x < board_size and 0 <= board_y < board_size:
if board[board_x][board_y] == 0: # 该位置为空
board[board_x][board_y] = 1 # 玩家棋子
draw_piece(board_x, board_y, "black")
# 检查玩家是否胜利
if check_winner(board_x, board_y, 1):
screen.update()
print("玩家胜利!")
turtle.bye()
return
player_turn = False # 玩家回合结束
screen.update()
ai_turn() # 轮到AI
# AI回合
def ai_turn():
global player_turn
def evaluate_position(x, y, player):
"""对某个位置进行评分"""
if board[x][y] != 0:
return -1 # 已有棋子的位置不可用
score = 0
directions = [
(1, 0), # 水平
(0, 1), # 垂直
(1, 1), # 主对角线
(1, -1) # 副对角线
]
for dx, dy in directions:
count = 0
for step in range(1, 5):
nx, ny = x + dx * step, y + dy * step
if 0 <= nx < board_size and 0 <= ny < board_size and board[nx][ny] == player:
count += 1
else:
break
for step in range(1, 5):
nx, ny = x - dx * step, y - dy * step
if 0 <= nx < board_size and 0 <= ny < board_size and board[nx][ny] == player:
count += 1
else:
break
score += count ** 2 # 连续棋子数量的平方作为评分
return score
# 找出所有空位并评分
best_score = -1
best_move = None
for x in range(board_size):
for y in range(board_size):
if board[x][y] == 0: # 空位
# 优先考虑阻止玩家
score_player = evaluate_position(x, y, 1)
score_ai = evaluate_position(x, y, 2)
if score_player >= 16: # 如果玩家即将连成五子,优先阻止
best_move = (x, y)
break
score = max(score_player, score_ai) # 评分取攻守最大值
if score > best_score:
best_score = score
best_move = (x, y)
if best_move is not None and best_score >= 16:
break
# AI落子
if best_move:
x, y = best_move
board[x][y] = 2
draw_piece(x, y, "red")
# 检查AI是否胜利
if check_winner(x, y, 2):
screen.update()
print("AI胜利!")
turtle.bye()
return
player_turn = True # 轮到玩家
screen.update()
# 绘制棋盘
draw_board()
# 绑定鼠标点击事件
screen.onclick(on_click)
# 保持窗口
turtle.done()