ActionScript 3.0从入门到精通(视频实战版)
上QQ阅读APP看书,第一时间看更新

第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,并添加属性nameage
    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