運行效果
當(dāng)前棋盤:
| | | |
| | | |
| | | |
AI為 'o' 棋,玩家為 'x' 棋太雨,玩家先
放置棋子輸入格式:行號,列號(數(shù)值為0/1/2)
請輸入要放置棋的坐標(biāo):0,1
當(dāng)前棋盤:
| | o | |
| | | |
| | | |
AI進行下一步...
當(dāng)前棋盤:
| | o | |
| | x | |
| | | |
請輸入要放置棋的坐標(biāo):0,0
當(dāng)前棋盤:
| o | o | |
| | x | |
| | | |
AI進行下一步...
當(dāng)前棋盤:
| o | o | x |
| | x | |
| | | |
請輸入要放置棋的坐標(biāo):2,0
當(dāng)前棋盤:
| o | o | x |
| | x | |
| o | | |
AI進行下一步...
當(dāng)前棋盤:
| o | o | x |
| x | x | |
| o | | |
請輸入要放置棋的坐標(biāo):1,2
當(dāng)前棋盤:
| o | o | x |
| x | x | o |
| o | | |
AI進行下一步...
游戲結(jié)束!平局
核心代碼
def cal_win_value(chessboard: Chessboard):
"""
計算當(dāng)前棋盤AI的得分(AI能贏解個數(shù)減去玩家能贏的解個數(shù))
:param chess_type 要判斷的棋子種類
"""
# 如果用戶直接可以贏,則得分無窮小套啤,采取防守策略
win, winner_chess = chessboard.can_win()
if not win and winner_chess is 'both':
print("游戲結(jié)束彤侍!平局")
exit()
elif win and winner_chess is chess_player:
return MIN
num_map = {
chess_ai: 0,
chess_player: 0
}
# 分別計算當(dāng)前棋局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
# 計算橫向可以贏的個數(shù)
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
# 計算縱向可以贏的個數(shù)
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
# 檢查主對角線可以贏的個數(shù)
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
# 檢查副對角線可以贏的個數(shù)
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
# 若不能絕殺,則需要預(yù)測玩家盏阶,計算最大得分的解
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)
# 計算當(dāng)前棋盤的得分
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)
完整代碼
我將積累的一些算法發(fā)布到了Gihub倉庫中,其中涉及一些常見的算法以及人工智能方面的算法,其中有該程序的完整實現(xiàn)代碼吴汪。
倉庫地址:https://github.com/yub1ng/Algorithm
個人博客地址:http://qiyubing.cn