小学生系列之八——猜数游戏2
一、功能描述
1、游戏开始时:
自动生成一个1~100之间的随机数,即“目标值”;
回答次数显示为0;
题目数显示为1;
最小次数为100;
2、玩家用数字键盘输入猜测结果后,点击确定按钮:
如果猜测值大于目标值,则提示“大了!”;
如果猜测值小于目标值,则提示“小了!”;
统计并显示猜测次数;
如果猜测值正确,则弹出对话框:
a) 显示“猜中了!”以及猜测次数;
b) 对话框提供两个按钮供用户选择:
i. 再来一次:从新开始猜数游戏——执行第一步中的操作
ii. 退出:退出游戏;
c) 比较本次猜测次数与最小次数,并更新最小次数的显示结果;
项目在设计视图中的样子如图1所示。由于项目中的组件数量多,组件列表分两次截图,下半部分显示在图的右侧。
图1 猜数游戏_数字键版的用户界面设计
二、组件清单及属性设置
注:表格中的双线界定了布局组件的包含关系。
三、认识代码块
1、组件对象与键值对列表
在编程视图中,无论点击哪一个组件,都会在组件所属的代码块抽屉中看到一个与该组件同名的代码块,如图2所示,在按钮1的代码块抽屉中,最后一个代码块就是按钮1,它代表组件本身,我们称之为组件对象。
图2 每个组件的最后一个代码块就是组件本身——组件对象
那么如何理解组件对象呢?也就是说,它里面包含了哪些信息,如何使用它呢?我们先来讨论第一个问题,组件对象包含了哪些信息,为此需要先了解一下列表——一种有结构的复杂数据。列表由一项或多项简单数据(数字、文本或逻辑值)按照一定的顺序和结构组合在一起,如图3所示,它表示了按钮1这个组件对象中包含的部分信息。
图3 组件对象包含的信息
可以将按钮1的组件对象理解为图中的四级列表:
第一级列表包含两个列表项,它们都是子列表,这里称之为二级列表;
第一个二级列表包含两个列表项,第一个列表项“名称”表明数据的性质(就像一个表格的表头),第二个列表项“按钮1”是数据的内容(表头下面的值),这种包含两个列表项的列表,被称为键值对,其中的“名称”叫做“键”,而“按钮1”叫做值。
再来看第二个二级列表,这也是一个键值对,只不过它的值是另一个列表——三级列表;
在三级列表中包含了5个(其实不止5个)键值对,它们分别用来描述按钮1的属性及属性值,像这样由多个键值对组成的列表,被称为键值对列表,这是一种非常有用的列表类型,它与普通列表混合使用,可以描述非常复杂的数据,图3中的组件对象就是其中一种。
2、组件对象列表
按钮1~按钮10用于输入数字,由于它们的功能相近,因此为它们编写的程序也十分相似,将它们放在列表中的目的,就是要利用循环语句,批量地处理某些操作。首先声明一个全局变量——数字按钮列表,初始值为空列表,并在屏幕初始化程序中,设置具体的列表项。如图4所示。
图4 按钮组件组成的对象列表
在一个记单词的应用中,我们可以直接定义一个单词表,如图5所示,那么为什么在这里我们不直接定义数字按钮类表呢?
图5 在记单词应用中定义的单词表
这是一个很好的问题,它让我们有机会了解应用程序启动时所发生的事情。如图6所示,我们也试图直接定义数字按钮列表,但App Inventor给出了警告信息——不能在定义中使用该代码块。不过App Inventor并没有解释为什么。事实上,在应用启动过程中,应用中的全局变量与组件是同时被创建的,无法确定它们之间的创建顺序,也就是说,当声明全局变量时,10个数字按钮也许还没有创建完成,组件对象的内容还无法确定,因此App Inventor不允许在声明全局变量时,直接创建组件对象列表。当全局变量与全部组件都创建完成后,会触发屏幕初始化事件,因此,这时才是创建组件对象列表的恰当时机,正如图4中所示。
图6 直接设置组件列表的尝试是失败的,为什么呢?
3、认识任意组件类代码块
如图7所示,代码块被划分为三个大的分组——内置块、Screen1以及任意组件。内置块分组中的代码块与项目无关,Screen1分组中列出了项目中的所有组件,是与项目中具体组件相关的代码块;任意组件也是与项目中组件相关的代码块,只不过它不针对某个具体的组件,而是针对某一类组件,例如在图7中打开“任意按钮”的代码块抽屉,你会发现其中包含两大类块:深绿色的设置属性块与浅绿色的读取属性块,它们与Screen1分组中深绿色的组件属性设置块及浅绿色的组件属性读取块作用相同。
图7 任意组件类代码块
那么如何使用这些代码块呢?我们举例说明。如图7所示,如果想设置按钮1的显示文本为1,则选择“设某按钮组件的'显示文本’”块,必须为该块提供两个参数值,第一个参数值'该组件为’设置为“按钮1”,第二个参数值'设定值为’设置为“1”。同样,当我们需要读取按钮1的显示文本时,选择“取某按钮组件的'显示文本’”块,并将'该组件为’的值设为“按钮1”即可。需要强调的是,这里所说的“按钮1”,正是我们上面提到的按钮1的组件对象。
在读取块与设置块中,都有一个下拉列表,可以从中选取任意一个属性,进行设置与读取。
在实际开发中,当应用中拥有许多同种类型的组件,而且这些组件的功能又相类似时,就需要用到这类代码块。例如这个应用中的按钮1~按钮10,它们都是用来输入数字的按钮。
4、带参数的过程——形式参数与实际参数
为了编写10个数字按钮的点击事件处理程序,我们定义了一个带参数的过程——输入答案,如图8所示。参数这个概念对于小学生来说不容易理解,它是一个名词,你也可以把它理解为一个变量,可以用它指代某个值。
在我们定义输入答案过程时,我们为过程设置了一个参数——按钮,这个“按钮”代表一个按钮类型的组件,它并没有指向一个具体的按钮,只是起到一个占位的作用,我们称这时的按钮参数为形式参数,简称形参。
当我们在10个数字按钮的点击事件中调用输入答案过程时,这个过程块中有一个缺口,需要我们提供一个参数——一个具体的按钮,以便过程可以正常运行,我们称这个具体的按钮为实际参数,简称实参。如图8所示。当数字按钮发生点击事件时,调用输入答案过程,这时,为形式参数“按钮”提供一个实际参数——当前正被点击的按钮,从而实现猜测结果标签显示文本的更新。
图8 定义过程来处理数字按钮的点击事件
上述代码的逻辑是这样的:屏幕初始化时,猜测结果标签的显示文本为空,当用户点击某个数字按钮时,触发该按钮的点击事件,执行输入答案过程——在猜测结果标签中显示第一个数字;此时,如果用户再次点击数字按钮,那么猜测结果标签上的数字将变为先后输入的两个数字的拼接,这正是你在计算器中输入数字时的效果。
为了帮助理解形式参数与实际参数的含义,我们来举一个日常学校生活中的例子。班级中都有班长这个职位,班长就是一个参数;在选举班长之前,老师和同学都知道班长这个词的含义。当老师说“今天我们来选班长”时,“班长”这个词就相当于定义过程时的形式参数,它用来指代班长这个职位,而非具体某个人。当班长被推选出来之后,老师说“班长课后来开会”,这时的“班长”相当于调用过程时提供的实际参数,它指的不再是一个职位,而是一个具体的人。
5、对话框——选择对话框
对话框组件是一个使用频率很高的组件,用于显示那些在特殊情况下需要显示的信息。对于手机这样的终端设备来说,由于屏幕尺寸有限,因此,一些不需要自始至终显示的信息,通常会利用对话框组件来显示。在图9的确认答案过程中,我们用对话框组件来显示猜中结果信息,并提供了下一步操作的两种选择——再来一次或退出。图的右侧显示了程序的运行结果,并用箭头表示了选择对话框中各个参数的作用。最后一个参数“允许返回”如果设为真,则在对话框中会增加一个选择按钮,按钮上会显示“返回”字样。
图9 选择对话框中各个参数的作用
6、处理对话框的完成选择事件
如图10所示,当用户在对话框中选择了某个按钮时,程序将针对不同的选择,给出不同的处理结果,完成选择事件块中携带了一个值——选择结果,它就等于对话框中按钮上的文字,如“再来一次”或“退出”,这里我们用“如果…则…否则…”来处理两种不同的选择,想想看,如果对话框中的允许返回参数为真时,应该如何改写这段程序呢?
图10 对话框完成选择事件的处理程序
7、清除功能的实现
考虑到用户可能会误输入某些数字,因此,在应用中设置了清除按钮,所谓清除,就是让猜测结果标签的显示文本为空字符,如图11所示。
图11 清除功能的实现
四、操作技巧
1、布局组件嵌套
如图1所示,10个数字按钮与两个功能按钮(清除、确定),共12个按钮,它们整齐地排列在屏幕上,这样的结果要依赖于布局组件的使用:
在屏幕上添加一个垂直布局组件,令它的高宽均为充满;
在垂直布局组件中放置3个水平布局组件,它们的宽高也设为充满;
在每个水平布局组件中添加4个按钮组件,设它们的宽高均为充满;
上述设置的结果,就产生了12个等高等宽的按钮。
2、批量设置按钮属性
列表+循环,这是计算机最擅长的操作,下面我们利用数字按钮列表,在针对数字的循环语句中,一次性地设置10个按钮的属性,代码如图12所示。
图12 批量设置10个按钮的属性
五、全部代码
六、课后作业
每次猜中结果后,在对话框中显示猜测过程,即,显示本次游戏猜测过的所有数字,以逗号间隔。