关于核心判断部分 maxmin()解释:
该函数根据当前游戏状态的得分,计算出下一步应该走的位置。该函数的参数如下:
- board:表示当前的游戏状态,是一个 3x3 的二维数组。
- depth:表示搜索的深度,即预测未来多少步。
- alpha:表示当前最好的评分(对于 maximizing 玩家来说),初始化为负无穷。
- beta:表示当前最好的评分(对于 minimizing 玩家来说),初始化为正无穷。
- maximizing:表示当前是轮到哪个玩家走棋,True 表示 maximizing 玩家,False 表示 minimizing 玩家。
该函数的返回值包括两个元素:
- best_score:表示当前的最优得分。
- best_move:表示当前应该走的位置。
在函数内部,首先使用 check_win 和 check_tie 函数判断当前游戏状态,如果存在胜负或平局,则返回对应的得分。如果还没有到达搜索的深度,则进入下一步的搜索。
如果当前是 maximizing 玩家,则使用 for 循环遍历棋盘中所有空位,对于每个空位,都假设 maximizing 玩家会走这个位置,并计算下一步的得分。如果得分比当前最优得分更好,则更新最优得分和最优位置。同时,更新 alpha 的值为当前最优得分和 alpha 中的最大值。如果 beta 的值小于或等于 alpha,则可以停止搜索并返回结果。
如果当前是 minimizing 玩家,则与 maximizing 玩家的情况类似,只是更新的是 beta 的值。
最终返回当前的最优得分和最优位置。
import math
def print_board(board):
for row in board:
print(" | ".join(row))
print()
# 判断是否有获胜者
def check_win(board, player):
for i in range(3):
if all(board[i][j] == player for j in range(3)):
return True
if all(board[j][i] == player for j in range(3)):
return True
if all(board[i][i] == player for i in range(3)):
return True
if all(board[i][2 - i] == player for i in range(3)):
return True
return False
# 判断是否平局
def check_tie(board):
for row in board:
for cell in row:
if cell == " ":
return False
return True
# 获得玩家落子位置
def get_player_move(board):
while True:
try:
row = int(input("输入行数 (1-3): ")) - 1
col = int(input("输入列数 (1-3): ")) - 1
if board[row][col] == " ":
return row, col
else:
print("这个位置已经被占,请重新输入.")
except ValueError:
print("请输入1-3之间的数.")
# 极大极小/α-β剪枝算法
def minmax(board, depth, alpha, beta, maximizing):
if check_win(board, "X"):
return -10, None
if check_win(board, "O"):
return 10, None
if check_tie(board):
return 0, None
if maximizing:
best_score = -math.inf
best_move = None
for row in range(3):
for col in range(3):
if board[row][col] == " ":
board[row][col] = "O"
score, _ = minmax(board, depth - 1, alpha, beta, False)
board[row][col] = " "
if score > best_score:
best_score = score
best_move = (row, col)
alpha = max(alpha, best_score)
if beta <= alpha:
break
return best_score, best_move
else:
best_score = math.inf
best_move = None
for row in range(3):
for col in range(3):
if board[row][col] == " ":
board[row][col] = "X"
score, _ = minmax(board, depth - 1, alpha, beta, True)
board[row][col] = " "
if score < best_score:
best_score = score
best_move = (row, col)
beta = min(beta, best_score)
if beta <= alpha:
break
return best_score, best_move
def play_game():
board = [[" " for j in range(3)] for i in range(3)]
print_board(board)
# 玩家选择先后手
while True:
user_choice = input("选择X或者O(X先手): ")
if user_choice.lower() == "x":
player = "X"
break
elif user_choice.lower() == "o":
player = "O"
break
else:
print("请输入X或O.")
# 玩家先手
if player == "X":
while not check_win(board, "X") and not check_tie(board):
row, col = get_player_move(board)
board[row][col] = "X"
print_board(board)
if check_win(board, "X"):
print("玩家获胜!")
return
if check_tie(board):
print("平局!")
return
_, (row, col) = minmax(board, 9, -math.inf, math.inf, True)
print("电脑思考后落子", (row+1, col+1))
board[row][col] = "O"
print_board(board)
if check_win(board, "O"):
print("玩家失败!")
return
if check_tie(board):
print("平局!")
return
# 电脑先手
else:
while not check_win(board, "O") and not check_tie(board):
_, (row, col) = minmax(board, 9, -math.inf, math.inf, True)
print("电脑思考后落子", (row+1, col+1))
board[row][col] = "X"
print_board(board)
if check_win(board, "X"):
print("玩家失败!")
return
if check_tie(board):
print("平局!")
return
row, col = get_player_move(board)
board[row][col] = "O"
print_board(board)
if check_win(board, "O"):
print("玩家获胜!")
return
if check_tie(board):
print("平局!")
return
if __name__ == '__main__':
play_game()