当前位置:   article > 正文

python-五子棋-AI_python五子棋ai

python五子棋ai

降智警告:本人为编程新手,遵守面向CSDN编程原则,代码架构具有个人特色,仅供参考

 

前言:课程期末项目写了个黑白棋,所以放假写个五子棋,作为今年的总结

(该五子棋仅涉及最基础的规则,轮留下,连五赢)

 

一.最终效果

功能:规定玩家先下,结束时展示结果。restart按钮会变色,鼠标在按钮上时颜色变深。按下restart按钮可以重新开局。

 

二.AI实现

1.思路

①棋局

使用二维列表表示棋盘,0表示空位,1表示玩家棋子(黑),2表示电脑棋子(白)

 

②局面评估

为了减少计算量,我将电脑当前的可下位置限制为,非空位置的八邻域中的空位。然后对每一个可下位置进行评估。

我们需要为每一个当前可下位置进行评估得到一个分数,然后取分数最高的位置作为本次的下子位置。

在评估时,我们需要考虑该位置对于本方的重要性,同时也要考虑该位置对敌方的重要性,所以我们需要将两个评估所得分数相加作为该位置的最终分数。

 

③评估方法

首先对于每一个需要评估的位置,先将电脑棋子放到该位置,然后分别取该位置的横,竖,左斜,右斜四个方向上的线上的所有位置作为四条棋线,对每个位置的四条棋线进行评估。然后反转棋盘,将电脑的棋子换为玩家棋子,玩家棋子换为电脑棋子,再对该位置进行评估。两个评估分数相加即为该位置的最终分数。

五子棋中有许多棋型,如连五,活四,冲四,活三等,为每一个棋型设置一个分数,每个位置的四条棋线中存在的所有棋型的分数相加,得到该位置的一方评估分数。

参考资料:棋型参考, 棋型评分参考

 

2.代码实现

这里仅给出根据当前棋局给出最佳下子位置的实现,项目完整代码在我的github

①获取当前棋局所有可下位置(限制条件下) 

  1. def get_charge_pos(board) :
  2. #八邻域
  3. way = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
  4. ret = []
  5. for i in range(15) :
  6. for j in range(15) :
  7. #当前位置不为空位
  8. if board[i][j] != 0 :
  9. #搜索八邻域
  10. for w in way :
  11. pos = (i + w[0], j + w[1])
  12. if pos[0] not in range(15) or pos[1] not in range(15) :
  13. continue
  14. if (board[pos[0]][pos[1]] == 0) and (pos not in ret) :
  15. ret.append(pos)
  16. return ret

②获取当前位置棋线

(将一条棋线上的位置整理为一个列表,将列表转化为字符串并进行处理,最终只剩下包含0,1,2三个数字的字符串,返回包含四条棋线代表的字符串的列表)

  1. def get_score(pos, board) :
  2. #获取棋盘副本,在当前位置放入棋子
  3. ori = copy.deepcopy(board)
  4. ori[pos[0]][pos[1]] = 2
  5. #横,竖
  6. h = str(ori[pos[0]])[1:-1].replace(',', '').replace(' ', '')
  7. s = str([ori[i][pos[1]] for i in range(15)])[1:-1].replace(',', '').replace(' ', '')
  8. #左斜
  9. lx = str([ori[i][i - pos[0] + pos[1]] for i in range(15) if (i - pos[0] + pos[1]) in range(15)])[1:-1].replace(',', '').replace(' ', '')
  10. #右斜
  11. rx = str([ori[i][pos[0] + pos[1] - i] for i in range(15) if (pos[0] + pos[1] - i) in range(15)])[1:-1].replace(',', '').replace(' ', '')
  12. return get_line_score([h, s, lx, rx])

 

③棋线评分

(由于棋型过多,判断比较繁琐,截取部分代码作为示例)

注意:由于棋线上对于棋型是单向查找的,所以对于不对称的棋型要反转棋型再次查找

④主函数

实现对每个可下位置进行两次评分得到最终分数后,返回分数最高的位置

  1. def get_pos(board) :
  2. pos = get_charge_pos(board)
  3. get = (-1, -1)
  4. score = -float("inf")
  5. for p in pos :
  6. #反转棋盘
  7. o_board = opp_board(board)
  8. s = get_score(p, board) + get_score(p, o_board)
  9. if s > score :
  10. get = p
  11. score = s
  12. return get

 

三.总结

这个项目的界面实现就不放代码了,有兴趣的可以看一下(项目代码

使用pygame来构造界面,调用了棋盘,黑白棋子,restart按钮共五张图片,如果修改图片的话需要更改显示的具体参数

因为界面用到好几张图,如果转化为py文件一起打包的话,最后的exe会很大,所以就放在一个文件夹里直接调用了,顺便把程序框图标的ico也放进去了

最终的效果还是不错的,AI的胜率挺高的,也用到了今年所学的东西,也是今年的最后一个项目了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/612591
推荐阅读
相关标签
  

闽ICP备14008679号