第3章〓控制程序设计 在前面两章,所有的程序都是顺序结构,即程序从main()方法开始进入,然后逐条指令开始执行,直到所有指令都执行完。但是,就像生活一样,不是所有的事情都能按照计划执行,许多事情经常会随着条件的变化面临着各种选择。程序亦是如此,也会根据不同条件执行相应的行为。例如,在“贪吃蛇”游戏中,按下不同的按键,“贪吃蛇”的运动方向随之而改变。本章主要介绍选择和循环控制结构程序设计的实现方法。 3.1选择控制结构语句 3.1.1if语句 最常见的选择语句是if语句。if语句用于选择是否执行一个行为,执行过程是先计算条件表达式的值,如果条件表达式为真,则执行其后的语句; 否则,就直接跳过其后的语句。Java语言提供了3种形式的if语句。 1. 单分支结构 单分支结构基本形式如下: if(条件表达式){ 语句; } 单分支结构非常简单,if后面括号里的条件表达式值为真,就执行{}里的语句; 否则,直接越过{}里的语句。{}里的语句是复合语句,相当于一个整体。{}里的语句可以是多条,也可以只有1条,当只有1条语句的时候,可以省略{}。 视频讲解 【例3.1】编写程序,实现通过按键控制方块运动,即当按下“w”键时,方块向上运动,如图3.1所示。 图3.1按键控制方块运动 为了实现按键控制方块运动,需要获得按键输入信息,然后根据判断信息执行相应的行为。Screen类的getKey()方法可以获得按键的输入信息,然后根据键值执行相应的操作。代码如下: public class Main { public static void main(String[] args){ final int SIZE = 8; Screen screen = new Screen(SIZE); int row = screen.getRandom(SIZE); int col = screen.getRandom(SIZE); Cell cell = new Cell(row,col); screen.add(cell); char key; while(true) { screen.delay(); key = screen.getKey(); if(key == 'w') {// 按键为w,向上运动 cell.moveUp(); } } } } 运行程序,在键盘上按“w”键时,方块向上运动。有时候不小心将键盘上大写键打开了,测试程序的时候,按下“w”键,方块并没有向上运动,这个错误不易发现,所以将代码修改成按下“W”键也能向上运动,代码如下: public class Main { public static void main(String[] args){ final int SIZE = 8; Screen screen = new Screen(SIZE); int row = screen.getRandom(SIZE); int col = screen.getRandom(SIZE); Cell cell = new Cell(row,col); screen.add(cell); char key; while(true) { screen.delay(); key = screen.getKey(); if(key == 'w' || key == 'W') { cell.moveUp(); } } } } 运行程序,当按下“W”键的时候,方块向上运动。 2. 双分支结构 除了上述单分支选择结构,Java语言提供了ifelse双分支语句,即在两条语句之中进行选择,格式如下: if(条件表达式){ 语句1; } else{ 语句2; } ifelse语句执行过程是: 如果满足条件表达式,则执行语句1; 否则执行语句2。语句1和语句2均可以由多条语句组成。另外,需注意else语句不能单独使用,必须与if配对使用。 视频讲解 【例3.2】编写程序,实现按“W”键控制方块向上运动,按其他键控制方块向下运动。 按下“W”键向上运动,按下其他键则向下运动,这是非常明显的二选一情况,所以可以使用ifelse语句实现要求,代码如下: public class Main { public static void main(String[] args){ final int SIZE = 8; Screen screen = new Screen(SIZE); int row = screen.getRandom(SIZE); int col = screen.getRandom(SIZE); Cell cell = new Cell(row,col); screen.add(cell); char key; while(true) { screen.delay(); key = screen.getKey(); if(key == 'w' || key == 'W') { cell.moveUp(); } else{ cell.moveDown(); } } } } 运行程序,当按下“W”键时,方块向上运动; 按下其他键时,方块向下运动。 3. 多分支结构 在程序中,经常会遇到面临很多选择的时候,例如按下不同的按键控制方块向不同方向运动,Java语言提供了ifelse ifelse语句,格式如下: if(条件表达式1){ 语句1; } else if(条件表达式2){ 语句2; } … else{ 语句n; } 该语句执行过程是: 如果满足条件表达式1的时候,则执行语句1,否则计算条件表达式2; 如果满足条件表达式2,则执行语句2,否则计算下一个条件表达式; 直到所有条件均不满足,则执行else所对应的语句n。 视频讲解 【例3.3】编写程序,实现按“W”键控制方块向上运动,按“S”键控制方块向下运动,按其他键控制方块斜向左上运动。 根据题意可知,这是多种选择的情况,可以使用ifelse ifelse语句实现功能,代码如下: public class Main { public static void main(String[] args){ final int SIZE = 8; Screen screen = new Screen(SIZE); int row = screen.getRandom(SIZE); int col = screen.getRandom(SIZE); Cell cell = new Cell(row,col); screen.add(cell); char key; while(true) { screen.delay(); key = screen.getKey(); if(key == 'w' || key == 'W') { cell.moveUp(); } else if(key == 's' || key == 'S'){ cell.moveDown(); } else{ cell.moveLeft(); cell.moveUp(); } } } } 运行程序,当按下“W”键时,方块向上运动; 按下“S”键时,方块向下运动; 按下其他按键时,方块斜向左上运动。 if语句用于选择是否执行一个行为,ifelse语句用于在两个语句之间进行选择,ifelse ifelse语句用于在多个语句之间进行选择。 3.1.2switch语句 对于在多个选项中选择,不仅可以用ifelse ifelse语句来完成,Java语言还提供了一种更为方便的switch语句,它的格式如下: switch(表达式){ case 常量表达式1: 语句1; break; case 常量表达式2: 语句2; break; ... default:语句n; } 该语句执行过程是: 先计算表达式的值,如果表达式的值与某个常量表达式的值相等,则执行其后控制的语句; 如果所有的常量表达式都与表达式的值不相等,则执行default后的语句。 需要注意的是: (1) case后面必须是常量表达式,不能包含变量,并且每个常量表达式的值都不相同。 (2) default语句可以缺省。如果省略了default语句,当表达式的值与所有的常量表达的值都不相等,则什么也不执行。 (3) break语句可以终止其所在的switch语句的执行。switch语句执行的原理是遇到匹配项之后,开始执行其后的语句,如果没有遇到break语句,会一直执行到switch语句结束为止。 视频讲解 【例3.4】使用switch语句编写程序,实现按“w”键控制方块向上运动,按“s”键控制方块向下运动,按“a”键控制方块向左运动,按键“d”控制方块向右运动。 使用switch语句,代码如下: public class Main { public static void main(String[] args){ final int SIZE = 8; Screen screen = new Screen(SIZE); int row = screen.getRandom(SIZE); int col = screen.getRandom(SIZE); Cell cell = new Cell(row,col); screen.add(cell); char key; while(true) { screen.delay(); key = screen.getKey(); switch(key) { case 'w' : cell.moveUp(); break; case 's': cell.moveDown(); break; case 'a': cell.moveLeft(); break; case 'd': cell.moveRight(); break; } } } } 运行程序,“w”“s”“a”“d”键可以分别控制方块上、下、左、右运动。 使用swtich语句的时候,要根据情况需要,判断是否要加上break语句。例如打开大写键,按键依然能控制方块上、下、左、右运动。使用swtich语句实现的话,代码如下: public class Main { public static void main(String[] args){ final int SIZE = 8; Screen screen = new Screen(SIZE); int row = screen.getRandom(SIZE); int col = screen.getRandom(SIZE); Cell cell = new Cell(row,col); screen.add(cell); char key; while(true) { screen.delay(); key = screen.getKey(); switch(key) { case 'w' : case 'W' : cell.moveUp(); break; case 's': case 'S': cell.moveDown(); break; case 'a': case 'A': cell.moveLeft(); break; case 'd': case 'D': cell.moveRight(); break; } } } } 运行程序,即使打开大写键,“W”“S”“A”“D”键依然能控制方块上、下、左、右运动。当按下按键“W”的时候,case 'w' 选项后的语句为空,程序会自动往下执行,执行case 'W' 选项对应的程序段,所以即使大写键开启,输入的键值是“W”也能控制方块向上运动。 如果给每一个case 选项的语句段都增加break语句,则需要增加不少重复的代码。对于不同条件,执行相同行为的场景下,通过switch语句和break语句的结合使用,可以写出简洁的代码。 对于switch语句中漏掉break语句这种情况时有发生,Java 14版本采用了新的方式规避这个问题,使用简化的“case L >”模式匹配语法,作用于不同范围并控制执行流,代码为: public class Main { public static void main(String[] args){ final int SIZE = 8; Screen screen = new Screen(SIZE); int row = screen.getRandom(SIZE); int col = screen.getRandom(SIZE); Cell cell = new Cell(row,col); screen.add(cell); char key; while(true) { screen.delay(); key = screen.getKey(); switch(key) { case 'w','W'-> { cell.moveUp(); } case 's','S'-> { cell.moveDown(); } case 'a','A'->{ cell.moveLeft(); } case 'd','D'->{ cell.moveRight(); } } } } } 将重复的case标签常量合并在一个case常量表达式中,用逗号分隔,箭头指向语句即可,执行完语句后退出switch语句。 虽然switch语句有时候比ifelse语句简洁,逻辑关系一目了然,程序可读性好,但是使用范围较窄,比如选择条件是非常大的范围时,就不适合用switch语句。如表达变量 i 是 100~550 的整数时,使用if语句非常简单,代码如下: if( i > 100 && i < 550 ) 而使用switch语句将会非常麻烦,需要设置几百个case选项,因此对于初学者来说,熟练掌握if语句即可。 3.2循环控制结构语句 循环是指反复执行某一过程,在3.1节中的案例使用的while语句就是一种经典的循环结构。循环结构是结构化程序的基本结构之一,它与顺序结构、选择结构共同构成各种复杂的程序。换言之,所有结构化程序都是由这三种基本结构组成。Java语言提供了while语句、dowhile语句和for语句来实现循环结构。 3.2.1while语句 while语句是常见的循环语句,while语句的格式如下: while(条件表达式){ 循环体语句; } while语句的执行过程是: 当圆括号里的条件表达式为真时,执行循环体语句,然后再判断表达式里的值,如果为真,继续执行循环体语句,如此重复执行,直到表达式的值为假的时候结束循环。 while语句和if语句,两者结构非常相似,两者的差别在于if语句只判断一次,而while语句会反复判断,直到条件不满足为止。 视频讲解 【例3.5】编写程序,使用while语句,实现“贪吃蛇”不断向下运动,一直运动到屏幕底部撞到墙,游戏结束,如图3.2所示。 图3.2“贪吃蛇”向下运动 “贪吃蛇”可以不断向下运动的条件就是: “蛇头”没有达到屏幕底部。解决了判断条件,接下来就是循环体的内容,主要包括两部分: 延时和向下运动。代码如下: public class Main { public static void main(String[] args){ final int SIZE = 8; Screen screen = new Screen(SIZE); Cell head = new Cell(0,4); Cell body = new Cell(0,5); screen.add(head); screen.add(body); while(head.getRow() 1){ k-- ; } A. 循环执行了5次 B. 循环执行了0次 C. 循环执行了4次 D. 循环执行了3次 3.2执行以下程序,sum的值为。 int sum = 0; int i ; for( i = 0; i <= 5; i++){ sum + = i; } A. 10 B. 15 C. 21 D. 28 3.3编写程序,在屏幕上显示杨辉三角图形,如图3.6所示。 第0行添加1个方块; 第1行添加2个方块; … 第N行添加N+1个方块。 3.4编写程序,在屏幕上显示倒杨辉三角图形,如图3.7所示。 图3.6杨辉三角 图3.7倒杨辉三角 3.5编写程序,按键“W”“S”“A”“D”控制“Z”形“俄罗斯方块”(如图3.8所示)上、下、左、右运动。 图3.8“Z”形“俄罗斯方块”示意图