「图形化编程」Micro:bit 井字棋游戏(一)

又要开始一个新的系列教程啦,这回我们来用 Micro:bit 做一个井字棋,提到井字棋,想必大家都不陌生,就是两个玩家轮流在一个井字型的 9 宫格里画 x 和 o,当某一方的棋子连成了一条线(横向,竖向和对角线),那么该方获胜,如果格子被填满也没有人成功连线,则平局。这次我们来学习如何用 micro:bit 实现一个井字棋小游戏。最终的实现效果详见 「预告」「图形化编程」Micro:bit 井字棋 小游戏

这节教程会讲解井字棋的基本原理,并实现井字棋的基础部分,包括以下功能

  1. 光标移动
  2. 用不同的 led 状态表示不同玩家的棋子
  3. A B 玩家交替落子

游戏规则

井字棋的游戏规则是,A B 两个玩家轮流在 9 个格子里放入 o 或者 x,当有一方的棋子连成一线,横向,纵向或对角线,则该方获胜,不能把棋子下在已经有棋子的位置上,因为在一个井字形状围成的棋盘里,所以叫井字棋
win

基本原理

基本原理分为 3 部分,

  • 坐标
  • 落子
  • 判断输赢

其中判断输赢的逻辑稍微有一些复杂,我们放在后面的教程里单独讲,先来说说 坐标 和 落子

坐标

因为井字棋一共有 9 个格子,因此对应到 led 点阵上也是 9 个 led 灯,但是 led 点阵一共有 5*5=25 个 led,所以我们要空出 16 个,可以下棋的位置坐标已经标记在下图里,请记好这张坐标图,它对我们判断输赢很重要

zuobiao

那么如何让光标只在这 9 个格子之间移动呢?如果你仔细观察,就会发现所有位置的 x 和 y 坐标都是偶数,这样我们就可以把开始点设置在其中一个位置上,然后让这个点的 x 和 y 坐标进行 +2 或着 -2,就可以保证它们只在这几个位置之间移动,而不会跑到类似 (1,3) 这样的位置上去啦

举个例子,假设初始光标在 (2,2) 向上移动 给 y-2 变成了 (2,0),再向右移动 给 x+2 变成了 (4,0),这样就能保证光标只能在这 9 个位置之间来回移动了

落子

落子的条件是当前位置上没有棋子,那如何判断当前位置有没有棋子呢?我们需要一个数组来保存当前已经下的棋子,然后遍历这个数组,看存不存在与当前光标位置一样的棋子,如果有,就代表当前光标位置处已经有棋子了,不能再落子了,如果没有,就代表可以落子,然后把当前位置加入数组,另外,我们需要一个变量来表明当前是哪个玩家在下棋

亮度与闪烁

由于 led 点阵是单色的,无法通过颜色来区分 A 方和 B 方的棋子,因此这里有个变通的办法,就是利用常亮闪烁来区分,同时为了保护眼睛,我们会把 led 灯的亮度调暗一些,因此将会接触到两个新模块 亮度 与 闪烁,用来区分 光标,A 玩家的棋子 和 B 玩家的棋子

亮度与闪烁的设置隐藏的有些深,位于 游戏 分类下的 sprite 设置 x 为 0 模块,点开那个 x 的下拉菜单,就能看到 亮度 和 闪烁 啦

liangduyushanshuo

下面是不同的亮度与闪烁效果
shanshuodaima

shanshuo

下面我们来说说如何实现,先打开这个网站,新建一个项目

初始化

我们需要做一些初始化工作,上面说了,我们会利用不同的亮度和闪烁来区别光标,A 方和 B 方的棋子

  • A 方棋子常亮
  • B 方棋子慢闪
  • 光标快闪

当开机时

  1. 创建一个变量 Axiaqi 并设置为 true,代表当前是否是 A 方在下棋,如果为 true,代表是 A 在下,如果为 false,代表 B 在下棋
  2. 创建一个精灵,并赋值给一个叫做 guangbiao 的变量,用来代表光标,并把他的亮度和闪烁设置为 100
  3. 创建一个空数组 qiziliebiao 用于保存已经下到棋盘的棋子
  4. 创建并设置变量 liangdu 为 50,为了保护我们的眼睛
  5. 创建并设置变量 Bshanshuo 为 500,让 B 棋子的闪烁比光标慢

kaiji1

重力控制光标移动

重力控制我们已经在前面的教程里多次接触过了,可以看看这篇教程这里就不细讲了,就是控制精灵 guangbiao 根据加速度的方向来增加或减少 x 或 y 坐标的值,但是要注意的是,这次是每次增加或减少 2,最后的 暂停 800ms 可以改成你喜欢的值

wuxianxunhuan1

落子

落子的过程就是先判断当前是哪一方的玩家下棋,然后判断当前光标位置有没有棋子,如果有就显示一个 x,如果没有就在当前位置创建一个精灵,并把它加到用于保存当前棋子的数组里,今天我们先不判断是否能够把棋下在当前光标位置,只实现 A B 方轮流下棋的过程,下节教程我们再来判断能否在当前位置下棋
落子分为两部分,一部分响应 按钮 A 和 按钮 B 的事件,另一部分处理 下棋逻辑

下棋函数

  1. 创建一个 函数,命名为 luozi
  2. 用 变量 guangbiao 的 x 和 y 坐标创建一个 精灵,并赋值给 变量 dangqianbu
  3. 把新创建的精灵 dangqianbu 添加到数组 qililiebiao 里
  4. 判断如果 Axiaqi 为 true,代表当前这一步 是 A 玩家走的,把 Axiaqi 设置为 false,并把精灵 dangqianbu 的亮度 设置为 liangdu 的值
  5. 否则 Axiaqi 为 false,代表当前这一步是 B 玩家走的,要把 Axiaqi 置为 true,代表下一步该 A 走了,因为 B 的棋子是闪烁的,因此把 dangqianbu 闪烁设置为 Bshanshuo 的值
  6. 最后把 guangbiao 的 x 和 y 都改成 2,让它重新回到屏幕中间

luozi1

按钮事件

按钮事件很简单,只要根据 Axiaqi 进行判定就好了,如果是按钮 A 按下了,那判断 Axiaqi 的值是不是 true,如果是,那就代表确实该 A 走棋,调用 luozi 函数来保存当前走的棋,否则显示箭头指向 B
按钮 B 的事件跟按钮 A 的逻辑正好相反

anniushijian

实现效果

最终的实现效果见下图

jingziqi1

可以看到 A B 轮流下棋,如果一方连续 按下相同的按钮,则显示箭头指向对方按钮,提示该对方下棋,A 的棋子常亮,每走完一步光标回到 屏幕中间,B 的棋子闪烁,频率要比光标闪烁得慢

完整代码

wanzhengdaima1

Hex 文件

这篇教程的 Hex 文件可以在 这个地址 下载

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.