App Inventor编程开发集锦是App Inventor编程教程的延伸,通过PBL项目制的实战案例,讲解App ...

App Inventor编程开发集锦-目录

第6课 程序的测试与修正

1、开发工具提示错误

(1)错误描述:

无论是闯关成功还是失败,当一轮游戏结束,点击“Cancel”或“重新开始”按钮后,在开发工具的编程视图中,出现以下错误提示,如图1- 49所示。同时,测试手机上显示上一轮游戏结束时的画面,如图1- 50。

图1- 49 错误提示:试图从长度为0的列表中选取索引值为1的列表项(闯关成功及失败)
图1- 50 测试中的第一个错误
(2)问题分析

从错误提示上看,错误与列表操作有关。我们来查看一下,在对话框组件中,当选择了“重新开始”按钮之后,都发生了哪些事情——在对话框1的“完成选择”事件中,调用了游戏初始化过程,我们来查看该过程。如图1- 47所示,该过程调用了两个过程(随机分配图案、初始化背面图案),并执行了五条指令(设置全局变量值、设置组件属性),其中两个过程都涉及到列表操作,那么问题在那个过程里呢?我们发现当开发环境提示错误信息时,测试手机上仍然显示上一轮游戏结束时的画面(显示已经翻开的水果图案),也就是说,初始化背面图案的过程没有起作用。我们尝试调换两个过程的顺序,让初始化背面图案过程优先执行,而随机分配图案过程随后执行。如图1- 51所示,测试结果发现所有卡片都显示了背面图案。这说明初始化背面图案过程中没有错误,由此看来,问题就出在随机分配图案过程中。

图1- 51 调换两个过程的执行顺序
在随机分配图案过程中,被操作的列表有三个:①全局变量图片列表;②全局变量随机图案列表;③局部变量图案列表。我们来分析每一步操作之后列表的变化。如图1- 52所示。

图1- 52 随机分配图案过程中,列表项的变化
与简单变量不同的是,列表变量在内存中保存了两类信息:①每个列表项的存放地址;②每个列表项的值。当我们访问列表项时,首先获得的是列表项的地址,然后再根据地址获取列表项的值。当我们执行“设 列表A 为 列表B”这样的指令时,我们并没有开辟另一块内存空间,单独存放列表A,而是把列表B存放数据的地址“引见”给列表A,两个列表拥有同一套列表项的地址及列表项的值(或者说是一个列表拥有两个名字),因此,当我们删除其中任何一个列表中的元素时,另一个列表中对应的元素也就不存在了。

在图1- 52中,当我们从局部变量图案列表中逐项删除其中的元素时,全局变量图片列表中的列表项也被同时删除,我们可以通过实验来证明这一点。我们在用户界面中添加一个标签组件,命名为图片列表,并在随机显示图案过程中监控图片列表的内容。

先把显示图片列表的代码放在过程的第一行,如图1- 53所示。

图1- 53 将显示图片列表的代码放在过程的第一行
再将显示图片列表的代码放在过程的末尾,如图1- 54所示,其结果如图1- 55所示。

图1- 54 将显示图片列表的代码放在过程的最后一行
图1- 55 代码放置的位置不同,测试结果不同
图1- 55的结果证明了我们的结论:临时变量图案列表和全局变量图片列表指向的是同一组数据。如果你有兴趣,可以将显示列表内容的代码放在不同的位置,并观察列表项的变化,相信你会有收获的。

(3)程序的修正

找到问题的原因就等于解决了问题的一大半,下面我们来修补程序,完成这个重新开始游戏的功能。

解决方法一:创建一个图片初始化的过程,在每次重新开始游戏时,调用该过程,如图1- 56所示。

图1- 56 每次重新开始游戏时,创建图片列表
解决方法二:使用列表复制功能,如图1-57,与图1- 54对比,多了一个“复制列表”的代码块。复制的意思就是另外生成一个一模一样的列表,新列表与原来列表不再使用同一个存储空间,这样,对新列表的任何操作不会再影响到原有列表。

