笨办法学 Java(四)(2)

简介: 笨办法学 Java(四)(2)

笨办法学 Java(四)(1)https://developer.aliyun.com/article/1481921


练习 57:一副扑克牌

在这本书结束之前,我需要向你展示如何使用记录数组来模拟一副扑克牌。

1 class Card
 2 {
 3     int value;
 4     String suit;
 5     String name;
 6 
 7     public String toString()
 8     {
 9         return name + " of " + suit;
10     }
11 }
12 
13 public class PickACard
14 {
15     public static void main( String[] args )
16     {
17         Card[] deck = buildDeck();
18         // displayDeck(deck);
19 
20         int chosen = (int)(Math.random()*deck.length);
21         Card picked = deck[chosen];
22 
23         System.out.println("You picked a " + picked + " out of the deck.");
24         System.out.println("In Blackjack your card is worth " + picked.value + " 
points.");
25     }
26 
27     public static Card[] buildDeck()
28     {
29         String[] suits = { "clubs", "diamonds", "hearts", "spades" };
30         String[] names = { "ZERO", "ONE", "two", "three", "four", "five", "six",
31             "seven", "eight", "nine", "ten", "Jack", "Queen", "King", "Ace" };
32 
33         int i = 0;
34         Card[] deck = new Card[52];
35 
36         for ( String s: suits )
37         {
38             for ( int v = 2; v <= 14 ; v++ )
39             {
40                 Card c = new Card();
41                 c.suit = s;
42                 c.name = names[v];
43                 if ( v == 14 )
44                     c.value = 11;
45                 else if ( v > 10 )
46                     c.value = 10;
47                 else
48                     c.value = v;
49 
50                 deck[i] = c;
51                 i++;
52             }
53         }
54         return deck;
55     }
56 
57     public static void displayDeck( Card[] deck )
58     {
59         for ( Card c : deck )
60             System.out.println(c.value + "\t" + c);
61     }
62 }

你应该看到什么

You picked a seven of hearts out of the deck. In Blackjack your card is worth 7 points.

当然,即使这几乎是最后一个练习,我也忍不住加入了一些新东西。你想学点新东西,不是吗?

首先,我在记录中偷偷加了一个函数。(实际上,因为这个函数在一个类中,它不是一个函数,而是一个“方法”。)

这个方法被命名为 toString。它没有参数,并返回一个String。在这个方法的主体中,我们通过连接名称字段、花色字段和单词“of”来创建一个字符串。这个方法不需要任何参数,因为它可以访问记录的字段。(事实上,这就是它成为“方法”而不是“函数”的原因。)

否则,Card记录应该是你期望的:它有卡的值(2-11)、花色名称和卡本身的名称的字段。

在第 17 到 24 行,你可以看到main(),它真的很短。第 17 行声明了一个卡片数组,并使用buildDeck()函数的返回值进行初始化。

第 18 行被注释掉了,但当我最初编写这个程序时,我使用了displayDeck()

确保buildDeck()函数是否正常工作。

第 20 行选择了一个介于0deck.length - 1之间的随机数。你可能会注意到这恰好是数组中合法索引的范围,这不是巧合。

实际上,你也可以说第 20 行选择了数组中的一个随机索引,或者第 20 行随机选择了数组的一个槽位。

然后在第 21 行,我们声明了一个新的 Card 变量picked,并给它一个从数组中随机选择的值。

第 23 行看起来相当无聊,但实际上发生了魔法。picked是什么类型的变量?它是一张卡。通常当你尝试像这样在屏幕上打印整个记录时,Java 不知道你想要打印哪些字段或以什么顺序打印,所以它只是在屏幕上打印垃圾。(你在上一个练习的学习中看到了吧?)

但是,如果你在记录中提供了一个名为toString()的方法,它返回一个String并且没有参数,那么在这种情况下,Java 将在幕后调用该方法。它将获取返回值并打印出来,而不是垃圾。

因此,第 23 行将在屏幕上打印出运行所选卡的toString()方法的结果。相比之下,第 24 行确实很无聊。它打印出所选卡的值字段。

在我们开始buildDeck(),这是这个练习中最复杂的部分之前,让我们跳到displayDeck()函数。displayDeck()期望你传入一个Card数组作为参数。

然后在第 59 行,我们看到了一些我们在前几个练习中没有见过的东西:一个 foreach 循环。这表示“对于牌组中的每张卡……”由于这个for循环的主体中只有一行代码,我省略了花括号。

第 60 行显示了当前卡片的值,一个制表符,然后调用toString()的结果。

代表 Card c的方法。

好吧,让我们来解决这个buildDeck()函数。buildDeck()不需要任何参数,因为它只是从无中创建牌组。不过它确实返回一个值:一组卡片。

在第 29 到 31 行,我们创建了两个字符串数组。第一个(第 29 行)包含了花色的名称。第二个包含了卡片的名称。

你可能会注意到我有一张叫做"ZERO"的卡片,另一张叫做"ONE"的卡片。为什么?这是为了我可以把这个数组当作“查找表”来使用。我将写我的循环,使得我的卡片值从214,我希望单词"two"在这个数组中的索引是2。所以我需要把一些字符串放到槽位01中来占用空间。

最初我只是放了两个空字符串,如下所示:

String[] names = { "", "", "two", "three", "four", "five", "six",

…但后来我担心如果我的代码有 bug,那么很难判断是没有打印任何内容还是names[0](或names[1])的值。因此,我为这两个索引放入了单词,但将它们全部大写,这样如果它们被打印出来,我就会注意到。

在第 33 行,我们创建了 i,它将跟踪下一个需要放入卡片的索引。第 34 行定义了我们的 52 张卡片的数组(从 0 到 51 索引)。

第 36 行是另一个 foreach 循环。变量 s 将被设置为"clubs",然后

“方块”,然后“红心”,最后“黑桃”。

第 38 行是另一个for循环,但这个循环是嵌套的。记住这意味着这个循环将进行

在外部循环改变 s 的值之前,v 会从 2 到 14 变化。

第 40 行定义了一个名为 c 的 Card。在第 41 行,我们将这张卡的花色字段设置为当前 s 中的任何值(一开始是"clubs")。

根据循环的次数,v 将是 2 到 14 之间的某个值,所以在第 42 行,我们使用 v 作为 names 数组的索引。也就是说,当 v 是 5 时,我们进入数组的第六个位置,那里会找到字符串"five"。我们将这个值的副本放入当前卡片的名称字段。

第 43 到 48 行将一个从 2 到 11 的整数存储到当前卡片的值字段中。我们需要 v 从 2 到 14 进行查找表,但现在已经完成了,我们需要确保没有卡片的值为 12 到 14。

第 14 张卡是 A,所以我们使用 11 作为卡的值。然后第 11、12 和 13 张卡是花牌,所以它们的卡值都是 10。其他卡的值都可以不变。

最后,我们将这张卡存储到deck的下一个可用槽中(用i索引),并使i增加 1。

当嵌套循环结束时,我们已经成功创建了标准牌组中的所有 52 张卡,并为它们赋予了与二十一点中使用方式相匹配的卡值。如果您想要确保,可以取消注释第 18 行上的displayDeck()调用。

buildDeck()的最后一步是return现在已经填满的 Cards 数组,这样它就可以存储到main()第 17 行的 deck 变量中。

学习演练

  1. 添加一个名为shuffleDeck()的函数。它应该以一组卡片的数组作为参数,并返回一组卡片。一种洗牌的方法是从 0 到 51 选择两个随机数,并“交换”这些槽中的卡片。然后将该代码放入一个重复大约 1000 次的循环中。这有点难以做到正确。

练习 58:最终项目-文本冒险游戏

如果您已经完成了到目前为止的所有练习,那么您应该准备好进行这个最终项目了。它比您之前做过的任何练习都要长,但比最近几个练习并不难。

您的最终练习是基于文本的冒险游戏引擎。通过引擎,我的意思是代码对冒险本身一无所知;游戏的进行完全取决于文件中的内容。更改文件就会改变游戏的进行。

所以首先要下载游戏数据文件的副本,并将其保存到与您要放置代码的相同文件夹中。

1 import java.util.Scanner;
  2 
  3 class Room
  4 {
  5     int roomNumber;
  6     String roomName;
  7     String description;
  8     int numExits;
  9     String[] exits = new String[10];
 10     int[] destinations = new int[10];
 11 }
 12 
 13 public class TextAdventureFinal
 14 {
 15     public static void main( String[] args )
 16     {
 17         Scanner keyboard = new Scanner(System.in);
 18 
 19         // initialize rooms from file
 20         Room[] rooms = loadRoomsFromFile("text­adventure­rooms.txt");
 21 
 22         // showAllRooms(rooms); // for debugging
 23 
 24         // Okay, so let's play the game!
 25         int currentRoom = 0;
 26         String ans;
 27         while ( currentRoom >= 0 )
 28         {
 29             Room cur = rooms[currentRoom];
 30             System.out.print( cur.description );
 31             System.out.print("> ");
 32             ans = keyboard.nextLine();
 33 
 34             // See if what they typed matches any of our exit names
 35             boolean found = false;
 36             for ( int i=0; i<cur.numExits; i++ )
 37             {
 38                 if ( cur.exits[i].equals(ans) )
 39                 {
 40                     found = true;
 41                     // if so, change our next room to that exit's room number
 42                     currentRoom = cur.destinations[i];
 43                 }
 44             }
 45             if ( ! found )
 46                 System.out.println("Sorry, I don't understand.");
 47         }
 48 
 49     }
 50 
 51     public static Room[] loadRoomsFromFile( String filename )
 52     {
 53         Scanner file = null;
 54         try
 55         {
 56             file = new Scanner(new java.io.File(filename));
 57         }
 58         catch ( java.io.IOException e )
 59         {
 60             System.err.println("Sorry, I can't read from the file '" + 
filename + "'.");
 61             System.exit(1);
 62         }
 63 
 64         int numRooms = file.nextInt();
 65         Room[] rooms = new Room[numRooms];
 66 
 67         // initialize rooms from file
 68         int roomNum = 0;
 69         while ( file.hasNext() )
 70         {
 71             Room r = getRoom(file);
 72             if ( r.roomNumber != roomNum )
 73             {
 74                 System.err.println("Reading room # " + r.roomNumber + ", but 
" + roomNum + " was expected.");
 75                 System.exit(2);
 76             }
 77             rooms[roomNum] = r;
 78             roomNum++;
 79         }
 80         file.close();
 81 
 82         return rooms;
 83     }
 84 
 85     public static void showAllRooms( Room[] rooms )
 86     {
 87         for ( Room r : rooms )
 88         {
 89             String exitString = "";
 90             for ( int i=0; i<r.numExits; i++ )
 91                 exitString += "\t" + r.exits[i] + " (" + r.destinations[i] + 
")";
 92             System.out.println( r.roomNumber + ") " + r.roomName + "\n" + 
exitString );
 93         }
 94     }
 95 
 96     public static Room getRoom( Scanner f )
 97     {
 98         // any rooms left in the file?
 99         if ( ! f.hasNextInt() )
100             return null;
101 
102         Room r = new Room();
103         String line;
104 
105         // read in the room # for error­checking later
106         r.roomNumber = f.nextInt();
107         f.nextLine();   // skip "\n" after room #
108 
109         r.roomName = f.nextLine();
110 
111         // read in the room's description
112         r.description = "";
113         while ( true )
114         {
115             line = f.nextLine();
116             if ( line.equals("%%") )
117                 break;
118             r.description += line + "\n";
119         }
120 
121         // finally, we'll read in the exits
122         int i = 0;
123         while ( true )
124         {
125             line = f.nextLine();
126             if ( line.equals("%%") )
127                 break;
128             String[] parts = line.split(":");
129             r.exits[i] = parts[0];
130             r.destinations[i] = Integer.parseInt(parts[1]);
131             i++;
132         }
133         r.numExits = i;
134 
135         // should be done; return the Room
136         return r;
137     }
138 
139 }


笨办法学 Java(四)(3)https://developer.aliyun.com/article/1481924

相关文章
|
5月前
|
Java C++
Java和C++的一些区别
Java和C++的一些区别
|
6月前
|
存储 Java Go
笨办法学 Java(四)(3)
笨办法学 Java(四)(3)
34 1
|
6月前
|
存储 Java
笨办法学 Java(三)(1)
笨办法学 Java(三)(1)
39 0
|
6月前
|
存储 人工智能 网络协议
笨办法学 Java(二)(2)
笨办法学 Java(二)
57 0
|
6月前
|
存储 Java 程序员
笨办法学 Java(三)(3)
笨办法学 Java(三)(3)
96 0
|
6月前
|
存储 Java 程序员
笨办法学 Java(一)(2)
笨办法学 Java(一)(2)
76 0
|
6月前
|
存储 Java 数据库
笨办法学 Java(四)(1)
笨办法学 Java(四)(1)
52 0
|
6月前
|
存储 安全 Java
笨办法学 Java(三)(2)
笨办法学 Java(三)(2)
46 0
|
6月前
|
存储 Java 程序员
笨办法学 Java(二)(3)
笨办法学 Java(二)(3)
54 0
|
6月前
|
存储 Java 编译器
笨办法学 Java(二)(1)
笨办法学 Java(二)(1)
57 0
下一篇
无影云桌面