写完忘记发了,今天补上
第九步 上一步我们已经完成了一个AI大脑的最核心功能。我们可以用它来对战了。
访问服务器http://xxx/join_game ,会返回一个游戏编号game_id。之后你可以使用这个游戏编号,进行游戏http://xxx/play_game/{game_id} 并查询游戏状态http://xxx/check_game/{game_id} 。
利用这三个功能我们就可以让我们的AI参战了。这个过程应该是这样的,这是一个典型的消息循环。
用join_game加入游戏
用check_game检查游戏状态
a. 如果游戏完成就退出
b. 如果不轮你下,就等一会,否则使用AI确定要落子的位置,并用play_game告知服务器你落子的位置
c. 返回到第2步用check_game检查游戏状态
其中join_game 需要登录,需要提交用户名和密码,需要使用第五步使用的加密方法对密码加密,用户名写入user 字段,加密后的密码写入password 字段。另外需要传入字段data_type ,将其设为json ,返回字段game_id 是加入的游戏编号。 play_game 也需要登录,落子的坐标写入coord 字段。 check_game 不需要登录,返回当前的游戏状态, 会返回以下状态:
is_success,error 查询是否成功及错误原因 step 当前是第几步 creator 游戏一方的用户名 creator_name 游戏一方的名字(昵称) creator_stone 游戏一方使用的棋子(x表示黑棋,o表示白棋) opponent 游戏另一方的用户名 opponent_name 游戏另一方的名字(昵称) opponent_stone 游戏另一方使用的棋子(x表示黑棋,o表示白棋) ready 游戏是否就绪,两个玩家都在线时,游戏进入就绪状态 current_turn 当前应当落子的玩家的用户名 current_stone 当前应当落子的玩家的使用的棋子(x表示黑棋,o表示白棋) left_time 剩余时间,为避免玩家过长思考,限制玩家必须在60秒内落子,否则游戏结束 winner 获胜的玩家的用户名,当游戏没有产生赢家时,该值为None board 棋盘的坐标表示 last_step 上一步落子的坐标 win_step 如果一方获胜,这个字段给出连成五子的一条线的棋子坐标 注意不要过于频繁的检查游戏的状态,使用sleep函数等待服务器更新状态,两次检查以5到10秒的间隔为宜。
任务 9 实现消息循环,开始作战吧! 修改了第八步的代码,因为觉得每次对方落子后都模拟整个棋盘一次太慢,所以加了对方落子函数,下棋过程中就不再需要每次遍历board 后重新绘制棋局了。轮到自己时利用last_step 确认对方落子位置即可。
import time
import urllib
import urllib.request
import urllib.response
import json
win_type = {"CMMMM": 10000, "MCMMM": 10000, "MMCMM": 10000, "MMMCM": 10000, "MMMMC": 10000}
defense_type = {"OOOOC": 6000, "COOOO": 6000}
latent_win_type = {".CMMM.": 5000, ".MCMM.": 5000, ".MMCM.": 5000, ".MMMC.": 5000}
latent_defense_type = {"COOO.": 2500, ".OOOC": 2500, ".OOCO.": 2500, ".OCOO.": 2500}
kill_type = {"OCMMM.": 2000, "OMCMM.": 2000, "OMMCM.": 2000, "OMMMC.": 2000, ".CMMMO": 2000, ".MCMMO": 2000,
".MMCMO": 2000, ".MMMCO": 2000}
latent_kill_type = {".MMC.": 400, ".MCM.": 400, ".CMM.": 400}
foresee_type = {".OOC": 400, "COO.": 400, "MOOOC": 400, "COOOM": 400}
invalid_type = {".MMCO": 200, ".MCMO": 200, ".CMMO": 200, "OMMC.": 200, "OMCM.": 200, "OCMM.": 200, "MOOC": 200,
"COOM": 200}
layout_type = {".MC.": 50, ".CM.": 50}
com = [win_type, defense_type, latent_win_type, latent_defense_type, kill_type, latent_kill_type, foresee_type,
invalid_type, layout_type]
def join_game():
req = urllib.request.Request(f'http://xxx/join_game?user={user}&password={password}&data_type=json')
res_data = urllib.request.urlopen(req)
res = res_data.read()
g_i = json.loads(res)['game_id']
return g_i
def check_game():
req = urllib.request.Request(f'http://xxx/check_game/{game_id}')
res_data = urllib.request.urlopen(req)
res = res_data.read()
str1 = json.loads(res)
return str1
def play_game(coord):
print("我落子:" + coord)
req = urllib.request.urlopen(
f'http://xxx/play_game/{game_id}?user={user}&password={password}&coord={coord}')
def draw_board():
for i in range(15):
board.append([])
for j in range(15):
board[i].append(".")
def calculate_score(str1):
sum1 = 0
for i in com:
for item, value in i.items():
if item in str1:
sum1 = sum1 + value
return int(sum1)
def game_transform(mes):
if mes['current_stone'] == "x":
for i in range(0, len(mes['board']), 2):
a = ord(mes['board'][i]) - 97
b = ord(mes['board'][i + 1]) - 97
if board[a][b] == "x":
board[a][b] = "M"
elif board[a][b] == "o":
board[a][b] = "O"
else:
for i in range(0, len(mes['board']), 2):
a = ord(mes['board'][i]) - 97
b = ord(mes['board'][i + 1]) - 97
if board[a][b] == "x":
board[a][b] = "O"
elif board[a][b] == "o":
board[a][b] = "M"
def transverse_judge(a, b):
a = a
b = b
str1 = []
for j in range(-4, 5):
if 0 <= b + j <= 14:
str1.append(board[a][b + j])
else:
continue
str1 = "".join(str1)
return calculate_score(str1)
def portrait_judge(a, b):
a = a
b = b
str1 = []
for j in range(-4, 5):
if 0 <= a + j <= 14:
str1.append(board[a + j][b])
else:
continue
str1 = "".join(str1)
return calculate_score(str1)
def left_leaning_judge(a, b):
a = a
b = b
str1 = []
for j in range(-4, 5):
if 0 <= a + j <= 14 and 0 <= b + j <= 14:
str1.append(board[a + j][b + j])
else:
continue
str1 = "".join(str1)
return calculate_score(str1)
def right_deviation_judge(a, b):
a = a
b = b
str1 = []
for j in range(-4, 5):
if 0 <= a - j <= 14 and 0 <= b + j <= 14:
str1.append(board[a - j][b + j])
else:
continue
str1 = "".join(str1)
return calculate_score(str1)
def play(message):
if message['current_turn'] != user:
print("Waiting for the opponent...")
return
else:
print("Let me think twice...")
if message['board'] == '':
play_game("hh")
board[7][7] = message['current_stone']
else:
luozi(message)
game_transform(message)
sum_max = 0
site1 = 0
site2 = 0
for num1 in range(15):
for num2 in range(15):
max1 = 0
if board[num1][num2] == ".":
board[num1][num2] = "C"
max1 = max1 + transverse_judge(num1, num2) + portrait_judge(num1, num2) + left_leaning_judge(
num1, num2) + right_deviation_judge(num1, num2)
board[num1][num2] = "."
if sum_max < max1:
sum_max = max1
site1 = num1
site2 = num2
str1 = chr(site1 + 97) + chr(site2 + 97)
play_game(str1)
board[site1][site2] = message['current_stone']
def luozi(mes):
num1 = ord(mes['last_step'][0]) - 97
num2 = ord(mes['last_step'][1]) - 97
if mes['current_stone'] == "x":
board[num1][num2] = "o"
else:
board[num1][num2] = "x"
user = "user"
password = "xxx"
game_id = join_game()
board = []
draw_board()
while 1:
mess = check_game()
print(mess)
if mess['winner'] != "None":
print("胜利者:" + mess['winner'])
break
else:
if mess['ready'] == "False":
continue
else:
play(mess)
time.sleep(6)
应该算只用了贪心的算法,后续优化可以选择学习极大极小算法 和AlphaBeta剪枝算法 、多线程等等,也可以利用机器学习写ai进行训练。最后这个五子棋没有考虑黑棋禁手以及换手等规则,需要的话还得学。 总之这就能将就着用了,也挺简单就可以看明白的。
|