图1- 57 使用复制列表功能
如果采用第二种方法,则在游戏初始化过程中,将不必调用图片初始化过程。我们的程序采用了第二种方法。

我们继续进行测试。第一轮游戏运行正常,当开始第二轮游戏时,开发环境中不再出现错误提示,却发现点击按钮时没有任何反应。

2、重新开始游戏时点击按钮无响应

(1)问题分析:

这也许是一个最容易解决的问题:按钮对于点击行为没有响应,说明按钮处于禁用状态(启用属性值为假)。回想一下我们的程序,每翻开一对卡片,都会设置按钮的启用属性值为假,在一轮游戏结束,并开始下一轮游戏时,执行了游戏初始化过程,该过程并没有更改按钮的启用属性,按钮实际上仍然处于禁用状态,因此点击按钮才会没有反应。

(2)修改程序

在游戏初始化过程里,添加针对按钮列表的循环语句,将每个按钮的启用属性设置为真。修改后的代码如图1- 58所示。

图1- 58 开始新一轮游戏前,启用所有按钮
经过测试,程序运行正常。继续测试发现,在第二轮乃至此后的每一轮游戏中,图案的排列顺序都与第一轮完全相同。

3、重新开始游戏时图案排列不变

(1)问题分析

图案随机排列的功能由随机分配图案过程负责,因此我们来检查这个过程。为了查看程序的执行效果,我们添加了一个标签,用于显示随机图案列表的内容,并在随机分配图案过程里设置它的显示文本属性。如图1- 59所示。测试结果如图1- 60所示,随机图案列表的列表项多出一倍。问题的原因在于:每次调用随机分配图案过程时,都会在原有列表的末尾添加16个列表项,因此每一轮游戏都会显示前面的16个图案,而新生成的16个图案永远都不可能被显示。

图1- 59 跟踪程序的执行结果
图1- 60 跟踪结果是,列表长度加倍
(2)程序修正

在随机分配图案过程里添加一行代码,在每次调用该过程时,先清空原有列表,如图1- 61所示。

图1- 61 在创建新的随机图案列表之前,清空该列表
经过测试,问题得到解决。继续测试。当我们快速点击按钮时,开发工具中会出现这样的错误提示,如图1- 62所示(这个错误在第四节出现过,见图1- 29);同时,快速点击按钮有时会让一张卡片单独地翻开,接下来的操作好像与它不再有任何关系,最终也无法让它再配成对,然后是闯关失败。

图1- 62 新的问题发生在快速点击按钮时

4、快速点击按钮时系统提示错误

(1)问题分析

问题的出现一定与闪现计时器的延迟有关。从闪现计时器开始计时,到第一次计时事件发生,这之间有500毫秒的时间,此时,全局变量翻牌1与翻牌2都不等于0,如果这期间玩家点击了第三个按钮,那么翻牌2将等于第三个按钮,而第二个按钮将失去翻牌2的“身份”,像一个孤儿一样被翻开在屏幕上,不能被再次点击(启用属性值为假),也没有机会被重新设置其图像及启用属性。这就是问题出现的原因。

(2)程序修正

为了防止发生这样的问题,我们采用一个极端的行为,在两张不同的卡片被翻开后,让所有的按钮都处于未启用状态,直到两张不同的卡片扣过去之后,再启用那些没有被翻开的按钮。这项功能需要对按钮的翻开状态进行判断。对处理点击事件过程进行修改,改过的代码如图1- 63及图1- 64所示。

图1- 63 当两张卡片图案不同时,让所有按钮的启用属性为假【处理点击事件过程】
图1- 64 当计时器1停止计时,让所有背面图案的按钮恢复到启用状态
现在,无论你以多快的速度点击按钮,程序都不会再出错了。

测试环节告一段落,随着更多的人开始使用这个软件,还有可能发现新的bug。