本文代码基于 python3.6 和 pygame1.9.4。

五子棋比起我之前写的几款游戏来说,难度提高了不少。如果是人与人对战,那么,电脑只需要判断是否赢了就可以。如果是人机对战,那你还得让电脑知道怎么下。

我们先从简单的问题来看。

开端

画棋盘

首先肯定是要画出棋盘来,用 pygame 画出一个 19 × 19 或 15 × 15 的棋盘并不是什么难事,这在之前的文章中已经多次用到,就不赘述了。

画棋子

需要说一下的是画棋子,因为没找到什么合适的棋子图片,所以只要自己来画棋子。

我们用 pygame.draw.circle 画出来的圆形是这样的:

锯齿状十分明显,pygame.draw 中有画抗锯齿直线的函数 aaline,但是并没有 aacircle 这样的函数来画一个抗锯齿的圆。

这里就需要用到 pygame.gfxdraw 啦。pygame.gfxdraw 目前还仅是实验版本,这意味着这个 api 可能会在以后的 pygame 版本中发生变化或消失。

要绘制抗锯齿和填充形状,请首先使用函数的aa *版本,然后使用填充版本。例如:

col = (255, 0, 0)

surf.fill((255, 255, 255))

pygame.gfxdraw.aacircle(surf, x, y, 30, col)

pygame.gfxdraw.filled_circle(surf, x, y, 30, col)

我们用这个方法在棋盘上画一个棋子试试看。

可以看到效果已明显改善。

落子

落子需要判断鼠标事件,当鼠标左键点击,获取鼠标点击的位置,然后根据棋盘的位置,计算出棋子落在棋盘的位置。

while true:

for event in pygame.event.get():

if event.type == quit:

sys.exit()

elif event.type == mousebuttondown:

pressed_array = pygame.mouse.get_pressed()

if pressed_array[0]:  # 鼠标左键点击

mouse_pos = pygame.mouse.get_pos()

click_point = _get_clickpoint(mouse_pos)

胜利判定

当一子落下,如何判定是否胜利?

可以肯定的是,当某一子落下的时候,如果出现了 5 连,那么落下的这颗子必定在这条 5 连线上。那么这个问题就可以简化了,我们无需全盘扫描,只需要在落子位置上横竖撇捺扫描一下,判断是否出现 5 连即可。

我们定义一个棋盘类,类中实例化一个 19 × 19 的二维数组,初始值皆为 0,表示空,用 1 表示黑子,2 表示白子。这个类对外提供一个落子方法 drop,接收参数落子方和落子坐标,如果落子后胜利,则返回胜利者,否则返回 none。

chessman = namedtuple('chessman', 'name value color')

point = namedtuple('point', 'x y')

black_chessman = chessman('黑子', 1, (45, 45, 45))

white_chessman = chessman('白子', 2, (219, 219, 219))

offset = [(1, 0), (0, 1), (1, 1), (1, -1)]

class checkerboard:

def __init__(self, line_points):

self._line_points = line_points

self._checkerboard = [[0] * line_points for _ in range(line_points)]

def _get_checkerboard(self):

return self._checkerboard

checkerboard = property(_get_checkerboard)

# 判断是否可落子

def can_drop(self, point):

return self._checkerboard[point.y][point.x] == 0

def drop(self, chessman, point):

"""

落子

:param chessman: 黑子/白子

:param point:落子位置

:return:若该子落下之后即可获胜,则返回获胜方,否则返回 none

"""

print(f'{chessman.name} ({point.x}, {point.y})')

self._checkerboard[point.y][point.x] = chessman.value

if self._win(point):

print(f'{chessman.name}获胜')

return chessman

# 判断是否赢了

def _win(self, point):

cur_value = self._checkerboard[point.y][point.x]

for os in offset:

if self._get_count_on_direction(point, cur_value, os[0], os[1]):

return true

def _get_count_on_direction(self, point, value, x_offset, y_offset):

count = 1

for step in range(1, 5):

x = point.x + step * x_offset

y = point.y + step * y_offset

if 0 <= x

count += 1

else:

break

for step in range(1, 5):

x = point.x - step * x_offset

y = point.y - step * y_offset

if 0 <= x

count += 1

else:

break

return count >= 5

这里我定义了一个偏移量,我们一共要计算横竖撇捺 4 条线,任意一条线出现 5 连就算获胜。计算方法实际上是一样的,只是方向不同,所以定义一个偏移量数组,不同的偏移量表示不同的方向,这样就可以利用循环来实现了,节省了很多代码。

电脑落子

这就是全篇的重头戏了,要怎么教电脑下五子棋。

首先声明,我用的是相对传统的方式,不是深度学习。

五子棋就是要实现 5 连,所以,一开始,我的想法是:将所有连线保存在一个数组中,落子的时候选择最长的连线落子。但这样有个问题解决不掉,如何让电脑识别“三三”呢?

后来网上看到篇文章,使用的方法是:遍历棋盘上的空位,计算每一个位置其横竖撇捺 8 个方向上是否有己方的子,有一个就加 10 分,最后选得分最高的位置落子。

这样不太严谨,写出来的电脑估计水平很菜,但是这个思路却是对的,落子就是要找到最值得的地方,那么我们干脆对每一个可落子的地方来做一个评估,选出最优解。

这里我们需要了解一下五子棋的几种基本棋形:连五,活四,冲四,活三,眠三,活二,眠二。

连五

顾名思义,五颗同色棋子连在一起,赢了。

活四

四颗同色棋子连在一起,并且左右两边都没有对方棋子阻挡,有两个连五点。

冲四

四颗同色棋子连在一起,并且一边有对方棋子阻挡,或者四颗棋子不是连的,当中有个空挡,这时只有一个连五点。

