第11届蓝桥杯青少年组省赛原定于2020年3月7日举行,因疫情延期到2020年6月21日进行,形式为在线考试。Scratch分为初级组和中级组,其中初级组面向7~10岁孩子,中级组面向11~14岁孩子。
对对碰,本题是第11届蓝桥杯Scratch省赛真题编程第6题,是中级组最后一题,题目要求考生编程创作一个简易的对对碰游戏,还可以统计每一局的时间,形成成绩单,并对成绩单进行排序。
先来看看题目的要求吧。
一.题目说明
编程实现:
对对碰
两两相同的一共四张扣下的纸牌,每次先后翻开两张。如果两张一样就消失,如果两张不一样就重新扣下。当舞台上所有纸牌都消失,就过关了。
具体要求:
1). 创建四个纸牌角色,每张纸牌包含两个造型(正面和背面),其中两张牌面为小猫,另外两张牌面为小狗,牌的背面图案都一样;
2). 当绿旗被点击,四张纸牌以牌面朝下的状态,以随机顺序出现在如图所示的四个位置(不能重叠),参考坐标:(-100,100),、(50,100)、(-100,-50)、(50,-50);
3). 任意选择一张纸牌,点击可以翻开这张纸牌, 每当翻开两张纸牌时就要判断这两张纸牌是否一样。如果一样,则这两张纸牌消失掉。如果不一样,则两张纸牌重新扣回,等待下一次翻牌;
4). 当舞台上的四张牌全部消除,则游戏成功。小猫角色出现在舞台中心位置,说出从开始出现纸牌到纸牌全部消除所用的游戏时间,持续2秒。并且将本次游戏时间加入列表“成绩单”的最后一项,此时列表“成绩单”还要显示在舞台上;
5). 紧接着,小猫询问“是否排序?”,如果输入“是”,那么就以从小到大的顺序,将列表中的数据进行排序,程序结束;
6). 再次点击绿旗,还可以进行下一轮游戏。注意:成绩单的数据要保留不要删除。
二.作品效果
在编程之前,先来看看作品的完整效果吧:
三.思路分析
本作品包含5个角色,分别是小猫和4张纸牌,如图所示:
题目其中纸牌1和纸牌2角色的牌面都是小猫,纸牌3和纸牌4角色的牌面是小狗。
本作品功能较多,大致可以分成如下几个模块:
- 随机摆放纸牌
- 翻牌配对
- 记录成绩
- 成绩单排序
除了记录成绩比较简单之外,另外的3个模块都有一定的难度。
四.编程实现
根据上面的思路分析,我们分4步来编写程序。
1). 随机摆放纸牌
每一次点击绿旗时,四张牌都是随机摆放的,我们可以使用数字1、2、3、4来表示他们的排列顺序。比如2、3、4、1就表示纸牌1放在第二个位置,纸牌2放在第三个位置,纸牌3放在第四个位置,纸牌4放在第一个位置。
4个位置是固定的,变化的是数字组合,如何得到一个变化的数字排列呢?很显然,列表是一个不错的选择。
创建一个列表,将其命名为”纸牌顺序“,点击绿旗时,清空列表,然后将数字1、2、3、4随机插入到列表中,在小猫角色中,编写代码如下:
代码也比较好理解,这里使用了”在列表的第x项前插入“指令,插入数字1的时候,只有一个位置,插入数字2的时候,有两个位置可选,插入数字3的时候,有3个位置可选,插入数字4的时候,则有4个位置可选,这样就可以得到一个随机顺序的列表,如图:
生成随机列表后,就可以摆放纸牌了,所以这里给纸牌角色发送了”洗牌“的广播消息,当纸牌角色接收到广播后,就可以根据列表数据来设置角色位置了,以纸牌1为例,编写代码如下:
其它3张纸牌角色的代码基本相同,纸牌2对应的是列表中的第2项,纸牌3对应的是列表的第3项,纸牌4对应的是列表的第4项。
2). 翻牌配对
纸牌摆好之后,接下来就是翻牌配对了,需要注意这里的逻辑,默认情况下,4张牌都是扣上的,背面朝上。当点击某张纸牌时,此时只翻开一张,无需比较,当再翻开另外一张牌时,才需要进行比较。
因此,这里需要创建一个变量,用来表示当前翻开的是第几张牌,并将其初始化值设为0,这个工作在列表初始化时已经完成了。每次点击纸牌时,将该变量加1,如果变量为2,就需要比较是否配对,然后再将变量重置为0。
如果当前翻开的是第2张牌,自己的牌面很容易获取,那如何获取已翻开纸牌的牌面呢?还是需要借助变量,再创建一个变量”已翻开牌面“,用来记录已翻开纸牌的牌面。
如果两张已翻开的牌面相等,纸牌消失,将纸牌隐藏起来即可,如果牌面不相等,则纸牌又翻回去。这两个操作,都需要发送相应的广播消息给第一张已翻开的纸牌。
以纸牌1角色为例,编写代码如下:
当前角色是纸牌1,它的牌面是小猫,只有牌面为小猫的纸牌才能和它配对,所以,配对成功的时候,发送的广播消息为”小猫消失“,是专门针对牌面为小猫的角色的。同理,配对失败的时候,发送的广播消息是”小狗翻牌“,是专门针对牌面为小狗的角色的。
当小猫角色接收到”小猫消失“广播后,隐藏自己即可,代码如下:
当小狗角色接收到”小狗翻牌“广播后,将纸牌换成背面造型即可,如图:
在翻牌的过程中,如果连续两次点击同一张牌,它也会配对成功并消失,这显然是不对的,怎么解决这个小bug呢?
常见的方法就是使用一个私有变量,也就是这里的”_可点击否“变量,默认为1,表示可点击,一旦点击之后,马上设置为0,表示不可点击。当两张纸牌比较完毕,牌翻回去了,再次将变量设置1,表示可以继续点击。
为了记录配对数量,这里还使用了变量“配对数”,初始值为0,当纸牌配对成功消除时,配对数加1。
纸牌2、纸牌3和纸牌4三个角色的代码和纸牌1基本相同,这里就不再列出了。
3). 记录成绩
每次游戏成功时,需要记录当前的时间,Scratch专门提供了一个计时器用于计时。在游戏开始时,也就是点击绿旗时,先将计时器清零,游戏结束时,将计时器的值保存起来即可。
要保存每一局游戏的成绩,我们可以创建一个列表“成绩单”,并且不需要初始化,当游戏结束时,将本局的时间插入到列表中即可,在小猫角色中编写代码如下:
每一次游戏过程中是不显示列表的,只有游戏结束后才显示列表,所以这里增加了隐藏列表和显示列表的指令。
在说出本局游戏花费的时间之后,会询问玩家是否需要对成绩单进行排序,如果玩家输入“是”,则需要排序。
4). 成绩单排序
排序是编程中最基本的算法,常见的排序算法有冒泡排序、选择排序、插入排序、快速排序和归并排序等。
在Scratch蓝桥杯中曾多次出现排序问题,比如第12届蓝桥杯Scratch省赛2真题第5题 《考试成绩系统》,第13届蓝桥杯Scratch省赛真题 第5题《统计字符串》。关于具体的原理和排序可以参考这两篇教程。
本题依然使用最简单的选择排序,在小猫角色中编写代码如下:
五.总结与思考
本题难度较大,积木块数量较多,大概在270个左右,涉及到的知识点主要包括:
- 列表的操作,包括插入、获取和删除等操作,尤其是随机插入数据;
- 事件广播机制;
- 变量的使用,包括全局变量和私有变量;
- Scratch问答模块;
- 计时器的使用;
- 条件指令的多层嵌套;
- 选择排序算法的原理及实现。
作为省赛的最后一题,本题难度较大,主要包括两个方面,一是翻牌游戏的逻辑实现,二是排序算法的原理和实现。翻牌游戏的玩法比较简单,但是要使用编程来实现,需要借助多个变量来记录和保存相关信息,变量一多,逻辑就变得复杂了,还容易出现各种小bug,需要多加思考,多测试。
本作品的对对碰游戏只使用了4张牌,在真实的对对碰游戏中,一般都是8张牌以上,比如8张牌、12张牌、16张牌等。一旦牌多了,再使用多个角色就有点麻烦了,比较好的处理方式是使用克隆,这可以节省大量的重复性代码,提高代码效率,你要不要尝试一下克隆版的对对碰游戏呢,赶紧动手编程吧。