运行效果
当前棋盘:
| | | |
| | | |
| | | |
AI为 'o' 棋,玩家为 'x' 棋,玩家先
放置棋子输入格式:行号,列号(数值为0/1/2)
请输入要放置棋的坐标:0,1
当前棋盘:
| | o | |
| | | |
| | | |
AI进行下一步...
当前棋盘:
| | o | |
| | x | |
| | | |
请输入要放置棋的坐标:0,0
当前棋盘:
| o | o | |
| | x | |
| | | |
AI进行下一步...
当前棋盘:
| o | o | x |
| | x | |
| | | |
请输入要放置棋的坐标:2,0
当前棋盘:
| o | o | x |
| | x | |
| o | | |
AI进行下一步...
当前棋盘:
| o | o | x |
| x | x | |
| o | | |
请输入要放置棋的坐标:1,2
当前棋盘:
| o | o | x |
| x | x | o |
| o | | |
AI进行下一步...
游戏结束!平局
核心代码
def cal_win_value(chessboard: Chessboard):
"""
计算当前棋盘AI的得分(AI能赢解个数减去玩家能赢的解个数)
:param chess_type 要判断的棋子种类
"""
# 如果用户直接可以赢,则得分无穷小,采取防守策略
win, winner_chess = chessboard.can_win()
if not win and winner_chess is 'both':
print("游戏结束!平局")
exit()
elif win and winner_chess is chess_player:
return MIN
num_map = {
chess_ai: 0,
chess_player: 0
}
# 分别计算当前棋局AI以及玩家能赢的解有多少种
for chess_type in [chess_ai, chess_player]:
temp_board = chessboard.copy_new()
# 将空位全部填充为某一类型的棋子
for row in range(3):
for col in range(3):
if temp_board.data[row][col] is not the_other(chess_type):
temp_board.data[row][col] = chess_type
# 计算横向可以赢的个数
for row in range(3):
row_status = True
for col in range(3):
if temp_board.data[row][col] is not chess_type:
row_status = False
if row_status is True:
num_map[chess_type] += 1
# 计算纵向可以赢的个数
for col in range(3):
col_status = True
for row in range(3):
if temp_board.data[row][col] is not chess_type:
col_status = False
if col_status is True:
num_map[chess_type] += 1
# 检查主对角线可以赢的个数
main_diag_status = True
for i in range(3):
if temp_board.data[i][i] is not chess_type:
main_diag_status = False
if main_diag_status is True:
num_map[chess_type] += 1
# 检查副对角线可以赢的个数
para_diag_status = True
for i in range(3):
if temp_board.data[2 - i][i] is not chess_type:
para_diag_status = False
if para_diag_status is True:
num_map[chess_type] += 1
return num_map[chess_ai] - num_map[chess_player]
def cal_total_value(chessboard: Chessboard, x_ai, y_ai):
"""
计算将要进行的一步棋的总得分
"""
total_value = 0
# win, winner_chess = chessboard.can_win()
# if win and winner_chess is chess_ai:
# return MAX
# elif win and winner_chess is chess_player:
# return -MIN
# 新建一个临时的棋盘,模拟之后的两步
temp_board = chessboard.copy_new()
if temp_board.can_put(x_ai, y_ai):
# AI走一步
temp_board.put_chess(chess_ai, x_ai, y_ai)
# AI可以绝杀
win, winner_chess = temp_board.can_win()
if win:
return MAX
# 若不能绝杀,则需要预测玩家,计算最大得分的解
empty_psts = chessboard.get_empty_psts()
# 遍历所有空位置,模拟玩家走一步
for x_player, y_player in empty_psts:
inner_temp_board = temp_board.copy_new()
if inner_temp_board.can_put(x_player, y_player):
# 玩家走一步
inner_temp_board.put_chess(chess_player, x_player, y_player)
# 计算当前棋盘的得分
value = cal_win_value(inner_temp_board)
total_value += value
return total_value
def ai_put(chessboard: Chessboard):
"""
AI放置一枚棋子
:param chessboard:
:return:
"""
empty_psts = chessboard.get_empty_psts()
max_value = MIN
for row, col in empty_psts:
value = cal_total_value(chessboard, row, col)
if value > max_value:
max_value = value
determined_x = row
determined_y = col
chessboard.put_chess(chess_ai, determined_x, determined_y)
完整代码
我将积累的一些算法发布到了Gihub仓库中,其中涉及一些常见的算法以及人工智能方面的算法,其中有该程序的完整实现代码。
仓库地址:https://github.com/yub1ng/Algorithm
个人博客地址:http://qiyubing.cn