欢乐五子棋辅助
Posted starrys
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了欢乐五子棋辅助相关的知识,希望对你有一定的参考价值。
苦练技术是不可能的,这辈子不可能好好练习。学技术又学不进去,就只有靠辅助才能维持的生活这样子。
简述
最近玩微信小程序 - 欢乐五子棋,结果老是被虐,好气啊。偶然想到了前段时间网上很火爆的跳一跳辅助。简单想了一想辅助实现的思路,发现目前所需的工具已经足够。
需要的工具主要分为以下三类:
-
Yixin 奕心引擎,这个引擎是国人所作,可以说是非商用版里面最强的五子棋AI
这个是官网 https://www.aiexp.info/pages/yixin-cn.html
一开始我想使用奕心的界面+引擎那款,因为可定制性足够强,结果发现Python 不好与带界面的程序进行交互,所以就选择了引擎。然而尴尬的一点是,我把官方文档翻了个遍都没有找到引擎的使用方法。不过后来在世界五子棋锦标赛 https://gomocup.org/ 找到了参加比赛的AI 必备的两种接口。
http://petr.lastovicka.sweb.cz/protocl2en.htm 使用输入输出流,本文选择的就是这种方式
-
Python 简单图片处理
-
Python adb 操作手机
思路
整个思路如下图,我们按照上面的顺序从简到繁,开始介绍每个模块。整个思路顺下来程序其实是比较好写的,就是前期需要手动的截取匹配图片,查看相应的像素点位置。
实现
前期准备
下面的区域参数以我的手机1920*1080为例,不同屏幕请自行适配
class mVars:
address=‘C:/Users/EA/Desktop/yixin/‘ # 使用到的文件所存放地址
boradOne = 67 #一个相邻落子点的像素间隔
borad = (65,480) #用来将图片像素坐标和棋盘坐标互转
confirmBW = (820,1590,820+45,1590+60)#用来确定己方是黑棋还是白棋的区域
confirmWin = (660,1780,660+46,1780+46)#用来确定是否胜利的区域
这些是前期需要准备好的图片,至于怎么获取这些图片,等后面有时间会在补充在文末,事实上,做好这些准备工作,整个进度就完成了30%
Yixin 引擎
从官网上可以下载这个Yixin 引擎 http://gomocup.org/static/download-ai/YIXIN18.zip
结合 http://petr.lastovicka.sweb.cz/protocl2en.htm 可以知道如何与引擎交互
我使用 subprocess 这个模块让python 与 引擎交互
import subprocess as sub
class YiXin:
mYixin = sub.Popen(mVars.address+"Yixin.exe", stdin=sub.PIPE, stdout=sub.PIPE, stderr=sub.PIPE)
def __init__(self):
self.input(‘START 15‘)
self.input(‘INFO timeout_match 300000‘)
self.input(‘INFO timeout_turn 10000‘)
self.output()
print("YiXin ready!!")
def input(self,str): #向Yixin 输入对手落子指令
print(‘Human: ‘+str)
self.mYixin.stdin.write((str+‘
‘).encode())
self.mYixin.stdin.flush()
def output(self): #获取Yixin 的输出
#一直获取Yixin 输出,直到落子的指令或其它
while True:
str = bytes.decode(self.mYixin.stdout.readline())
print(‘YiXin: ‘+ str,end=‘‘)
if ((‘,‘ in str) or (‘OK‘ in str)):
break;
self.mYixin.stdout.flush()
if(‘,‘ in str):
return str
def restart(self):
self.input(‘RESTART 15‘)
self.output()
图片处理
这个模块需要做的事就是处理跟图片相关的,包括比较图片,转换坐标等
起初有两种思路,1.每隔一段时间获取截一张图,对比两张图不同的地方,从而获取对手落点位置。2.没隔一段时间截一张图,识别图上的所有有棋的位置并保存,然后通过比较,得到对手落子位置。出于效率考虑,我选择了第一种方法。
class ImageProcess:
#如果匹配成功,则返回中心像素点
def matchImg(self,imgsrc,imgobj,confidence=0.8):
coord = None
res = ac.find_template(imgsrc,imgobj,confidence)
if res != None:
coord = (int(res[‘result‘][0]),int(res[‘result‘][1]))
return coord
#将像素坐标转化为棋盘坐标
def transformBoard(self,coord):
x = coord[0]
y = coord[1]
xcoord = ycoord = 0
while x>=mVars.borad[0]:
x-=mVars.boradOne
xcoord+=1
while y>=mVars.borad[1]:
y-=mVars.boradOne
ycoord+=1
return xcoord-1,ycoord-1
#将棋盘坐标转化为像素坐标
def transfromScreen(self,coord):
return (coord[0]*mVars.boradOne+mVars.borad[0],coord[1]*mVars.boradOne+mVars.borad[1])
#对比两张图片的差异
def difference(self,img1,img2):
return img1-img2
ADB 模块
这个模块与手机交互,这块我用的是无线ADB连接,当然也可以有线连接,关于ADB连接教程见https://github.com/mzlogin/awesome-adb
import os
import time
class Adb:
#无线连接手机
def __init__(self):
os.system(‘adb connect 1.1.1.1:5555‘)#ip 示例
os.system(‘adb devices‘)
#捕获截图
def capture(self):
os.system(‘adb exec-out screencap -p > ‘+mVars.address+‘sc.jpg‘)
return ac.imread(mVars.address+‘sc.jpg‘)
#点击特定位置
def click(self,piexl):
os.system(‘adb shell input tap %d %d‘%(piexl[0],piexl[1]))
time.sleep(0.1)
os.system(‘adb shell input tap %d %d‘%(piexl[0],piexl[1]))
游戏系统模块
class System:
Yixin = YiXin()
ImageP = ImageProcess()
Adb = Adb()
imgobj = None #用来检测对手落子的图片
certain = 0 #1表示己方为白,2表示己方为黑
#确认是否胜利
def confirmWin(self,imgsrc):
x0,y0,x1,y1 = mVars.confirmWin
imgsrc = imgsrc[y0:y1,x0:x1]
imgobj = ac.imread(mVars.address+‘confirmwin.jpg‘)
return self.ImageP.matchImg(imgsrc,imgobj,0.9)
#确认己方是黑棋还是白棋
def confirmBW(self,imgsrc):
x0,y0,x1,y1 = mVars.confirmBW
imgsrc = imgsrc[y0:y1,x0:x1]
imgobjw = ac.imread(mVars.address+‘confirmw.jpg‘)
imgobjb = ac.imread(mVars.address+‘confirmb.jpg‘)
if (self.ImageP.matchImg(imgsrc,imgobjw,0.8) != None):
self.certain = 1
self.imgobj=ac.imread(mVars.address+‘objb.jpg‘)
elif (self.ImageP.matchImg(imgsrc,imgobjb,0.8)!= None):
self.certain = 2
self.imgobj=ac.imread(mVars.address+‘objw.jpg‘)
#做好比赛前准备,
def ready(self):
while True:
imgsrc = self.Adb.capture()
self.confirmBW(imgsrc)
if(self.certain != 0):
break;
print(‘UnCertain‘)
time.sleep(1)
if self.certain == 2:
self.runCommand(‘BEGIN‘)
return imgsrc
elif self.certain == 1:
return ac.imread(mVars.address+‘None.jpg‘)
#向Yixin 输入对方落点,获得Yixin 落点并点击屏幕
def runCommand(self,COMMAND):
self.Yixin.input(COMMAND)
str = self.Yixin.output()
a = str.find(‘,‘)
b = str.find(‘
‘)
piexl = self.ImageP.transfromScreen((int(str[0:a]),int(str[a+1:b])))
# print(piexl)
self.Adb.click(piexl)
#开始游戏
def play(self,imgsrc):
flag=False
imagep = self.ImageP
oldimg = newimg = imgsrc
while self.confirmWin(newimg) == None:
imgdif = imagep.difference(oldimg,newimg)
ac.cv2.imwrite(mVars.address+‘diff.jpg‘,imgdif)
coord = imagep.matchImg(imgdif,self.imgobj)
# print(coord)
if(coord != None):
x, y = imagep.transformBoard(coord)
COMMAND = "TURN %d,%d"%(x,y)
self.runCommand(COMMAND)
oldimg,newimg = newimg,self.Adb.capture()
time.sleep(0.8)
#新一轮游戏
def newGame(self):
time.sleep(4)
os.system(‘cls‘)
os.system(‘adb shell input tap %d %d‘%(100,1820))
time.sleep(0.5)
os.system(‘adb shell input tap %d %d‘%(540,940))
self.Yixin.restart()
self.certain = 0
self.imgobj = None
主函数
msys = System()
# n = input("请输入你想玩的局数:")
# for i in range(1,int(n)+1):
while True:
imgBegin = msys.ready()
msys.play(imgBegin)
print("You Win !! Next Game Will Begin After 4sec")
msys.newGame()
后记
所有代码到这里就结束了,后面将用到的资源整理一下再上传。
已经成功的上到最高级,胜率不是100%,因为欢乐五子棋没有禁手,所以执白时偶尔会输,但执黑必胜
以上是关于欢乐五子棋辅助的主要内容,如果未能解决你的问题,请参考以下文章
女朋友下棋比我厉害,还特别嚣张,Python敲个辅助,看她如何嚣张