第3章 AS 3.0程序设计
任何一门编程语言都要设计程序问题,ActionScript 3.0也不例外。本章将介绍ActionScript 3.0中代码的基本语句以及程序设计的一般过程。首先介绍程序控制的逻辑运算,然后着重介绍条件语句和循环语句。
3.1 逻辑运算
在程序设计的过程中,要实现程序设计的目的,必须进行逻辑运算。只有进行逻辑运算,才能控制程序不断向最终要达到的目标前进,直到最后实现目标。
逻辑运算又称为布尔运算,通常用来测试真假值。逻辑运算主要使用条件表达式进行判断,如果符合条件,则返回结果true;不符合条件,返回结果false。
条件表达式中最常见的形式就是利用关系运算符进行操作数比较,进而得到判断条件。
当然,有些情况下需要控制的条件比较多,那么就需要使用逻辑表达式进行逻辑运算,得到一个组合条件,并控制最后的输出结果。
常见的条件表达式举例如下:
❑(a>0):表示判断条件为a>0。若是,返回true;否则返回false。
❑(a==b)&&(a>0):表示判断条件为a大于0,并且a与b相等。若是,返回true,否则返回false。
❑(a==b)||(a>0):表示判断条件为a大于0,或者a与b相等。若是,返回true,否则返回false。
逻辑运算执行的最终结果,就是返回一个Boolean型的变量true或者false,然后按照程序的要求,执行相应的操作。
3.2 程序的3种结构
在程序设计的过程中,如果要控制程序,应安排每句代码执行的先后次序,这个先后执行的次序称为“结构”。常见的程序结构有3种:顺序结构、选择结构和循环结构。本节将分别介绍一下这3种程序结构的概念和流程。
3.2.1 顺序结构
顺序结构最简单,就是按照代码的顺序,一句一句地执行操作,结构如图3.1所示。
图3.1 顺序结构
ActionScript代码中的简单语句都是按照顺序进行处理的,这就是顺序结构。请看下面的示例代码:
//执行第一句代码,初始化一个变量 var a:int; //执行第二句代码,给变量a赋值数值1 a=1; //执行第三句代码,变量a执行递加操作 a++;
3.2.2 选择结构
当程序有多种可能的选择时,就要使用选择结构。选择哪一个,要根据条件表达式的计算结果而定。结构如图3.2所示。
图3.2 选择结构
举个简单的例子,使用if...else语句实现这样的效果。如果现在时间超过了22点,就停止写作,否则继续写作。程序代码如下所示:
if(现在时间>22点){ 停止写作 }else{ 继续写作 }
3.2.3 循环结构
循环结构就是多次执行同一组代码,重复的次数由一个数值或条件来决定。结构如图3.3所示。
图3.3 循环结构
循环结构只是包含了选择结构,因为它要判断是否符合条件,如果符合条件才会执行代码,否则就会跳出循环,执行后面的代码。对编程过程来说,循环结构能够节约程序代码,提高执行效率。例如,要在输出面板输出0~9这10个数,不使用循环结构,代码只能这样写:
trace(0); trace(1); trace(2); trace(3); trace(4); trace(5); trace(6); trace(7); trace(8); trace(9);
要写10行代码才能完成,而使用循环结构,只需用3行就可以实现相同的效果。代码如下所示:
for (var i:uint; i<10; i++) { trace(i); }
3.3 选择程序结构
选择程序结构就是利用不同的条件执行不同的语句或者代码。ActionScript 3.0有3个可用来控制程序流的基本条件语句,分别为if...else条件语句、if...else if...else条件语句、switch条件语句。本节将详细讲解这3种不同的选择程序结构。
3.3.1 if...else 条件语句
if...else条件语句判断一个控制条件,如果该条件能够成立,则执行一个代码块,否则执行另一个代码块。
if...else条件语句基本格式如下:
if(表达式){ 语句1; } else { 语句2; }
说明
如果表达式的值为真,就执行语句1,否则就执行语句2。
下面使用if...else条件语句实现年份是否为闰年的判断。
由分析可知,闰年的判断条件有以下两条:
❑当年份能被4整除,且不能被100整除,则该年为闰年。
❑当年份能被4整除,又能被400整除,则该年为闰年。
如果年份满足上述两个条件中的一个就是闰年。
若用year来表示存放年份的变量,则条件可以表示为:
(year%400==0)||(year%4==0)&&(year%100!=0)
完成后的代码如下所示:
var year:int=2008; if ((year%400==0)||(year%4==0)&&(year%100!=0)) { trace("今年是闰年"); } else { trace("今年不是闰年"); }
如果只是想在满足某个条件时执行操作,而不满足时不执行操作,可以省略else语句。格式如下所示:
if(表达式){ 语句; }
3.3.2 if...else if...else语句
if...else条件语句执行的操作最多只有两种选择,如果有更多的选择,那就可以使用if...else if...else条件语句。
if...else if...else语句格式如下:
if(表达式1){ 语句1; } else if (表达式2){ 语句2; } else if (表达式3){ 语句3; } . . . else if (表达式n){ 语句n; } else{ 语句 m; }
可以通过使用多个else⋯if来进行多个条件的判断,最后的else语句块可有可无(根据实际需要选用)。但是,这种多层条件判断语句在层次太多时执行速度较慢。另外如果条件过多,在编程的时候容易出现错误。
下面使用if...else if...else语句来实现网络上非常流行的隔段问候语效果。要实现的效果为先判断当前的时间,然后根据当前的时间来作出判断。
完成后的代码如下所示:
//获取当前时间 var date:Date=new Date(); //获取当前的小时 var hh:int=date.getHours(); //进行判断 if (( hh >= 0 ) && (hh <= 4 )) { trace("深夜了,注意身体,该休息了!"); } else if (( hh >= 4 ) && (hh < 7)) { trace("清晨好,这么早就上网呀?! "); } else if (( hh >= 7 ) && (hh < 12)) { trace("早上好,一日之际在于晨,又是美好的一天!"); } else if (( hh >= 12) && (hh <= 13)) { trace("该吃午饭啦!有什么好吃的?"); } else if (( hh >= 13) && (hh <= 17)) { trace("外面的天气很热吧?!心静自然凉! "); } else if (( hh >= 17) && (hh <= 18)) { trace("太阳落山了!快看看夕阳吧!"); } else if ((hh >= 18) && (hh <= 19)) { trace("吃过晚饭了吗?"); } else if ((hh >= 19) && (hh <= 23)) { trace("一天过得可真快!今天过得好吗?"); }
说明 if...else语句实现条件判断,但是使用起来相对比较烦琐一点,需要在使用的过程中根据需要来选择。
3.3.3 switch语句
switch语句相当于一系列的if...else if...else语句,但是比if语句要清晰得多。switch语句不是对条件进行测试以获得布尔值,而是对表达式进行求值,并使用计算结果确定要执行的代码块。
switch语句格式如下:
switch (表达式) { case1: 程序语句1; break; case2: 程序语句2; break; case3: 程序语句3; break; default: 默认执行程序语句; }
格式说明如下:
❑表达式:可以是任何表达式,其结果是一个具体的值。
❑case:关键字,其后跟有一个表达式、冒号和一组语句。如果在使用全等(===)的情况下,若此处的表达式与switch的表达式的参数相匹配,则执行这组语句。
❑break:跳出判断语句,也就是说,如果上面的表达式判断正确,已经执行了相应的语句,那么执行以后将跳出判断。
❑default:关键字,其后跟有一组语句。如果case表达式都不与switch的表达式参数全等(===)匹配时,将执行这些语句。
下面使用switch语句结合Date.getDay()方法返回的日期值输出当前的星期日期,代码如下所示:
//获取当前时间 var date:Date = new Date(); //获取当前是星期几 var dd:uint = date.getDay(); switch (dd) { case 0: trace("今天星期日"); break; case 1: trace("今天星期一"); break; case 2: trace("今天星期二"); break; case 3: trace("今天星期三"); break; case 4: trace("今天星期四"); break; case 5: trace("今天星期五"); break; case 6: trace("今天星期六"); break; default: trace("超出星期范围,是不可能的!"); break; }
说明 break关键字是跳出执行语句,在遇到该关键字后,程序代码将不再执行。
3.4 循环程序结构
在现实生活中有很多规律性的操作,作为程序来说就是要重复执行某些代码。其中重复执行的代码称为循环体,能否重复操作,取决于循环的控制条件。循环语句可以认为是由循环体和控制条件两部分组成。
循环程序的结构一般有两种:
❑一种是先进行条件判断,若条件成立,执行循环体代码,执行完成之后再进行条件判断,若条件成立,循环继续,否则退出循环。若第一次条件就不满足,则一次也不执行,直接退出。
❑另一种是先执行操作,不管条件,执行完成之后进行条件判断,若条件成立,循环继续,否则退出循环。
下面依次介绍ActionScript 3.0中的循环语句:for循环语句、while循环语句、do...while循环语句、for...in循环语句和for each...in循环语句。
3.4.1 for循环语句
for循环语句是ActionScript编程语言中最灵活、应用最为广泛的语句。for循环语句语法格式如下:
for(初始化;循环条件;步进语句) { 循环执行的语句; }
格式说明如下:
❑初始化:把程序循环体中需要使用的变量进行初始化。注意要使用var关键字来定义变量,否则编译时会报错。
❑循环条件:逻辑运算表达式,运算的结果决定循环的进程,若为false,退出循环,否则继续执行循环代码。
❑步进语句:算术表达式,用于改变循环变量的值。通常为使用++(递增)或--(递减)运算符的赋值表达式。
❑循环执行的语句:循环体,通过不断改变变量的值,以达到需要实现的目标。
下面的这段代码可以用来计算1~100的自然数之和:
//初始化变量 var sum = 0; //下面是 for 循环 for (var i:int=1; i<=100; i++) { //在计算加和的基础上累加 sum = sum + i;//循环体 } trace("sum="+sum);
代码运行后的输出结果如下所示:
//输出结果:sum=5050
另外,利用逗号运算符(,)可以在for循环中增加变量和控制语句。语法格式如下所示:
for(初始化语句1,初始化语句2;循环条件;步进语句1,步进语句2)
下面计算两个变量之积小于100的值,并输出对应的计算表达式。代码如下所示:
for (var a:int=1,b:int=20; a*b<100; a++,b--) { trace(a+"*"+b+"="+a*b); }
代码运行后的输出结果如下所示:
1*20=20 2*19=38 3*18=54 4*17=68 5*16=80 6*15=90 7*14=98
注意 在多个初始化语句中,只能在第一个初始化语句中使用var关键字,其他的语句不能使用var关键字,否则编译器会报错。
3.4.2 while循环语句
while循环语句是典型的“当型循环”语句,意思是当满足条件时,执行循环体的内容。while循环语句语法格式如下:
while(循环条件) { 循环执行的语句 }
格式说明如下:
❑循环条件:逻辑运算表达式,运算的结果决定循环的进程,若为true,继续执行循环代码,否则退出循环。
❑循环执行的语句:循环体,其中包括变量改变赋值表达式,以及执行语句并实现变量赋值。
该语句是常用的循环语句,其代码的执行过程为:先测试循环条件的逻辑结果,如果返回true,则运行循环语句块,如果该条件为false,则跳过该语句块,并执行while动作语句块之后的第一条语句。下面使用while循环计算1~100的自然数之和。代码如下所示:
//先初始化变量 var i:int = 0; var sum:int=0; //下面是 while 循环 while (i <= 100) { sum = sum + i; i++; } trace("sum="+sum);
代码运行后的输出结果如下所示:
sum=5050
3.4.3 do...while循环语句
do...while循环是另一种while循环,它保证至少执行一次循环代码,这是因为其在执行代码块后才会检查循环条件。do...while循环语句语法格式如下:
do {
循环执行的语句
} while (循环条件)
格式说明如下:
❑循环执行的语句:循环体,其中包括变量改变赋值表达式,以及执行语句并实现变量赋值。
❑循环条件:逻辑运算表达式,运算的结果决定循环的进程,若为true,继续执行循环代码,否则退出循环。
该语句的执行顺序和while语句有一定的区别。该循环要先执行语句,然后进入循环条件判断,如果条件为true,继续进行循环,否则跳出循环。
下面使用do...while循环计算1~100的自然数之和。代码如下所示:
//初始化变量 var i:int=0; var sum:int; //循环语句 do {; //循环体 sum+=i; i++; } while (i<=100); //输出结果 trace("sum="+sum);
代码运行后的输出结果如下所示:
sum=5050
3.4.4 for...in和for each...in语句
for...in和for each...in语句都可以用于循环访问对象属性或数组元素。下面分别使用这两个语句来访问对象中的属性。代码如下所示:
//定义一个对象lzxt,并添加属性name和age var lzxt:Object = {name:"浪子啸天", age:30}; //执行遍历操作 for (var i:String in lzxt) { //输出属性名称和属性值 trace("for in 语句输出:"+i + ": " + lzxt[i]); } //执行for each遍历操作 for each (var k:String in lzxt) { //输出属性值 trace("for each 语句输出:"+k); }
代码运行后的输出结果如下所示:
for in 语句输出:age: 30 for in 语句输出:name: 浪子啸天 for each 语句输出:30 for each 语句输出:浪子啸天
说明
从上面语句的测试结果可以看出,for...in语句在执行遍历对象操作时,遍历的结果是对象的属性;for each...in语句遍历的结果是属性的值。另外,for...in语句可以通过数组访问符“[]”和遍历出的对象属性来访问对象属性的值。
下面分别使用两种语句来遍历数组中的值。代码如下所示:
//定义一个数组变量,并初始化赋值 var arr:Array = ["one", "two", "three"]; //执行for in 遍历操作 for (var i:String in arr) { //输出数组的值 trace(arr[i]); } //执行for each in遍历操作 for each (var k in arr) { trace(k); }
代码运行后的输出结果如下所示:
one two three one two three
从一些程序的测试结果来看,for each...in语句比for...in语句的执行速度要快,执行效率要高。
for each...in语句除了可以用来遍历对象和数组的值,还可以通过循环访问XML或XMLList对象。下面使用for each...in语句来访问XML对象,代码如下所示:
//声明一个XML对象,并初始化赋值 var myXML:XML = <book> <bookname>flash cs3之路</bookname> <bookname>as3基础教程</bookname> <bookname>flex语言基础</bookname> </book>; //属于for each...in操作遍历XML对象 for each (var item in myXML.bookname) { //输出遍历获得的结果 trace(item); }
代码运行后的输出结果如下所示:
flash cs3之路 as3基础教程 flex语言基础
使用for each...in语句可以很方便地访问XML对象,并获取节点属性的值。
3.4.5 循环的嵌套
嵌套循环语句是在一个循环的循环体中存在另一个循环体,如此重复下去直到循环结束为止,即为循环中的循环。以for循环为例,格式如下所示:
for (初始化; 循环条件; 步进语句) { for (初始化; 循环条件; 步进语句) { 循环执行的语句; } }
下面使用循环语句,实现一个九九乘法表的效果。代码如下所示:
//循环语句1 for (var i:int=1; i<10; i++) { //循环语句2 for (var j:int=1; j<=i; j++) { //循环体 var label:TextField=new TextField(); label.text=i+"×"+j+"="+i*j; label.x=5+50*i; label.y=20*j; addChild(label); } }
完成后的效果如图3.4所示。
图3.4 九九乘法表效果图
循环嵌套可以解决很多比较麻烦的问题,但是也有一些需要注意的地方:
❑使用嵌套循环时,内部循环体的变量不要和外部循环体的变量相同。
❑嵌套循环结构的书写,最好用严格格式,采用相应的缩进,以体现循环层次。
❑要尽量避免使用太多层的循环结构,否则执行的效率会比较低。
3.4.6 循环流程控制语句
在ActionScript 3.0中可以使用break和continue来控制循环流程。break语句的结果是直接跳出循环,不再执行后面的语句;continue语句的结果是停止当前这一轮的循环,直接跳到下一轮的循环,而当前轮次中continue后面的语句也不再执行。
下面的两个例子分别执行循环变量从0递增到10的过程,如果i等于4,分别执行break和continue语句,观察各自执行的情况。代码如下所示:
//使用break控制循环 for (var i:int=0; i<10; i++) { if (i==3) { break; } trace("当前数字是:"+i); }
代码运行后的输出结果如下所示:
当前数字是:0 当前数字是:1 当前数字是:2
下面使用continue控制循环,代码如下所示:
for (var j:int=0; j<10; j++) {
if (j==3) {
continue;
}
trace("当前数字是:"+j);
}
代码运行后的输出结果如下所示:
当前数字是:0 当前数字是:1 当前数字是:2 当前数字是:4 当前数字是:5 当前数字是:6 当前数字是:7 当前数字是:8 当前数字是:9
说明
从上面代码的输出结果来看,break语句直接退出了循环,只输出到2,就连已经执行到的数值3都没有输出;continue语句则只是退出了当前轮次语句的执行,当重新开始后继续执行循环,故至少输出了i=3这一个结果。
break语句控制循环流程的退出。如果是在嵌套循环中,则主循环体内的break只能退出当前的循环,不能退出外部的循环。要使用break控制,则必须使用多个break语句。而ActionScript中引入了标签,新的标签可以和循环体一起使用,通过break标签的方法直接退出循环。下面的示例从内循环直接退出主循环。代码如下所示:
var j:Number; mainLoop:for (var i:int=0; i<10; i++) { for (j=0; j<10; j++) { if (i > 3 || j > 3) { break mainLoop; } trace(i,j); } }
代码运行后的输出结果如下所示:
0 0 0 1 0 2 0 3
说明
其中的mainLoop就是自定义的标签,当表达式i > 3 || j > 3返回为false时,就退出循环。
3.5 练习题
1. 用for循环计算1,2,4,8,⋯,2n(n=10)的和。
2. for(var...in...)和for each(...in...)是我们常用的遍历方法,它们有什么区别?
3. 补充下面代码,输出数据中的书名,输出格式为:
book1:sky book2:the wind
代码:
var arr:Array=[{name: "yyy",book: "sky"},{name: "xiang"},book: "the wind"] for(var i in arr){ var data:Object=arr[i]; for(var j in data){ trace( ) } }
4. 运行以下代码,i的值会是( )。
for(var i=0;i<10;++i){ } i=i+++i++; trace(i);
A. 11
B. 12
C. 21
D. 22