活三、跳活三

活三:三颗同色棋子连在一起。

python俄罗斯方块代码turtle_Python:游戏:300行代码实现俄罗斯方块相关推荐

  1. python编写游戏300行代码_300行代码实现Python游戏:俄罗斯方块

    本文代码基于 python3.6 和 pygame1.9.4. 俄罗斯方块是儿时最经典的游戏之一,刚开始接触 pygame 的时候就想写一个俄罗斯方块.但是想到旋转,停靠,消除等操作,感觉好像很难啊, ...

  2. 入门python,看完这个300行代码的例子,足矣~

    我梦想有一天,看遍了整个世界后,栖居在一个小城,与世无争 出自---------沃自己 前言 学习python有一段时间了,整个学习过程不算系统,也没有任何路线.最初零零散散的从慕课堂中看了些pyth ...

  3. python编程小游戏代码-Python小游戏之300行代码实现俄罗斯方块

    前言 本文代码基于 python3.6 和 pygame1.9.4. 俄罗斯方块是儿时最经典的游戏之一,刚开始接触 pygame 的时候就想写一个俄罗斯方块.但是想到旋转,停靠,消除等操作,感觉好像很 ...

  4. python小游戏源码-Python小游戏之300行代码实现俄罗斯方块

    Python小游戏之300行代码实现俄罗斯方块 来源:中文源码网 浏览: 次 日期:2019年11月5日 [下载文档: Python小游戏之300行代码实现俄罗斯方块.txt ] (友情提示:右键点上 ...

  5. Python 游戏:300行代码实现俄罗斯方块

    本文代码基于 python 3.6 和 pygame1.9.4. 俄罗斯方块是儿时最经典的游戏之一,刚开始接触 pygame 的时候就想写一个俄罗斯方块.但是想到旋转,停靠,消除等操作,感觉好像很难啊 ...

  6. python编写小游戏代码_Python小游戏之300行代码实现俄罗斯方块

    Python小游戏之300行代码实现俄罗斯方块 来源:中文源码网 浏览: 次 日期:2019年11月5日 [下载文档: Python小游戏之300行代码实现俄罗斯方块.txt ] (友情提示:右键点上 ...

  7. python小游戏代码大全-Python小游戏之300行代码实现俄罗斯方块

    前言 本文代码基于 python3.6 和 pygame1.9.4. 俄罗斯方块是儿时最经典的游戏之一,刚开始接触 pygame 的时候就想写一个俄罗斯方块.但是想到旋转,停靠,消除等操作,感觉好像很 ...

  8. python小技巧:300行代码实现俄罗斯方块

    @本文来源于公众号:csdn2299,喜欢可以关注公众号 程序员学府 文章目录 前言 外形 方块 停靠 前言 本文代码基于 python3.6 和 pygame1.9.4. 俄罗斯方块是儿时最经典的游 ...

  9. python300行代码_Python:游戏:300行代码实现俄罗斯方块

    本文代码基于 python3.6 和 pygame1.9.4.python 俄罗斯方块是儿时最经典的游戏之一,刚开始接触 pygame 的时候就想写一个俄罗斯方块.可是想到旋转,停靠,消除等操做,感受 ...

  10. 三百行python代码的项目_使用300行代码创建一个分布式系统

    使用 300 行代码创建一个分布式系统 构建一个分布式系统是很困难的. 它需要可扩展性. 容错性. 高可用性. 一致性. 可伸缩以及高效.为了达到这些目的,分布式系统需要很多复杂的组件以一 种 复杂的 ...

最新文章

  1. (超贴心)Centos7安装2.5G网卡驱动(Realtek 3000)
  2. thinkphp5.0 insert添加数据
  3. android照片备份软件下载,照片备份云相册app下载-照片备份云相册下载V1.9安卓版-西西软件下载...
  4. 被遮挡的绝对定位 z-index
  5. php语言冒泡法,PHP实现冒泡排序算法的案例
  6. 理解 JavaScript 闭包{转载}
  7. Sentinel服务熔断OpenFeign_削峰填谷_流量控制_速率控制_服务熔断_服务降级---微服务升级_SpringCloud Alibaba工作笔记0054
  8. Advanced+Apple+Debugging(2)
  9. oralce 存储过程、函数和触发器
  10. Linux常用命令——cd
  11. AM3352 bootloader引导程序开发
  12. 树莓派 Linux VS code 远程断点调试 .net 6.0 保姆级教程
  13. 吴恩达深度学习课程笔记(二):改善深层神经网络
  14. php eot,php中理解print的EOT分界符
  15. python函数ppt_如何用 Python 让你的PPT数据动起来
  16. gitee 上删除远程仓库
  17. 算法细节系列(3):梯度下降法,牛顿法,拟牛顿法
  18. oracle11导出导入dmp详解
  19. GPS授时服务器(时间同步服务器)在机场网络系统中应用
  20. 基于脑机接口的人脑控制机械手臂

热门文章

  1. jquery插件(二):Infinite Scroll–无限分页
  2. oracle全文搜索
  3. SpringBoot 分布式系统简单了解
  4. 如何预防网站被挂黑链?
  5. 基于51单片机十字路口红绿灯交通灯+紧急模式
  6. 大华sdk转springboot项目 (刷卡、刷人脸、刷二维码、刷身份证)
  7. 前端每日实战:161# 视频演示如何用纯 CSS 创作一张纪念卓别林的卡片(没有笑声的一天就是被荒废的一天)...
  8. 吐血整理50家企业真实大数据面试题!!学长实测,真实面试!!快收藏!
  9. 转:免费电子书籍下载站点
  10. 纯小白入门Linux基础