橘子的英文译语怎么说-奥巴马的就职演讲
2023年3月31日发(作者:福原美穂)
深度学习----实现⼀个博弈型的AI,从五⼦棋开始
好久没有写过博客了,多久,⼤概8年最近重新把写作这事⼉捡起来……最近在折腾AI,写个AI相关的给团队的⼩伙伴们看吧。
搞了这么多年的机器学习,从分类到聚类,从朴素贝叶斯到SVM,从神经⽹络到深度学习,各种神秘的项⽬⾥⽤了⽆数次,但是感觉⼲的各种事情离我们⽣活还是太远了。最近AlphaGo
Zero的发布,深度学习⼜⽕了⼀把,⼩伙伴们按捺不住内⼼的躁动,要搞⼀个游戏AI,好吧,那就从规则简单、⽼少皆宜的五⼦棋开始讲起。
好了,废话就说这么多,下⾯进⼊第⼀讲,实现⼀个五⼦棋。
⼩伙伴:此处省去吐槽⼀万字,说好的讲深度学习,怎么开始扯实现⼀个五⼦棋程序了,⼤哥你不按套路出牌啊……
我:⼯欲善其事必先利其器,要实现五⼦棋的AI,连棋都没有,A精选唐诗宋词50首 I个锤⼦!
⽼罗:什么事?
……
五⼦棋分为有禁⼿和⽆禁⼿,我们先实现⼀个普通版本的⽆禁⼿版本作为例⼦,因为这个不影响我们实现⼀个AI。补充说明⼀下,⽆禁⼿⿊棋必胜,经过⽐赛和各种研究,⼈们逐渐知道
了这个事实就开始想办法来限制⿊棋先⼿优势。于是出现了有禁⼿规则,规定⿊棋不能下三三,四四和长连。但随着⽐赛的结果的研究的继续进⾏,发现其实即使是对⿊棋有禁⼿限制,
还是不能阻⽌⿊棋开局必胜的事实,像直指开局中花⽉,⼭⽉,云⽉,溪⽉,寒星等,斜指开局中的名⽉,浦⽉,恒星,峡⽉,岚⽉都是⿊棋必胜。于是⽇本⼈继续提出了交换和换打的
思想,到了后来发展成了国际⽐赛中三⼿交换和五⼿⼆打规则,防⽌执⿊者下出必胜开局或者在第五⼿下出必胜打。所以结论是,在不正规的⽐赛规则或者⽆禁⼿情况下,⿊棋必胜是存
在的。
(1)五⼦棋下棋逻辑实现
这⾥⽤Python来实现,因为之后的机器学习库也是P国庆节放假 ython的,⽅便⼀点。
界⾯和逻辑要分开,解耦合,这个是⽏庸置疑的,并且之后还要训练AI,分离这是必须的。所以我们先来实现⼀个五⼦棋的逻辑。
我们先来考虑五⼦棋是⼀个15*15的棋盘,棋盘上的每⼀个交叉点(或格⼦)上⼀共会有3种状态:空⽩、⿊棋、⽩棋,所以先建个⽂件
做如下定义:
fromenumimportEnum
N=15
classChessboardState(Enum):
EMPTY=0
BLACK=1
WHITE=2
棋盘的状态,我们先⽤⼀个15*15的⼆维数组chessMap来表⽰,建⼀个类
currentI、currentJ、currentState分别表⽰当前这步着棋的坐标和颜⾊,再定义⼀个get和set函数,最基本的框架就出来了,代码如下:
fromenumimportEnum
fromconstsimport*
classGoBang(object):
def__init__(self):
self.__chessMap=[[orjinrange(N)]foriinrange(N)]
self.__currentI=-1
self.__currentJ=-1
self.__currentState=
defget_chessMap(self):
returnself.__chessMap
defget_chessboard_state(self,i,j):
returnself.__chessMap[i][j]
defset_chessboard_state(self,i,j,state):
self.__chessMap[i][j]=state
self.__currentI=i
self.__currentJ=j
self.__currentState=state
这样界⾯端可以调⽤get函数来获取各个格⼦的状态来决定是否绘制棋⼦,以及绘制什么样的棋⼦;每次下棋的时候呢,在对应的格⼦上,通过坐标来设置棋盘Map的状态。
所以最基本的展⽰和下棋,上⾯的逻辑就够了,接下来⼲什么呢,得考虑每次下棋之后,set了对应格⼦的状态,是不是需要判断当前有没有获胜。所以还需要再加两个函数来⼲这个事
情,思路就是从当前位置从东、南、西、北、东南、西南、西北、东北8个⽅向,4根轴,看是否有连续的⼤于5颗相同颜⾊的棋⼦出现。假设我们⽬前落⼦在棋盘正中,需要判断的位置
如下图所⽰的⽶字形。
那代码怎么写呢,最最笨的办法,按照字⾯意思来翻译咯,⽐如横轴,先看当前位置左边有多少颗连续同⾊的,再看右边有多少颗连续同⾊的,左边加右边,就是当前横轴上的连续数,
如果⼤于5,则胜利。
defhave_five(self,current_i,current_j):
#四个⽅向计数竖横左斜右斜
hcount=1
temp=
#H-左
forjinrange(current_j-1,-1,-1):#横向往左from(current_j-1)to0
temp=self.__chessMap[current_i][j]
iftemp==rtemp!=self.__currentState:
break
hcount=hcount+1#H-右
forjinrange(current_j+1,N):#横向往右from(current_j+1)toN
temp=self.__chessMap[current_i][j]
iftemp==rtemp!=self.__currentState:
break
hcount=hcount+1#H-结果
ifhcount>=5:
returnTrue
以此类推,再看竖轴、再看左斜、再看⼜斜,于是,have_five函数变成这样了:
defhave_five(self,current_i,current_j):
#四个⽅向计数竖横左斜右斜
hcount=1
vcount=1
lbhcount=1
rbhcount=1
temp=
#H-左
forjinrange(current_j-1,-1,-1):#横向往左from(current_j-1)to0
temp=self.__chessMap[current_i][j]
iftemp==rtemp!=self.__currentState:
break
hcount=hcount+1
#H-右
forjinrange(current_j+1,N):#横向往右from(current_j+1)toN
temp=self.__chessMap[current_i][j]
iftemp==rtemp!=self.__currentState:
break
hcount=hcount+1
#H-结果
ifhcount>=5:
returnTrue
#V-上
foriinrange(current_i-1,-1,-1):#from(current_i-1)to0
temp=self.__chessMap[i][current_j]
iftemp==rtemp!=self.__currentState:
break
vcount=vcount+1
#V-下
foriinrange(current_i+1,N):#from(current_i+1)toN
temp=self.__chessMap[i][current_j]
iftemp==rtemp!=self.__currentState:
break
vcount=vcount+1
#V-结果
ifvcount>=5:
returnTrue
#LB-上
fori,jinzip(range(current_i-1,-1,-1),range(current_j-1,-1,-1)):
temp=self.__chessMap[i][j]
iftemp==rtemp!=self.__currentState:
break
lbhcount=lbhcount+1
#LB-下
fori,jinzip(range(current_i+1,N),range(current_j+1,N)):
temp=self.__chessMap[i][j]
iftemp==rtemp!=self.__currentState:
break
lbhcount=lbhcount+1
#LB-结果
iflbhcount>=5:
returnTrue
#RB-上
fori,jinzip(range(current_i-1,-1,-1),range(current_j+1,N)):
temp=self.__chessMap[i][j]
iftemp==rtemp!=self.__currentState:
break
rbhcount=rbhcount+1
#RB-下
fori,jinzip(range(current_i+1,N),range(current_j-1,-1,-1)):
temp=self.__chessMap[i][j]
iftemp==rtemp!=self晓风残月的晓是什么意思 .__currentState:
break
rbhcount=rbhcount+1
#LB-结果
ifrbhcount>=5:
returnTrue
这样是不是就写完了,五⼦棋的逻辑全部实现~
NO,别⾼兴得太早,我想说,我好恶⼼,上⾯那个代码,简直丑爆了,再看⼀眼,重复的写了这么多for,这么多if,这么多重复的代码块,让我先去吐会⼉……
好了,想想办法怎么改,⾄少分了4根轴,是重复的对不对,然后每根轴分别从正负两个⽅向去统计,最后加起来,两个⽅向,也是重复的对不对。
于是我们能不能只写⼀个⽅向的代码,分别调2次,然后4根轴,分别再调4次,2*4=8,诗歌朗诵《相信未来》 ⼀共8⾏代码搞定试试。
因为有45和135这两根斜轴的存在,所以⽅向上应该分别从x和y两个轴来控制正负,于是可以这样,先写⼀个函数,按照⽅向来统计:
xdirection=0,ydirection=1表⽰从y轴正向数;
xdirection=0,ydirection=-1表⽰从y轴负向数;
xdirection=1,ydirection=1表⽰从45斜轴正向数;
……
不⼀⼀列举了,再加上边界条件的判断,于是有了以下函数:
defcount_on_direction(self,i,j,xdirection,ydirection,color):
count=0
forstepinrange(1,5):#除当前位置外,朝对应⽅向再看4步
ifxdirection!=0and(j+xdirection*step<0orj+xdirection*step>=N):
break
ifydirection!=0and(i+ydirection*step<0ori+ydirection*step>=N):
break
ifself.__chessMap[i+ydirection*step][j+xdirection*step]==color:
count+=1
else:
break
returncount
于是乎,前⾯的have_five稍微长的好看了⼀点,可以变成这样:
defhave_five(self,i,j,color):
#四个⽅向计数竖横左斜右斜
hcount=1
vcount=1
lbhcount=1
rbhcount=1
hcount+=_on_direction(i,j,-1,0,color)
hcount+=_on_描写月亮的绝美诗句 direction(i,j,1,0,color)
ifhcount>=5:
returnTrue
vcount+=_on_direction(i,j,0,-1,color)
vcount+=_on_direction(i,j,0,1,color)
ifvcount>=5:
returnTrue
lbhcount+=_on_direction(i,j,-1,1,color)
lbhcount+=_on_direction(i,j,1,-1,color)
iflbhcount>=5:
returnTrue
rbhcount+=_on_direction(i,j,-1,-1,color)
rbhcount+=_on_direction(i,j,1,1,color)
ifrbhcount>=5:
returnTrue
还是⼀⼤排重复的代码呀,我还是觉得它丑啊,我真的不是处⼥座,但是这个函数是真丑啊,能不能让它再帅⼀点,当然可以,4个重复块再收成⼀个函数,循环调4次,是不是可以,
好,就这么⼲,于是have_five就⼜漂亮了⼀点点:
defhave_five(self,i,j,color):
#四个⽅向计数竖横左斜右斜
directions=[[(-1,0),(1,0)],
[(0,-1),(0,1)],
[(-1,1),(1,-1)],
[(-1,-1),(1,1)]]
foraxisindirections:
axis_count=1
for(xdirection,ydirection)inaxis:
axis_count+=_on_direction(i,j,xdirection,ydirection,color)
ifaxis_count>=5:
returnTrue
returnFalse
嗯,感觉好多了,这下判断是否有5颗相同颜⾊棋⼦的逻辑也有了,再加⼀个函数来给界⾯层返回结果,逻辑部分的代码就差不多了:
defget_chess_result(self):
_five(self.__currentI,self.__currentJ,self.__currentState):
returnself.__currentState
else:
于是,五⼦棋逻辑代码就写完了,完整代码如下:
#coding:utf糠组词 -8
fromenumimportEnum
fromconstsimport*
classGoBang(object):
def__init__(self):
self.__chessMap=[[orjinrange(N)]foriinrange(N)]
self.__currentI=-1
self.__currentJ=-1
self.__currentState=
defget_chessMap(self):
returnself.__chessMap
defget_chessboard_state(self,i,j):
returnself.__chessMap[i][j]
defset_chessboard_state(self,i,j,state):
self.__chessMap[i][j]=state
self.__currentI=i
self.__currentJ=j
self.__currentState=state
defget_chess_result(self):
_five(self.__currentI,self.__currentJ,self.__currentState):
returnself.__currentState
else:
defcount_on_direction(self,i,j,xdirection,ydirection,color):
count=0
forstepinrange(1,5):#除当前位置外,朝对应⽅向再看4步
ifxdirection!=0and(j+xdirection*step<0orj+xdirection*step>=N):
break
ifydirection!=0and(i+ydirection*step<0ori+ydirection*step>=N):
break
ifself.__chessMap[i+ydirection*step][j+xdirection*step]==color:
count+=1
else:
break
returncount
defhave_five(self,i,j,color):
#四个⽅向计数竖横左斜右斜
directions=[[(-1,0),(1,0)],
[(0,-1),(0,1)],
[(-1,1),(1,-1)],
[(-1,-1),(1,1)]]
foraxisindirections:
axis_count=1
for(xdirection,ydirection)inaxis:
axis_count+=_on_direction(i,j,xdirection,ydirection,color)
ifaxis_count>=5:
returnTrue
returnFalse
背景⾳:⼤哥,憋了半天,就憋出这么不到60⾏代码?
我:代码不再多,实现则灵……
明天来给它加个render,前端界⾯就有了,就是⼀个简单的完整游戏了,⾄于AI,别急嘛。
好吧,就这样…
更多推荐
LBH是什么意思在线翻译读音例句
发布评论