minimax算法和Alpha-Beta pruning实现英式跳棋

算法作业喜加一。这alpha-Beta剪枝也太绕了
看了Tech With Tim的教程……真的好厉害噢
这个跳棋和中国的三角式还不太一样,棋盘是8*8的
minimax算法和Alpha-Beta pruning实现英式跳棋_第1张图片

大概就是两边各执一方,然后正常跳,跳过去的时候会把对手棋子吃掉,跳到对面最后一列就会变成KING,然后可以往回反跳。
最后就是看谁剩下的棋子多谁赢。

所以

算法

他的总和就是比如图上。
白色棋子数减去红色棋子数。
白方希望这个数越大,而红方希望这个数越小。
对于每个棋子,
所有的可能性行为就是一棵搜索树。
所以就成了经典的的最大最小博弈算法。

#伪代码:
function minimax(node, depth, maximizingPlayer)  
if depth ==0 or node is a terminal node then  
return static evaluation of node  
  
if MaximizingPlayer then      // for Maximizer Player  
maxEva= -infinity            
 for each child of node do  
 eva= minimax(child, depth-1, false)  
maxEva= max(maxEva,eva)        //gives Maximum of the values  
return maxEva  
  
else                         // for Minimizer player  
 minEva= +infinity   
 for each child of node do  
 eva= minimax(child, depth-1, true)  
 minEva= min(minEva, eva)         //gives minimum of the values  
 return minEva  

minimax 算法的主要缺点是对于复杂的游戏,比如国际象棋、围棋等,它变得非常慢。这种类型的游戏具有数量庞大的分支node,但是可以通过alpha-beta 剪枝算法来改进。

Alpha-Beta剪枝用于裁剪所有不会真正影响最终决策但使算法变慢的节点,以提高运算速度,可以在不检查搜索树的每个节点的情况下计算正确的极小极大决策,涉及到两个阈值参数 Alpha 和 bet。

Alpha:到目前为止,在 Maximizer 路径上的任何一点找到的最佳(最高值)选择。alpha 的初始值为-∞。
Beta:在 Minimizer 路径上的任何一点找到的最佳(最低值)选择。beta 的初始值为+∞。
当一个 Min 节点的 β值≤任何一个父节点的α值时 ,剪掉该节点的所有子节点(下一个节点对应Min就更新β值)
当一个 Max 节点的 α值≥任何一个父节点的β值时 ,剪掉该节点的所有子节点(下一个节点对应Max就更新 α值)
每一层都需要判断是否α>=β ,如果是,就终止遍历进行pruning

总结一下关键点就是:
max对应α
min对应β
α>=β就剪枝

#伪代码
function minimax(node, depth, alpha, beta, maximizingPlayer) is  
if depth ==0 or node is a terminal node then  
return static evaluation of node  
  
if MaximizingPlayer then
for Maximizer Player  
   maxEva= -infinity            
   for each child of node do  
   eva= minimax(child, depth-1, alpha, beta, False)  
  maxEva= max(maxEva, eva)   
  alpha= max(alpha, maxEva)      
   if beta<=alpha  
 break  
 return maxEva  
    
else
for Minimizer player  
   minEva= +infinity   
   for each child of node do  
   eva= minimax(child, depth-1, alpha, beta, true)  
   minEva= min(minEva, eva)   
   beta= min(beta, eva)  
    if beta<=alpha  
  break          
 return minEva  

虽然很绕,但是youtube随便搜了个教学视频就懂了
但是蛮怪的,这个alpha beta
到底是哪个神仙发明的算法
好绕噢

思路

构建while loop循环游戏
棋子类
棋盘类,实例化每个棋子

如果棋子剩余数量为0结束游戏

棋子:

属性有行,列。(x,y)颜色,是否为王
[downside_red,downside_blue,upside_red,upside_blue] 0 is false

计算位置:是对应的行列+格子中心
x = SQUARE_SIZE * self.col + SQUARE_SIZE // 2
y = SQUARE_SIZE * self.row + SQUARE_SIZE // 2
然后定义获取是否是KING,是的话在中心位置把王冠图叠上去。
接着移动棋子的方法也放在这里,把棋子行列更新一下后计算新的位置
最后用 __repr__方法,返回棋子的颜色。

界面主体:

属性有双方棋子数,困难度

参数ROW和COL都是8
每个格子大小就是设置的页面大小整除格子长宽

#一个隔一个涂色
for col in range(row % 2, COLS, 2)

pygame.draw.rect
pygame.draw.rect(Surface, color, Rect, width=0): return Rect
在Surface上绘制矩形,第二个参数是线条(或填充)的颜色,第三个参数Rect的形式是((x, y), (width, height)),表示的是所绘制矩形的区域,其中第一个元组(x, y)表示的是该矩形左上角的坐标,第二个元组 (width, height)表示的是矩形的宽度和高度。width表示线条的粗细,单位为像素;默认值为0,表示填充矩形内部。

(row*SQUARE_SIZE, col *SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE)
元组区域就是(对应的行,对应的列,格子的宽,格子的高)

在移动方法里
把新位置和棋子的位置进行交换,如果是国王行,对应国王+1且调用棋子里的国王方法。

 self.board[piece.row][piece.col], self.board[row][col] = self.board[row][col], self.board[piece.row][piece.col]

捕获方法就是把他对应的位置变0,棋子数量-1,捕获的对象如果是国王,则直接获胜触发弑君

所有绘画都在这里,棋盘,棋子,有效的移动

有效移动方法,启发函数,获取所有棋子,获取界面棋子状态(有多少红蓝在上半,多少在下半)

如何有效移动:

创建一个move的dictionary且返回所有可能性
{(目标位置x,y),[是否有能吃的颜色,返回颜色]}
如果斜对角有棋子且颜色相同,break
有棋子且颜色不同,吃掉,并把吃掉的位置保存,
没有棋子,遍历移动
如果吃完后没有下一步的位置了,break(比如边界)
吃完后有棋子,重复颜色判断

最终返回所有的可能性
这段其实是抄的实在有点绕不出来了
但是抄完感觉懂了(。)

游戏主体:

在game类里实例board
属性有pygame界面,有效移动dic{},轮次
select piece funcation选择棋子
update function 更新游戏状态
select function对应回合选择棋子,用到board里validmove
其他杂七杂八的还有改变轮次,和基于board的继承实现

做了个劣质ui
minimax算法和Alpha-Beta pruning实现英式跳棋_第2张图片

AI:

deepcocy复制棋盘,ai改一次复制一次,
棋子,ai的移动,ai吃的棋子,游戏的状态

你可能感兴趣的:(学习笔记,算法)