目录
- 顺序控制
- 分支控制(if else,switch)
- 循环控制(for,while,do while,多重循环)
- break
- continue
-
1.程序流程控制介绍
在程序中,程序运行的流程控制决定程序是如何执行的,是我们必须掌握的,主要有三大流程控制语句。
1) 顺序控制
2) 分支控制
3) 循环控制2.顺序控制
3.分支控制 if-else
介绍:
让程序有选择的的执行,分支控制有三种
1) 单分支 if
2) 双分支 if-else
3) 多分支 if-else if -….-else单分支
4.双分支
多分支
多分支的流程图(重要!)
案例演示 1
请大家看个案例[If03.java]:
输入保国同志的芝麻信用分:
如果:
1) 信用分为 100 分时,输出 信用极好;
2) 信用分为(80,99]时,输出 信用优秀;
3) 信用分为[60,80]时,输出 信用一般;
4) 其它情况 ,输出 信用 不及格
5) 请从键盘输入保国的芝麻信用分,并加以判断import java.util.Scanner;
public class If03{
public static void main(String[] args){
Scanner myScanner = new Scanner(System.in);
System.out.println("请输入芝麻信用分(1-100):");
int score = myScanner.nextInt();
//对输入数据判断
if(score >= 1 && score <= 100){
if(score == 100){
System.out.println("信用极好");
}else if(score > 80 && score <= 99){
System.out.println("信用优秀");
}else if(score >= 60 && score <= 80){
System.out.println("信用一般");
}else{
System.out.println("信用不及格");
}
}else{
System.out.println("信用分在1-100,请重新输入:");
}
}
}
5.嵌套分支
介绍:
在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层分支外面的分支结构称为外 层分支。老师建议: 不要超过 3 层 (可读性不好)
基本语法
应用案例
参加歌手比赛,如果初赛成绩大于 8.0 进入决赛,否则提示淘汰。并且根据性别提示进入男子组或女子组。
【可以
让学员先练习下】, 输入成绩和性别,进行判断和输出信息。[NestedIf.java]
import java.util.Scanner;
public class NestedIf{
public static void main(String[] args){
//思路分析:
//使用if判断,如果大于8.0进入决赛,否则淘汰
//如果进入决赛,再次if判断性别,是男的进入男子组,是女的进入女子组
Scanner myScanner = new Scanner(System.in);
System.out.println("输入该歌手成绩(0.0-10.0):");
double score = myScanner.nextDouble();
//对输入数据判断
if(score > 8.0){
System.out.println("输入性别(男/女)");
char gender = myScanner.next().charAt(0);
if(gender == '男'){
System.out.println("进入男子组");
}else if(gender == '女'){
System.out.println("进入女子组");
}else{
System.out.println("输入有误,重新输入");
}
}else{
System.out.println("Sorry,你被淘汰了");
}
}
}
课后练习:
import java.util.Scanner;
public class IfExercise{
public static void main(String[] args){
Scanner myScanner = new Scanner(System.in);
System.out.println("请输入月份(1-12)");
int month = myScanner.nextInt();
System.out.println("请输入年龄");
int age = myScanner.nextInt();
if(month >= 4 && month <= 10){
if(age < 18){
System.out.println("儿童半价:" + 30);
}else if(age >= 18 && age <=60){
System.out.println("成人全票:" + 60);
}else{
System.out.println("老人1/3:" + 20);
}
}else{
if(age >= 18 && age <=60){
System.out.println("成人全票:" + 40);
}else{
System.out.println("其他票价:" + 20);
}
}
}
}
6.switch分支结构
基本语法
流程图
入门案例:
案例:Switch01.java
- 请编写一个程序,该程序可以接收一个字符,
- 比如:a,b,c,d,e,f,g a 表示星期一,b 表示星期二 …
- 根据用户的输入显示相应的信息.要求使用 switch 语句完成
Scanner myScanner = new Scanner(System.in);
System.out.println("请输入一个字符(a-g)");
char week = myScanner.next().charAt(0);
switch(week){
case 'a':
System.out.println("今天是星期一");
break;
case 'b':
System.out.println("今天是星期二");
break;
case 'c':
System.out.println("今天是星期三");
break;
case 'd':
System.out.println("今天是星期四");
break;
case 'e':
System.out.println("今天是星期五");
break;
case 'f':
System.out.println("今天是星期六");
break;
case 'g':
System.out.println("今天是星期日");
break;
default:
System.out.println("输入有误,重新输入");
}
switch 注意事项
总结:
case类型一致(或自动类型转换)
数值为小于int和int以及String
default是可选的,没有匹配case,执行defaultswitch 课堂练习
(学员先做) SwitchExercise.java
1) 使用 switch 把小写类型的 char 型转为大写(键盘输入)。只转换 a, b, c, d, e. 其它的输出 “other”。
2) 对学生成绩大于 60 分的,输出”合格”。低于 60 分的,输出”不合格”。(注:输入的成绩不能大于 100), 提示 成绩/60
3) 根据用于指定月份,打印该月份所属的季节。3,4,5 春季 6,7,8 夏季 9,10,11 秋季 12, 1, 2 冬季 [课堂练习, 提示 使
用穿透 ]System.out.println("输入成绩(1-100)");
double score = myScanner.nextDouble();
if(score >= 0 && score <= 100){
switch((int)(score / 60)){
case 1:
System.out.println("合格");
break;
case 0:
System.out.println("不合格");
break;
}
}else{
System.out.println("输入有误,请重新输入(1-100)");
}
System.out.println("输入该月份(1-12)");
int month = myScanner.nextInt();
switch(month){
case 3:
case 4:
case 5:System.out.println("Spring");
break;
case 6:
case 7:
case 8:System.out.println("Summer");
break;
case 9:
case 10:
case 11:System.out.println("Autumn");
break;
case 12:
case 1:
case 2:System.out.println("Winter");
break;
default:
System.out.println("输入有误,重新输入(1-12)");
}
switch 和 if 的比较:
1) 如果 判断的具体数值不多,而且符合 byte、 short 、int、 char, enum[枚举], String 这 6 种类型。
虽然两个语句都可
以使用,建议使用 swtich 语句。
2) 其他情况:对区间判断,对结果为 boolean 类型判断,使用 if,if 的使用范围更广
7.for 循环控制(!!!)
基本介绍:
基本语法
说明:
- for 关键字,表示循环控制
2. for 有四要素: (1)循环变量初始化(2)循环条件(3)循环操作(4)循环变量迭代
3. 循环操作 , 这里可以有多条语句,也就是我们要循环执行的代码
4. 如果 循环操作(语句) 只有一条语句,可以省略 {}, 建议不要省略for 循环执行流程分析
1) 使用 for 循环完成前面的题
2) 画出 for 流程图
内存分析法
注意事项
ForDetail.java
1) 循环条件是返回一个布尔值的表达式
2) for(;循环判断条件;) 中的初始化和变量迭代可以写到其它地方,但是两边的分号不能省略。
3) 循环初始值可以有多条初始化语句,但要求类型一样,并且中间用逗号隔开,循环变量迭代也可以有多条变量迭代
语句,中间用逗号隔开。
4) 使用内存分析法,老师分析输出下面代码输出什么?
总结for:
- 循环条件为false退出
- 初始和迭代条件可写在外面,但是 ;必须有
- 死循环三个条件都没有,;必须有
- 初始混合迭代可多个,判断只能一个
for循环练习题:
(学员先做) ForExercise.java
1) 打印 1~100 之间所有是 9 的倍数的整数,统计个数 及 总和.[化繁为简, 先死后活]
2.完成下面的表达式输出 [老师评讲 ForExercise02.java]public class ForExercise {
public static void main(String[] args) {
//打印 1~100 之间所有是 9 的倍数的整数,统计个数 及 总和.[化繁为简,先死后活]
//老韩的两个编程思想(技巧)
//1. 化繁为简 : 即将复杂的需求, 拆解成简单的需求,逐步完成 编程 = 想 思想 -- 练习-> 代码
//2. 先死后活 : 先考虑固定的值,然后转成可以灵活变化的值
//思路分析
//打印 1~100 之间所有是 9 的倍数的整数,统计个数 及 总和
//化繁为简
//(1) 完成 输出 1-100 的值
//(2) 在输出的过程中,进行过滤,只输出 9 的倍数 i % 9 ==0
//(3) 统计个数 定义一个变量 int count = 0; 当 条件满足时 count++;
//(4) 总和 , 定义一个变量 int sum = 0; 当条件满足时累积 sum += i;
//先死后活
//(1) 为了适应更好的需求,把范围的开始的值和结束的值,做出变量
//(2) 还可以更进一步 9 倍数也做成变量 int t = 9;
int count = 0; //统计 9 的倍数个数变量
int sum = 0; //总和
int start = 10;
int end = 200;
int t = 5; // 倍数
for(int i = start; i <= end; i++) {
if( i % t == 0) {
System.out.println("i=" + i);
count++;
sum += i;//累积
}
}
System.out.println("count=" + count);
System.out.println("sum=" + sum);
}
}
编程思想:
- 化繁为简 : 即将复杂的需求, 拆解成简单的需求,逐步完成
2. 先死后活 : 先考虑固定的值,然后转成可以灵活变化的值编程思想总结:
- 化繁为简 : 复杂需求->细化小需求
2. 先死后活 : 固定值->范围8.while 循环控制
基本语法
画出流程图
代码执行内存分析图
注意事项和细节说明
1) 循环条件是返回一个布尔值的表达式
2) while 循环是先判断再执行语句课堂练习题
[学员先做] WhileExercise.java
1) 打印 1—100 之间所有能被 3 整除的数 [使用 while, 老师评讲 ]
2) 打印 40—200 之间所有的偶数 [使用 while, 课后练习]9.do..while 循环控制
基本语法
循环变量初始化;
do{
循环体( 语句);
循环变量迭代;
}while(循环条件);说明:
- do while 是关键字
1. 也有循环四要素, 只是位置不一样
2. 先执行,再判断,也就是说,一定会至少执行一次
3. 最后 有一个 分号 ;
4. while 和 do..while 区别举例: 要账do…while 循环执行流程分析
1) 画出流程图
2) 使用 do…while 循环完成前面的题
注意事项和细节说明
1) 循环条件是返回一个布尔值的表达式
2) do..while 循环是先执行,再判断, 因此它至少执行一次
总结:
课堂练习题
【学员先做】
1) 打印 1—100 [学生做]
2) 计算 1—100 的和 [学生做]
3) 统计 1—-200 之间能被 5 整除但不能被 3 整除的个数 (DoWhileExercise01.java)
4) 如果李三不还钱,则老韩将一直使出五连鞭,直到李三说还钱为止
System.out.println(“老韩问:还钱吗?y/n”)] do…while ..
DoWhileExercise02.java
方法一:
public class DoWhileExercise02 {
public static void main(String[] args) {
//如果李三不还钱,则老韩将一直使出五连鞭,直到李三说还钱为
//[System.out.println("老韩问:还钱吗?y/n")] do...while ..
//化繁为简
//(1) 不停的问还钱吗?
//(2) 使用 char answer 接收回答, 定义一个 Scanner 对象
//(3) 在 do-while 的 while 判断如果是 y 就不在循环
//一定自己动脑筋..
Scanner myScanner = new Scanner(System.in);
char answer = ' ';
do {
System.out.println("老韩使出五连鞭~");
System.out.println("老韩问:还钱吗?y/n");
answer = myScanner.next().charAt(0);
System.out.println("他的回答是" + answer);
}while(answer != 'y');//判断条件很关键
System.out.println("李三还钱了");
}
}
answer != ‘y’:answer不等于y为true,answer等于y为false
总结:
满足某个条件,成立
x==x true
满足某个条件,不成立
x!=x false
方法二:
Scanner myScanner = new Scanner(System.in);
boolean flag = true;
do{
System.out.println("老王使出五连鞭");
System.out.println("老王问:还钱吗?y/n");
char decide = myScanner.next().charAt(0);
switch(decide){
case 'y':
flag = false;
break;
case 'n':
break;
default:
System.out.println("输入有误,重新输入(y/n)");
}
}while(flag);
System.out.println("李三已经还钱");
10.多重循环控制(难点! 重点!)
介绍:
1) 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for ,while ,do…while 均可以作为外层循环和内层循环。
【建议一般使用两层,最多不要超过 3 层, 否则,代码的可读性很差】
2) 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为 false 时,才会完全跳出内
层循环,才可结束外层的当次循环,开始下一次的循环[听不懂,走案例]。
3) 设外层循环次数为 m 次,内层为 n 次,则内层循环体实际上需要执行 m*n 次。
多重循环执行步骤分析:
请分析 下面的多重循环执行步骤, 并写出输出 => 韩老师的内存分析法
//双层 for MulFor.java for(int i = 0; i < 2; i++) { //先思考 for( int j = 0; j < 3; j++) { System.out.println(“i=” + i + j=” + j); } }
内心解析:
总结:内存循环从初始开始,外层循环连续进行;外层信息结束才是结束
应用实例:
//MulForExercise01.java
1) 统计 3 个班成绩情况,每个班有 5 名同学,求出各个班的平均分和所有班级的平均分[学生的成绩从键盘入]。
2) 统计三个班及格人数,每个班有 5 名同学。
import java.util.Scanner;
public class MulForExercise01 {
public static void main(String[] args) {
//统计 3 个班成绩情况,每个班有 5 名同学,
//求出各个班的平均分和所有班级的平均分[学生的成绩从键盘输入]。
//统计三个班及格人数,每个班有 5 名同学。
//
// 思路分析:
//化繁为简
//(1) 先计算一个班 , 5 个学生的成绩和平均分 , 使用 for
//1.1 创建 Scanner 对象然后,接收用户输入
//1.2 得到该班级的平均分 , 定义一个 doubel sum 把该班级 5 个学生的成绩累积
//(2) 统计 3 个班(每个班 5 个学生) 平均分
//(3) 所有班级的平均分
//3.1 定义一个变量,double totalScore 累积所有学生的成绩
//3.2 当多重循环结束后,totalScore / (3 * 5)
//(4) 统计三个班及格人数
//4.1 定义变量 int passNum = 0; 当有一个学生成绩>=60, passNum++
//4.2 如果 >= 60 passNum++
//(5) 可以优化[效率,可读性, 结构]
//创建 Scanner 对象
Scanner myScanner = new Scanner(System.in);
double totalScore = 0; //累积所有学生的成绩
int passNum = 0;//累积 及格人数
int classNum = 3; //班级个数
int stuNum = 5;//学生个数
for( int i = 1; i <= classNum; i++) {//i 表示班级
double sum = 0; //一个班级的总分
for( int j = 1; j <= stuNum; j++) {//j 表示学生
System.out.println("请数第"+i+"个班的第"+j+"个学生的成绩");
double score = myScanner.nextDouble();
//当有一个学生成绩>=60, passNum++
if(score >= 60) {
passNum++;
}
sum += score; //累积
System.out.println("成绩为" + score);
}
//因为 sum 是 5 个学生的总成绩
System.out.println("sum=" + sum + " 平均分=" + (sum / stuNum));
//把 sum 累积到 totalScore
totalScore += sum;
}
System.out.println("三个班总分="+ totalScore
+ " 平均分=" + totalScore / (classNum*stuNum));
System.out.println("及格人数=" + passNum);
}
}
3) 打印出九九乘法表[课后题
总结:如果j = i,那么内层循环为j <= i
public class Multiplication{
public static void main(String[] args){
//九九乘法表
for(int i = 1;i <= 9;i++){
System.out.println();
for(int j = 1;j <= i;j++){
System.out.print(j + " * " + i + " = " + i * j + "\t");
}
}
}
}
经典的打印金字塔
使用 for 循环完成下面的案例
1.请编写一个程序,可以接收一个整数,表示层数(totalLevel),打印出金字塔。(Stars.java) [化繁为简, 先死后活]
public class Stars{
public static void main(String[] args){
/*
*
* *
* *
*******
思路分析:
化繁为简
1.先打印一个矩形
*****
*****
*****
*****
*****
2.先打印半个金字塔
* 第1行 1个*
** 第2行 2个*
*** 第3行 3个*
**** 第4行 4个*
***** 第5行 5个*
3.打印整个金字塔
i
* 第1行 1个* 2i - 1 4个空格 5-i
*** 第2行 3个* 3个空格
***** 第3行 5个* 2个空格
******* 第4行 7个* 1个空格
********* 第5行 9个* 0个空格
4.打印空心金字塔
i
* 第1行 1个* 当前行第一个(1)*和最后一个(2i - 1)*
* * 第2行 2个*
* * 第3行 2个*
* * 第4行 2个*
********* 第5行 9个* 全部输出(第五层)*
5.先死后活
5层做成变量int totalLevel = 5;
*/
// for(int i = 1;i <= 5;i++){//i表示行
// //输出*之前,还要输出打印每行对应空格
// for(int k = 1;k <= 5 - i;k++){
// System.out.print(" ");
// }
// //控制打印每行的*个数[纯for整个金字塔]
// for(int j = 1;j <= 2 * i - 1;j++){//j表示*
// //当前行第一个*和最后一个*,其他是空格
// //最后一层全部*
// if(j == 1 || j == 2 * i - 1 || i == 5){
// System.out.print("*");
// }else{//其他情况输出空格
// System.out.print(" ");
// }
// }
// //每打印完一层*后,就换行
// System.out.println();
// }
int totalLevel = 10;
for(int i = 1;i <= totalLevel;i++){//i表示行
//输出*之前,还要输出打印每行对应空格
for(int k = 1;k <= totalLevel - i;k++){
System.out.print(" ");
}
//控制打印每行的*个数[纯for整个金字塔]
for(int j = 1;j <= 2 * i - 1;j++){//j表示*
//当前行第一个*和最后一个*,其他是空格
//最后一层全部*
if(j == 1 || j == 2 * i - 1 || i == totalLevel){
System.out.print("*");
}else{//其他情况输出空格
System.out.print(" ");
}
}
//每打印完一层*后,就换行
System.out.println();
}
}
}
2.菱形
public class rhombusStars{
public static void main(String[] args){
/*
* 第1行 1个* 2个空格
*** 第2行 3个* 1个空格
***** 第3行 5个*
*** 第4行 3个*
* 第5行 1个*
*
* *
* *
* *
*
*/
//实心菱形
// int i = totalLever /2
for(int i = 1;i <= 3;i++){
for(int j = 1;j <= 3 - i;j++){//打印上半部分空格
System.out.print(" ");
}
for(int j = 1;j <= 2 * i - 1;j++){//打印上半部分*部分
if(j == 1 || j == 2 * i - 1){
System.out.print("*");
}else{
System.out.print(" ");
}
}
System.out.println();
}
for(int i = 2;i >= 1;i--){
for(int j = 1;j <= 3 - i;j++){//打印下半部分空格
System.out.print(" ");
}
for(int j = 1;j <= 2 * i - 1;j++){//打印下半部分*部分
if(j == 1 || j == 2 * i - 1){
System.out.print("*");
}else{
System.out.print(" ");
}
}
System.out.println();
}
}
}
递增和递减星星(重要)
/*
i
* 1 1
** 2 2
*** 3 3
**** 4 3
i
**** 1 4 4-i+1
*** 2 3
** 3 2
* 4 1
*/
for(int i =1;i <= 4;i++){
for(int j =1;j <= i;j++){
System.out.print("*");
}
System.out.println();
}
for(int i =1;i <= 4;i++){
for(int j =1;j <= 4 - i + 1;j++){
System.out.print("*");
}
System.out.println();
}
总结:
外层循环控制行,内行循环控制列
&&输出一个结果,||输出多个结果
递增j=i,递减j=h+1-i
11.跳转控制语句-break
看下面一个需求
随机生成 1-100 的一个数,直到生成了 97 这个数,看看你一共用了几次?
提示使用 (int)(Math.random() * 100) + 1
思路分析:
循环,但是循环的次数不知道. -> break ,当某个条件满足时,终止循环
通过该需求可以说明其它流程控制的必要性,比如 break
基本介绍:
break 语句用于终止某个语句块的执行,一般使用在 switch 或者循环[for , while , do-while]中
基本语法:
以 while 使用 break 为例,画出示意图
快速入门:
注意事项和细节说明:
label:
label: + break lable退出指定循环
用法:
label:for(){
break label;
}
课堂练习题:
1) 1-100 以内的数求和,求出 当和 第一次大于 20 的当前数 【for + break】BreakExercise.java
2) 实现登录验证,有 3 次机会,如果用户名为”丁真” ,密码”666”提示登录成功,否则提示还有几次机会,请使用 for+break
完成 BreakExercise02.java
//实现登录验证,有 3 次机会,如果用户名为"丁真" ,密码"666"提示登录成功,
//否则提示还有几次机会,请使用 for+break 完成
//
// 思路分析
// 1. 创建 Scanner 对象接收用户输入
// 2. 定义 String name ; String passwd; 保存用户名和密码
// 3. 最多循环 3 次[登录 3 次],如果 满足条件就提前退出
// 4. 定义一般变量 int chance 记录还有几次登录机会
//
// 代码实现
Scanner myScanner = new Scanner(System.in);
String name = "";
String passwd = "";
int chance = 3; //登录一次 ,就减少一次
for( int i = 1; i <= 3; i++) {//3 次登录机会
System.out.println("请输入名字");
name = myScanner.next();
System.out.println("请输入密码");
passwd = myScanner.next();
//比较输入的名字和密码是否正确
//补充说明字符串 的内容 比较 使用的 方法 equals
if("丁真".equals(name) && "666".equals(passwd)) {
System.out.println("恭喜你,登录成功~");
break;
}
}
//登录的机会就减少一次
chance--;
System.out.println("你还有" + chance + "次登录机会");
12. 跳转控制语句-continue
基本介绍:
1) continue 语句用于结束本次循环, 继续执行下一次循环。
2) continue 语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环 , 这个和前面的标签的
使用的规则一样.
基本语法:
以 while 使用 continue 为例,画出示意图
快速入门案例:
细节案例分析和说明:
ContinueDetail.java
label1:
for(int j = 0; j < 4; j++){
label2:
for(int i = 0; i < 10; i++){
if(i == 2){
//看看分别输出什么值,并分析
//continue ;
//continue label2;
continue label1;
}
System.out.println("i = " + i);//0 1 0 1
}
}
13.跳转控制语句-returnreturn
使用在方法,表示跳出所在的方法,在讲解方法的时候,会详细的介绍,这里我们简单的提一下。注意:如
果 return 写在 main 方法,退出程序..Return01.java
break/return/continue区别
不使用label:
break终止最近循环
return终止当前方法
continue结束本次循环
14.本章作业
循环最重要
习题详解
public class Homework06{
public static void main(String[] args) {
/*
输出1-100之间不能被5整除的数,每5个一行
思路分析:
1.先输出1-100的所有数
2.然后过滤出不能被5整除的数 i % 5 != 0
3.每5个一行,使用int count 统计输出个数;
当count%5==0,就说明输出了5个,这时输出一个换行
*/
int count = 0;//统计输出个数
for(int i = 1;i <= 100;i++){
if(i % 5 != 0){
count++;
System.out.print(i + "\t");
//判断,每满5个,输出一个换行
if(count % 5 == 0){
System.out.println();
}
}
}
}
}
/*
输出小写a-z以及大写Z-A
考察我们对a-z编码和for的综合使用
思路分析:
1.'b'='a'+1;'c'='a'+2
2.使用for循环
*/
for(char c = 'a';c <= 'z';c++){
System.out.print(c + "\t");
}
//
for(char c = 'Z';c >= 'A';c--){
System.out.print(c + "\t");
}
/*
求出1-1/2+1/3-1/4...1/100的和
思路分析:
1. 1-1/2+1/3-1/4...1/100 = (1/1)-(1/2)+(1/3)-(1/4)...1/100
2. 从上面看出:
1)分子为1,分母从1-100
2)分母是偶数为减,分母是奇数为加
3.使用for+判断完成
4.把结果定义变量累加
5.$隐藏陷阱:1/整型=0,把分子1写成1.0 => 1.0/整型=精确小数
*/
double subtr = 0;
for(int i = 1;i <= 100;i++){
if(i % 2 == 0){//i为奇数
subtr -= 1.0 / i;
}else{//i为偶数
subtr += 1.0 / i;
}
}
System.out.println(subtr);
总结
一般使用coutinue都可以用!=代替;活用计数器得到换行/平均/次数
字符总结:
字符可以直接赋一个整数(或字符),输出整数对应字符
字符运算,实际是整数运算(int)
例如:a=97,b=98;A=65,B=66
余数商总结
循环总结:
i表示外层循环时,同时也是内层循环last=金字塔模型
starNum= i * j