笨办法学 Java(二)(3)

简介: 笨办法学 Java(二)(3)

笨办法学 Java(二)(2)https://developer.aliyun.com/article/1481895


练习 33:名为“Pig”的骰子游戏

在上一课中,我们为骰子游戏Pig编写了计算机 A.I.(记住,如果你想要更多关于这个游戏的信息,你可以阅读维基百科关于 Pig 的条目。)在这一课中,我们将有整个游戏的代码,有一个人类玩家和一个计算机玩家轮流进行。

你上次写的整个程序大致对应于这个程序中的第 43 到 67 行。唯一的主要区别是,我们将有一个turnTotal变量来保存一个回合的点数,而total2变量则保存计算机从一轮到另一轮的总点数。

1 import java.util.Scanner;
 2 
 3 public class PigDice
 4 {
 5     public static void main( String[] args )
 6     {
 7         Scanner keyboard = new Scanner(System.in);
 8 
 9         int roll, total1, total2, turnTotal;
10         String choice = "";
11 
12         total1 = 0;
13         total2 = 0;
14 
15         do
16         {
17             turnTotal = 0;
18             System.out.println( "You have " + total1 + " points." );
19 
20             do
21             {
22                 roll = 1 + (int)(Math.random()*6);
23                 System.out.println( "\tYou rolled a " + roll + "." );
24                 if ( roll == 1 )
25                 {
26                     System.out.println( "\tThat ends your turn." );
27                     turnTotal = 0;
28                 }
29                 else
30                 {
31                     turnTotal += roll;
32                     System.out.println( "\tYou have " + turnTotal + " points so far this 
round." );
33                     System.out.print( "\tWould you like to \"roll\" again or \"hold\"? " );
34                     choice = keyboard.next();
35                 }
36             } while ( roll != 1 && choice.equals("roll") );
37 
38             total1 += turnTotal;
39             System.out.println( "\tYou end the round with " + total1 + " points." );
40 
41             if ( total1 < 100 )
42             {
43                 turnTotal = 0;
44                 System.out.println( "Computer has " + total2 + " points." );
45 
46                 do
47                 {
48                     roll = 1 + (int)(Math.random()*6);
49                     System.out.println( "\tComputer rolled a " + roll + "." );
50                     if ( roll == 1 )
51                     {
52                         System.out.println( "\tThat ends its turn." );
53                         turnTotal = 0;
54                     }
55                     else
56                     {
57                         turnTotal += roll;
58                         System.out.println( "\tComputer has " + turnTotal + " points so far this 
round." );
59                         if ( turnTotal < 20 )
60                         {
61                             System.out.println( "\tComputer chooses to roll again." );
62                         }
63                     }
64                 } while ( roll != 1 && turnTotal < 20 );
65 
66                 total2 += turnTotal;
67                 System.out.println( "\tComputer ends the round with " + total2 + " points." );
68             }
69 
70         } while ( total1 < 100 && total2 < 100 );
71 
72         if ( total1 > total2 )
73         {
74             System.out.println( "Humanity wins!" );
75         }
76         else
77         {
78             System.out.println( "The computer wins." );
79         }
80 
81     }
82 }

你应该看到什么

You have 0 points.
You rolled a 2.
You have 2 points so far this round.
Would you like to "roll" again or "hold"? roll You rolled a 1.
That ends your turn.
You end the round with 0 points.
Computer has 0 points.
Computer rolled a 6.
Computer has 6 points so far this round. Computer chooses to roll again.
Computer rolled a 6.
Computer has 12 points so far this round. Computer chooses to roll again.
Computer rolled a 1\. That ends its turn.
Computer ends the round with 0 points.
You have 0 points.
You rolled a 3.
You have 3 points so far this round.
Would you like to "roll" again or "hold"? roll You rolled a 5.
You have 8 points so far this round.
Would you like to "roll" again or "hold"? roll You rolled a 2.
You have 10 points so far this round.
Would you like to "roll" again or "hold"? roll You rolled a 2.
You have 12 points so far this round.
Would you like to "roll" again or "hold"? hold You end the round with 12 points.
Computer has 0 points.
Computer rolled a 5.
Computer has 5 points so far this round. Computer chooses to roll again.
Computer rolled a 4.
Computer has 9 points so far this round. Computer chooses to roll again.
Computer rolled a 4.
Computer has 13 points so far this round. Computer chooses to roll again.
Computer rolled a 3.
Computer has 16 points so far this round. Computer chooses to roll again.
Computer rolled a 5.
Computer has 21 points so far this round.
Computer ends the round with 21 points.
You have 12 points.
You rolled a 2.
You have 2 points so far this round.
Would you like to "roll" again or "hold"? roll
...etc
Computer has 20 points so far this round. 
Computer ends the round with 102 points.
The computer wins.

我们从两个变量开始程序:total1保存人类的总点数,total2保存计算机的总点数。两者都从 0 开始。

然后在第 15 行开始一个非常庞大的 do-while 循环,基本上包含了整个游戏,直到第 70 行才结束。向下滚动,你会看到这个循环会重复,只要total1total2都小于 100。当任一玩家达到 100 或更多时,条件不再成立,do-while 循环不会再重复。

然后在那个 do-while 循环结束之后(从第 72 行开始),有一个if语句和一个else来确定赢家。

让我们往上滚动一下,看看人类的回合,从第 17 行开始。turnTotal是人类到目前为止在这一轮中赚得的点数。由于这是一轮的开始,我们应该从 0 开始。

第 20 行是一个包含人类回合的 do-while 循环的开始。它在第 36 行结束,所有在第 20 行和第 36 行之间的代码都会重复,只要人类没有掷出 1,只要人类继续选择再次掷骰子。

人类的每次掷骰子都和计算机一样开始:选择一个从 1 到 6 的随机数。我们在第 22 行打印出来。

现在可能发生两件事:要么掷骰子是 1——人类失去本轮获得的所有分数——要么掷骰子是 2-6,然后将掷骰子的点数加到他们的turnTotal上。我们显示适当的消息,在第 33 和 34 行,我们给人类选择再次掷骰的机会,或者通过保持来安全地玩。然后在第 36 行,do-while 循环的条件将检查并在适当的情况下重复回到第 20 行。

一旦玩家的回合结束,我们将turnTotal(可能为 0)加到玩家的总分上,并显示他们当前的分数。

在第 41 行,计算机的回合开始了。然而,如果人类已经达到了 100 分,计算机就不会轮到了:在这种情况下游戏结束。因此,为了防止计算机玩游戏,我们必须将整个计算机的回合包装在一个大的if语句中,以便在人类的总分(total1)大于或等于 100 时跳过。这个if语句从第 41 行开始,到第 68 行结束。

所以在第 43 行,计算机的回合真正开始了。这基本上与上一个练习相同,所以我不会再解释一遍。请注意,计算机正在根据其回合总数决定是否继续掷骰子。

第 70 行结束了包含整个游戏的 do-while 循环,第 72 到 79 行确定并显示赢家。

希望你能够很好地跟上游戏的流程。这相当复杂。

我还要指出,对于这样一个程序来说,每次你放一个左大括号,将其后的所有内容缩进一级是非常重要的。如果你可以从第 47 行的左大括号直观地扫描你的眼睛到第 64 行的右大括号,看看 do-while 循环中有什么,没有什么,这将为你节省很多烦恼。

练习 34:调用一个函数

上一个练习相当复杂。所以我们今天的练习会放松一下。我们将学习如何在 Java 中编写“函数”,以及如何通过“调用”来执行它。10

1 public class ThereAndBackAgain
 2 {
 3     public static void main( String[] args )
 4     {
 5         System.out.println( "Here." );
 6         erebor();
 7         System.out.println( "Back first time." );
 8         erebor();
 9         System.out.println( "Back second time." );
10     }
11 
12     public static void erebor()
13     {
14         System.out.println( "There." );
15     }
16 }

你应该看到什么

Here.
There.
Back first time.
There.
Back second time.

因此,第 5 到 9 行相当无聊,除了在第 6 和第 8 行我们提到了一些叫做“erebor”的东西,你在 Java 中以前没有见过。你知道为什么你没有见过它吗?因为它根本不存在!

跳到第 12 到 15 行,你会注意到我在我们的程序中添加了一些不在main()主体内的东西。通常情况下,public static void main的右大括号几乎在代码的末尾,而它之后的唯一内容就是public class Whatevs的右大括号。但这次不是!

第 12 到 15 行定义了一个名为erebor()的函数。(erebor()这个词在 Java 中没有特别的含义。我们可以将其命名为bilbo()smaug()或者任何我们喜欢的名字。)

这个函数在第 13 行有一个左大括号,就像main()总是有一个左大括号一样。在第 15 行是函数主体的结束,有一个右大括号。所以函数定义从第 12 行开始,到第 15 行结束。

这个函数是做什么的?它在屏幕上打印字符串"There."

10 这是我充满谎言的事情之一。从技术上讲,Java 甚至没有函数。它只有“方法”,这是一个方法,而不是函数。

但这只是一个方法,因为这就是 Java 所拥有的。在任何其他编程语言中,我们写的内容都会被称为函数而不是方法。这是因为方法是面向对象的东西,而这个程序根本不是面向对象的。

因此,尽管从技术上讲是不正确的,我将这种事情称为函数,并且只使用方法这个词。

当我做出的东西实际上像一个方法时。

我的故意错误的词汇只会在你与一个迂腐的 Java 程序员交谈时引起问题,因为他们可能会取笑你。如果发生这种情况,给他们看这个脚注,并问问他们教初学者编程多少年了。我保证这样做比从一开始就向你展示真正的方法,或者现在就这样做并尝试区分“像函数一样运行的方法”和“行为像真正方法的方法”要好。

那么现在让我们回到main(),看看main()体内的函数调用。

第 5 行我们在屏幕上打印字符串"Here."。然后第 6 行你会看到一个“函数调用”。这行代码告诉计算机跳到函数erebor(),运行该函数主体中的所有代码,然后在完成后返回到第 6 行。

所以你看到当我们调用erebor()函数时,字符串"There."会在字符串"Here."之后打印在屏幕上。当计算机运行第 6 行时,程序的执行在main()中暂停,跳过main()中的所有其余代码,跳到第 12 行,运行erebor()函数主体中的所有代码(只有 1 行),然后一旦执行到第 15 行的右花括号,它返回到第 6 行的末尾,恢复main()的执行。接着运行第 7 行。

第 7 行显示屏上显示另一条消息,然后第 8 行有另一个函数调用。函数 erebor 被第二次调用。它在第 8 行暂停了main(),跳下去运行 erebor 的主体(再次打印字符串"There."),然后返回到第 8 行,main()的执行继续。

最后第 9 行在屏幕上打印最后一个字符串。然后执行继续到

main()在第 10 行。当main()结束时,程序也结束。

这很重要,所以我会再说一遍:当main()结束时,程序也结束。即使在class内有很多不同的函数,程序执行也是从main()的第一行开始的。一旦main()的最后一行被执行,程序就停止运行,即使有一些从未被调用的函数。(我们将在下一个练习中看到一个例子。)

学习演练

  1. 删除第 6 行第一个函数调用末尾的括号,使其看起来像这样:
erebor;

编译后会发生什么?(然后把括号放回去。)

  1. 删除第二个函数调用(第 8 行)。你可以直接删除整行,或者在行前加上斜杠,这样编译器会认为它是注释,就像这样:
// erebor();

编译它,但在运行之前,你认为输出会有什么不同?运行它,看看你是否正确。

练习 35:调用函数绘制旗帜

现在你已经了解了如何定义函数和调用函数的绝对基础知识,让我们通过定义十一个函数来进行一些练习!

这个程序中没有零(0)。所有看起来像O的东西都是大写字母 O。还要注意,第 45 行和第 50 行使用的是print()而不是println()

1 import static java.lang.System.*;
 2 
 3 public class OverlyComplexFlag
 4 {
 5     public static void main( String[] args )
 6     {
 7         printTopHalf();
 8 
 9         print48Colons();
10         print48Ohs();
11         print48Colons();
12         print48Ohs();
13         print48Colons();
14         print48Ohs();
15     }
16 
17     public static void print48Colons()
18     {
19         out.println( "|::::::::::::::::::::::::::::::::::::::::::::::::|" );
20     }
21 
22     public static void print48Ohs()
23     {
24         out.println( "|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO|" );
25     }
26 
27     public static void print29Colons()
28     {
29         out.println( "|:::::::::::::::::::::::::::::|" );
30     }
31 
32     public static void printPledge()
33     {
34         out.println( "I pledge allegiance to the flag." );
35     }
36 
37     public static void print29Ohs()
38     {
39         out.println( "|OOOOOOOOOOOOOOOOOOOOOOOOOOOOO|" );
40     }
41 
42     public static void print6Stars()
43     {
44         out.print( "| *  *  *  *  *  * " );
45     }
46 
47     public static void print5Stars()
48     {
49         out.print( "|   *  *  *  *  *  " );
50     }
51 
52     public static void printSixStarLine()
53     {
54         print6Stars();
55         print29Ohs();
56     }
57 
58     public static void printFiveStarLine()
59     {
60         print5Stars();
61         print29Colons();
62     }
63 
64     public static void printTopHalf()
65     {
66         out.println( " ________________________________________________" ); //
1 space then 48 underscores
67         printSixStarLine();
68         printFiveStarLine();
69         printSixStarLine();
70         printFiveStarLine();
71         printSixStarLine();
72         printFiveStarLine();
73         printSixStarLine();
74     }
75 
76 }

你应该看到什么

| * * * * * * |OOOOOOOOOOOOOOOOOOOOOOOOOOOOO|
|  * * * * * |:::::::::::::::::::::::::::::|
| * * * * * * |OOOOOOOOOOOOOOOOOOOOOOOOOOOOO|
|  * * * * * |:::::::::::::::::::::::::::::|
| * * * * * * |OOOOOOOOOOOOOOOOOOOOOOOOOOOOO|
|  * * * * * |:::::::::::::::::::::::::::::|
| * * * * * * |OOOOOOOOOOOOOOOOOOOOOOOOOOOOO|
|::::::::::::::::::::::::::::::::::::::::::::::::|
|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO|
|::::::::::::::::::::::::::::::::::::::::::::::::|
|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO|
|::::::::::::::::::::::::::::::::::::::::::::::::|
|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO|

这个练习很荒谬。没有任何值得尊重的程序员会以这种方式在屏幕上绘制旗帜。如果编写这个程序感觉有点傻,那没关系。但是函数很重要,我更喜欢从你实际能理解的愚蠢例子开始,而不是从太难跟随的现实例子开始。

那么我们如何追踪执行这样的程序呢?我们从开始开始:main()的第一行。在第 7 行,main 做的第一件事是调用函数printTopHalf()。所以 main 被暂停,执行跳到printTopHalf()函数的第一行,即第 66 行。

printTopHalf 的第一件事是在屏幕上打印一堆下划线,这将是我们旗帜的顶部。之后,执行移动到第 67 行,这是另一个函数调用!所以main() 仍然在暂停之前,等待printTopHalf() 完成,现在printTopHalf() 本身也在暂停,等待printSixStarLine() 完成并返回控制权到这里。

printSixStarLine() 从第 54 行开始,它调用print6Stars() 函数。那个函数(幸运的是)只在屏幕上显示一些东西,所以当print6Stars() 的右大括号出现在第 45 行时,它将控制权返回到printSixStarLine() 的第二行(第 55 行),然后又有一个函数调用。这通过print29Ohs() 函数的主体运行,并返回到第 56 行。然后printSixStarLine() 结束,将控制权返回到第 67 行的末尾。

在这一点上,我认为解释所有的函数调用会比跟随执行路径更加混乱,所以在这里我将按顺序打印所有执行的行号。调用一个函数会增加缩进级别,从该函数返回会减少缩进级别。

5 ­ begin main
6
7 ­ call printTopHalf
    64 ­ begin printTopHalf
        65
        66
        67 ­ call printSixStarLine
            52 ­ begin printSixStarLine
                53
                54 ­ call print6Stars
                    42 ­ begin print6Stars
                        43
                        44
                        45 ­ end print6Stars
                54 ­ resume printSixStarLine
                55 ­ call print29Ohs
                    37 ­ begin print29Ohs
                        38
                        39
                        40 ­ end print29Ohs
                55 ­ resume printSixStarLine
                56 ­ end printSixStarLine
         67 ­ resume printTopHalf
             68 ­ call printFiveStarLine
                 58 ­ begin printFiveStarLine
                     59
                     60 ­ call print5Stars
                         47 ­ begin print5Stars
                             48
                             49
                             50 ­ end print5Stars
                     60 ­ resume printFiveStarLine
                     61 ­ call print29Colons
                         27 ­ begin print29Colons
                             28
                             29
                             30 ­ end print29Colons
                     61 ­ resume printFiveStarLine
                     62 ­ end printFiveStarLine
             68 ­ resume printTopHalf
             69 ­ call printSixStarLine
            52 ­ begin printSixStarLine
                53
                54 ­ call print6Stars
                    42 ­ begin print6Stars
                        43
                        44
                        45 ­ end print6Stars
                54 ­ resume printSixStarLine
                55 ­ call print29Ohs
                    37 ­ begin print29Ohs
                        38
                        39
                        40 ­ end print29Ohs
                55 ­ resume printSixStarLine
                56 ­ end printSixStarLine
         69 ­ resume printTopHalf
             70 ­ call printFiveStarLine
                 58 ­ begin printFiveStarLine
                     59
                     60 ­ call print5Stars
                         47 ­ begin print5Stars
                             48
                             49
                             50 ­ end print5Stars
                     60 ­ resume printFiveStarLine
                     61 ­ call print29Colons
                         27 ­ begin print29Colons
                             28
                             29
                             30 ­ end print29Colons
                     61 ­ resume printFiveStarLine
                     62 ­ end printFiveStarLine
         70 ­ resume printTopHalf
             71 ­ call printSixStarLine
            52 ­ begin printSixStarLine
                53
                54 ­ call print6Stars
                    42 ­ begin print6Stars
                        43
                        44
                        45 ­ end print6Stars
                54 ­ resume printSixStarLine
                55 ­ call print29Ohs
                    37 ­ begin print29Ohs
                        38
                        39
                        40 ­ end print29Ohs
                55 ­ resume printSixStarLine
                56 ­ end printSixStarLine
         71 ­ resume printTopHalf
             72 ­ call printFiveStarLine
                 58 ­ begin printFiveStarLine
                     59
                     60 ­ call print5Stars
                         47 ­ begin print5Stars
                             48
                             49
                             50 ­ end print5Stars
                     60 ­ resume printFiveStarLine
                     61 ­ call print29Colons
                         27 ­ begin print29Colons
                             28
                             29
                             30 ­ end print29Colons
                     61 ­ resume printFiveStarLine
                     62 ­ end printFiveStarLine
         72 ­ resume printTopHalf
             73 ­ call printSixStarLine
            52 ­ begin printSixStarLine
                53
                54 ­ call print6Stars
                    42 ­ begin print6Stars
                        43
                        44
                        45 ­ end print6Stars
                54 ­ resume printSixStarLine
                55 ­ call print29Ohs
                    37 ­ begin print29Ohs
                        38
                        39
                        40 ­ end print29Ohs
                55 ­ resume printSixStarLine
                56 ­ end printSixStarLine
         73 ­ resume printTopHalf
             74 ­ end printTopHalf
     7 ­ resume main
     8
     9 ­ call print48Colons
         17 ­ begin print48Colons
             18
             19
             20 ­ end print48Colons
     9 ­ resume main
     10 ­ call print48Ohs
         22 ­ begin print48Ohs
             23
             24
             25 ­ end print48Ohs
     10 ­ resume main
     11 ­ call print48Colons
         17 ­ begin print48Colons
             18
             19
             20 ­ end print48Colons
     11 ­ resume main
     12 ­ call print48Ohs
         22 ­ begin print48Ohs
             23
             24
             25 ­ end print48Ohs
     12 ­ resume main
     13 ­ call print48Colons
         17 ­ begin print48Colons
             18
             19
             20 ­ end print48Colons
     13 ­ resume main
     14 ­ call print48Ohs
         22 ­ begin print48Ohs
             23
             24
             25 ­ end print48Ohs
     14 ­ resume main

天哪!如果你能成功地追踪到这一点,那么你就已经在成为一个称职的程序员的路上了。

学习演练

  1. 你真的没有完全追踪整个程序,是吗?好吧,回去做吧。这本书不叫“学习 Java 的一半”,对吧?打印出代码,拿起一支铅笔,在一个函数调用其他地方时画一条线,当函数返回时画一条线。完成后,它应该看起来有点像一盘石墨意面!
  2. 在 32 到 35 行,你会找到一个名为printPledge() 的函数的定义。但是这个函数的输出从来没有出现过。为什么?在main() 的末尾添加一个函数调用来运行这个函数,以便它出现在旗帜下面。
    (尽管这个程序很邪恶,但我对那面旗帜感到非常自豪。如果你用尺子测量一切的尺寸,你会发现我的旗帜与真正的美国国旗的尺寸几乎一样。我实际上花了很长时间测量和调整一切。)

练习 36:使用函数显示骰子

上一个练习在一个函数实际上使事情变得更糟的程序中使用了函数。所以今天我们准备看一个情况,使用函数实际上使程序变得更好。

Yacht 是一个古老的骰子游戏,后来被修改为商业游戏 Yahtzee。它涉及一次掷五个骰子,并为各种组合赚取积分。最罕见的组合是“游艇”,当五个骰子都显示相同的数字时。

这个程序不做任何其他的评分,它只是掷五个骰子,直到它们都相同。(计算机速度很快,所以即使这需要很多次尝试,也不会花费很长时间。)

1 public class YachtDice
 2 {
 3     public static void main( String[] args )
 4     {
 5         int roll1, roll2, roll3, roll4, roll5;
 6         boolean allTheSame;
 7 
 8         do
 9         {
10             roll1 = 1 + (int)(Math.random()*6);
11             roll2 = 1 + (int)(Math.random()*6);
12             roll3 = 1 + (int)(Math.random()*6);
13             roll4 = 1 + (int)(Math.random()*6);
14             roll5 = 1 + (int)(Math.random()*6);
15             System.out.println("\nYou rolled: " + roll1 + " " + roll2 + " " + 
roll3 + " " + roll4 + " " + roll5);
16             showDice(roll1);
17             showDice(roll2);
18             showDice(roll3);
19             showDice(roll4);
20             showDice(roll5);
21             allTheSame = ( roll1 == roll2 && roll2 == roll3 && roll3 == roll4 
&& roll4 == roll5 );
22 
23         } while ( ! allTheSame );
24         System.out.println("The Yacht!!");
25     }
26 
27     public static void showDice( int roll )
28     {
29         System.out.println("+­­­+");
30         if ( roll == 1 )
31         {
32             System.out.println("|   |");
33             System.out.println("| o |");
34             System.out.println("|   |");
35         }
36         else if ( roll == 2 )
37         {
38             System.out.println("|o  |");
39             System.out.println("|   |");
40             System.out.println("|  o|");
41         }
42         else if ( roll == 3 )
43         {
44             System.out.println("|o  |");
45             System.out.println("| o |");
46             System.out.println("|  o|");
47         }
48         else if ( roll == 4 )
49         {
50             System.out.println("|o o|");
51             System.out.println("|   |");
52             System.out.println("|o o|");
53         }
54         else if ( roll == 5 )
55         {
56             System.out.println("|o o|");
57             System.out.println("| o |");
58             System.out.println("|o o|");
59         }
60         else if ( roll == 6 )
61         {
62             System.out.println("|o o|");
63             System.out.println("|o o|");
64             System.out.println("|o o|");
65         }
66         System.out.println("+­­­+");
67     }
68 }

你应该看到什么

You rolled:
+­­­+
|o o|
| |
|o o|
+­­­+
+­­­+
|o o|
|o o|
|o o|
+­­­+
+­­­+
|o o|
| o |
|o o|
+­­­+
+­­­+
|o o|
| o |
|o o|
+­­­+
+­­­+
|o o|
|o o|
|o o|
+­­­+
4
6
5
5
6
You rolled:
+­­­+
|o |
| |
| o|
+­­­+
+­­­+
|o |
| |
| o|
+­­­+
+­­­+
|o o|
| o |
|o o|
2
2
5
6
6
+­­­+
+­­­+
|o o|
|o o|
|o o|
+­­­+
+­­­+
|o o|
|o o|
|o o|
+­­­+
...etc
You rolled: 5 5 5 5 5
+­­­+
|o o|
| o |
|o o|
+­­­+
+­­­+
|o o|
| o |
|o o|
+­­­+
+­­­+
|o o|
| o |
|o o|
+­­­+
+­­­+
|o o|
| o |
|o o|
+­­­+
+­­­+
|o o|
| o |
|o o|
+­­­+
The Yacht!!

除了第 21 行的花哨的布尔表达式之外,这个练习中有一个名为showDice 的单个函数。

在 10 到 14 行,我们选择五个随机数(每个数从 1 到 6)并将结果存储到五个整数变量roll1roll5中。

我们想要使用一些if 语句在屏幕上显示骰子的值,但我们不想写五次相同的if 语句(因为变量是不同的)。解决方案是创建一个带参数的函数。

在第 27 行,你看到了showDice 函数定义的开始。在名称(或“标识符”)showDice 后面,有一组括号,在它们之间声明了一个变量!这个变量叫做“参数”。showDice 函数有一个参数。这个参数是一个整数。它的名字叫 roll。

这意味着每当你为showDice写一个函数调用时,你不能只写函数的名称和括号,比如showDice()。它不会编译。你必须在括号中包含一个整数值(这称为“参数”),要么是一个变量,要么是一个简化为整数值的表达式。

这里有一些例子。

showDice;                       // NO  (without parens this refers to a variable not a function call)
showDice();                     // NO  (function call must have one argument, not zero)
showDice(1);                    // YES (one argument is just right)
showDice(4);                    // YES
showDice(1+2);                  // YES
showDice(roll2);                // YES
showDice(roll5);                // YES
showDice( (roll3+roll4) / 2 );  // YES (strange but legal)
showDice(17);                   // YES (although it won't show a proper dice picture)
showDice(3, 4);                 // NO  (function call must have one argument, not two)
showDice(2.0);                  // NO  (argument must be an integer, not a double)
showDice("two");                // NO  (argument must be an integer, not a String)
showDice(false);                // NO  (argument must be an integer, not a Boolean)

在所有情况下,参数的值的副本都存储在参数中。因此,如果你这样调用函数 showDice(3);,那么函数被调用,值3被存储到参数 roll 中。所以到第 29 行,参数变量 roll 已经被声明并初始化为值3

如果我们使用变量调用函数,比如 showDice(roll2); 那么在函数体执行之前,函数被调用并且当前在 roll2 中的任何值的副本将被存储到参数变量 roll 中。

因此,在第 16 行,showDice函数被执行,roll 将被设置为 roll1 中的任何值。

然后在第 17 行,showDice再次被调用,但这次 roll 将被设置为 roll1 中的任何值。

roll2。第 18 行调用showDice,同时将其参数设置为 roll3 的值。等等。

这样我们基本上运行了相同的代码块五次,但用不同的变量替换

每次掷骰子。这为我们节省了很多代码。

为了对比,我还写了一个简化的两个骰子版本的练习,而不使用函数。请注意,我必须重复完全相同的if语句序列两次:每个变量一次。

还要注意的是,虽然定义函数比只是复制和粘贴要多一点工作

1 public class YachtDiceNoFunctions
 2 {
 3     public static void main( String[] args )
 4     {
 5         int roll1, roll2;
 6 
 7         do
 8         {
 9             roll1 = 1 + (int)(Math.random()*6);
10             roll2 = 1 + (int)(Math.random()*6);
11             int total = roll1 + roll2;
12             System.out.println("\nYou rolled a " + roll1 + " and a " + roll2);
13             System.out.println("+­­­+");
14             if ( roll1 == 1 )
15             {
16                 System.out.println("|   |");
17                 System.out.println("| o |");
18                 System.out.println("|   |");
19             }
20             else if ( roll1 == 2 )
21             {
22                 System.out.println("|o  |");
23                 System.out.println("|   |");
24                 System.out.println("|  o|");
25             }
26             else if ( roll1 == 3 )
27             {
28                 System.out.println("|o  |");
29                 System.out.println("| o |");
30                 System.out.println("|  o|");
31             }
32             else if ( roll1 == 4 )
33             {
34                 System.out.println("|o o|");
35                 System.out.println("|   |");
36                 System.out.println("|o o|");
37             }
38             else if ( roll1 == 5 )
39             {
40                 System.out.println("|o o|");
41                 System.out.println("| o |");
42                 System.out.println("|o o|");
43             }
44             else if ( roll1 == 6 )
45             {
46                 System.out.println("|o o|");
47                 System.out.println("|o o|");
48                 System.out.println("|o o|");
49             }
50             System.out.println("+­­­+");
51 
52 
53             System.out.println("+­­­+");
54             if ( roll2 == 1 )
55             {
56                 System.out.println("|   |");
57                 System.out.println("| o |");
58                 System.out.println("|   |");
59             }
60             else if ( roll2 == 2 )
61             {
62                 System.out.println("|o  |");
63                 System.out.println("|   |");
64                 System.out.println("|  o|");
65             }
66             else if ( roll2 == 3 )
67             {
68                 System.out.println("|o  |");
69                 System.out.println("| o |");
70                 System.out.println("|  o|");
71             }
72             else if ( roll2 == 4 )
73             {
74                 System.out.println("|o o|");
75                 System.out.println("|   |");
76                 System.out.println("|o o|");
77             }
78             else if ( roll2 == 5 )
79             {
80                 System.out.println("|o o|");
81                 System.out.println("| o |");
82                 System.out.println("|o o|");
83             }
84             else if ( roll2 == 6 )
85             {
86                 System.out.println("|o o|");
87                 System.out.println("|o o|");
88                 System.out.println("|o o|");
89             }
90             System.out.println("+­­­+");
91 
92             System.out.println("The total is " + total + "\n");
93         } while ( roll1 != roll2 );
94 
95         System.out.println("Doubles!  Nice job.");
96     }
97 }

你应该看到什么

You rolled a 5 and a 4
+­­­+
|o o|
| o |
|o o|
+­­­+
+­­­+
|o o|
|   |
|o o|
+­­­+
The total is 9
You rolled a 6 and a 2
+­­­+
|o o|
|o o|
|o o|
+­­­+
+­­­+
|o  |
|   |
|  o|
+­­­+
The total is 8
You rolled a 2 and a 2
+­­­+
|o  |
|   |
|  o|
+­­­+
+­­­+
|o  |
|   |
|  o|
+­­­+
The total is 4
Doubles!  Nice job.

学习演练

  1. 添加第六个骰子。注意,只需添加一个函数调用就可以轻松显示roll6
相关文章
|
5月前
|
存储 Java Go
笨办法学 Java(四)(3)
笨办法学 Java(四)(3)
33 1
|
5月前
|
存储 Java 索引
笨办法学 Java(四)(2)
笨办法学 Java(四)(2)
35 0
|
5月前
|
存储 Java 编译器
笨办法学 Java(二)(1)
笨办法学 Java(二)(1)
56 0
|
5月前
|
存储 Java
笨办法学 Java(三)(1)
笨办法学 Java(三)(1)
37 0
|
5月前
|
存储 Java 程序员
笨办法学 Java(一)(2)
笨办法学 Java(一)(2)
74 0
|
5月前
|
存储 Java 程序员
笨办法学 Java(三)(3)
笨办法学 Java(三)(3)
91 0
|
5月前
|
存储 Java 程序员
笨办法学 Java(一)(1)
笨办法学 Java(一)
69 0
|
5月前
|
存储 人工智能 网络协议
笨办法学 Java(二)(2)
笨办法学 Java(二)
55 0
|
5月前
|
存储 安全 Java
笨办法学 Java(三)(2)
笨办法学 Java(三)(2)
44 0
|
5月前
|
存储 Java 数据库
笨办法学 Java(四)(1)
笨办法学 Java(四)(1)
50 0