Case Study: Card Shuffling and Dealing Simulation

Một phần của tài liệu Visual C 2012 How to Program _ www.bit.ly/taiho123 (Trang 340 - 344)

2. When the app executes, another compiler (known as the just-in-time compiler

8.5 Case Study: Card Shuffling and Dealing Simulation

MessageProperty of the Exception Parameter

When lines 22–27 catch the exception, the program displays a message indicating the problem that occurred. Line 24 uses the exception object’sMessage propertyto get the error message that’s stored in the exception object and display it. Once the message is dis- played in this example, the exception is considered handled and the program continues with the next statement after thecatchblock’s closing brace. In this example, the end of theforstatement is reached (line 28), so the program continues with the increment of the control variable in line 16. We use exception handling again in Chapter 10 and Chapter 13 presents a deeper look at exception handling.

8.5 Case Study: Card Shuffling and Dealing Simulation

So far, this chapter’s examples have used arrays of value-type elements. This section uses random-number generation and anarray of reference-type elements—namely,objectsrepre- senting playing cards—to develop a class that simulates card shuffling and dealing. This class can then be used to implement apps that play card games. The exercises at the end of the chapter use the techniques developed here to build a poker app.

We first develop classCard(Fig. 8.9), which represents a playing card that has a face (e.g.,"Ace","Deuce","Three", …,"Jack","Queen","King") and a suit (e.g.,"Hearts",

"Diamonds","Clubs","Spades"). Next, we develop classDeckOfCards(Fig. 8.10), which creates a deck of 52 playing cards in which each element is aCardobject. Then we build an app (Fig. 8.11) that uses classDeckOfCards’s card shuffling and dealing capabilities.

ClassCard

ClassCard(Fig. 8.9) contains twostring instance variables—faceandsuit—that are used to store references to theface valueandsuit namefor a specificCard. The constructor for the class (lines 9–13) receives two strings that it uses to initialize faceandsuit. MethodToString(lines 16–19) creates astringconsisting of thefaceof the card, the

string " of "and thesuitof the card. Recall from Chapter 7 that the+operator can be used to concatenate (i.e., combine) severalstrings to form one largerstring.Card’sTo- Stringmethod can be invokedexplicitlyto obtain a string representation of aCardobject (e.g.,"Ace of Spades"). TheToStringmethod of an object is calledimplicitlyin many cases when the object is used where astringis expected (e.g., whenWriteLineoutputs the object or when the object isconcatenatedto astringusing the+operator). For this behavior to occur,ToStringmust be declared with the header exactly as shown in line 16 of Fig. 8.9. We’ll explain the purpose of theoverridekeyword in more detail when we discuss inheritance in Chapter 11.

1 // Fig. 8.9: Card.cs

2 // Card class represents a playing card.

3 public class Card 4 {

5 private string face; // face of card ("Ace", "Deuce", ...) 6 private string suit; // suit of card ("Hearts", "Diamonds", ...) 7

Fig. 8.9 | Cardclass represents a playing card. (Part 1 of 2.)

ClassDeckOfCards

ClassDeckOfCards(Fig. 8.10) declares an instance-variable nameddeckthat will refer to an array ofCardobjects (line 7). Like simple-type array variable declarations, the declaration of a variable for an array of objects (e.g.,Card[] deck) includes the type of the elements in the array, followed by square brackets and the name of the array variable. ClassDeckOfCardsalso declaresintinstance variablecurrentCard(line 8), representing the nextCardto be dealt from thedeckarray, and named constantNUMBER_OF_CARDS(line 9), indicating the number ofCards in the deck (52).

8 // two-parameter constructor initializes card's face and suit 9 public Card( string cardFace, string cardSuit )

10 {

11 face = cardFace; // initialize face of card 12 suit = cardSuit; // initialize suit of card 13 } // end two-parameter Card constructor

14

15 // return string representation of Card 16

17 18 19

20 } // end class Card

1 // Fig. 8.10: DeckOfCards.cs

2 // DeckOfCards class represents a deck of playing cards.

3 using System;

4

5 public class DeckOfCards 6 {

7 private Card[] deck; // array of Card objects

8 private int currentCard; // index of next Card to be dealt (0-51) 9 private const int NUMBER_OF_CARDS = 52; // constant number of Cards 10 private Random randomNumbers; // random-number generator

11

12 // constructor fills deck of Cards 13 public DeckOfCards()

14 {

15 16 17 18 19

20 currentCard = 0; // set currentCard so deck[ 0 ] is dealt first 21 randomNumbers = new Random(); // create random-number generator 22

Fig. 8.10 | DeckOfCardsclass represents a deck of playing cards. (Part 1 of 2.) Fig. 8.9 | Cardclass represents a playing card. (Part 2 of 2.)

public override string ToString() {

return face + " of " + suit;

} // end method ToString

string[] faces = { "Ace", "Deuce", "Three", "Four", "Five", "Six",

"Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };

string[] suits = { "Hearts", "Diamonds", "Clubs", "Spades" };

deck = new Card[ NUMBER_OF_CARDS ]; // create array of Card objects

8.5 Case Study: Card Shuffling and Dealing Simulation 301

ClassDeckOfCards: Constructor

The class’s constructor instantiates thedeckarray (line 19) to be of sizeNUMBER_OF_CARDS. When first created, the elements of thedeckarray arenullby default, so the constructor uses aforstatement (lines 24–26) to fill thedeckarray with Cards. Theforstatement initializes control variablecountto0and loops whilecountis less thandeck.Length, caus- ingcountto take on each integer value from0to51(the indices of thedeckarray). Each

Cardis instantiated and initialized with twostrings—one from thefacesarray (which contains thestrings"Ace"through"King") and one from thesuitsarray (which con- tains the strings "Hearts", "Diamonds", "Clubs" and "Spades"). The calculation

count % 13always results in a value from0to12(the 13 indices of thefacesarray in lines 15–16), and the calculationcount / 13always results in a value from0to3(the four in- dices of thesuitsarray in line 17). When thedeckarray is initialized, it contains theCards with faces"Ace"through"King"in order for each suit.

23 24 25 26

27 } // end DeckOfCards constructor 28

29 // shuffle deck of Cards with one-pass algorithm 30 public void Shuffle()

31 {

32 // after shuffling, dealing should start at deck[ 0 ] again 33 currentCard = 0; // reinitialize currentCard

34

35 // for each Card, pick another random Card and swap them 36 for ( int first = 0; first < deck.Length; ++first )

37 {

38 // select a random number between 0 and 51

39 int second = randomNumbers.Next( NUMBER_OF_CARDS );

40

41 // swap current Card with randomly selected Card 42

43 44

45 } // end for

46 } // end method Shuffle 47

48 // deal one Card 49 public Card DealCard()

50 {

51 // determine whether Cards remain to be dealt

52 if ( )

53 return deck[ currentCard++ ]; // return current Card in array

54 else

55 return null; // indicate that all Cards were dealt 56 } // end method DealCard

57 } // end class DeckOfCards

Fig. 8.10 | DeckOfCardsclass represents a deck of playing cards. (Part 2 of 2.)

// populate deck with Card objects

for ( int count = 0; count < deck.Length; ++count ) deck[ count ] =

new Card( faces[ count % 13 ], suits[ count / 13 ] );

Card temp = deck[ first ];

deck[ first ] = deck[ second ];

deck[ second ] = temp;

currentCard < deck.Length

ClassDeckOfCards:ShuffleMethod

MethodShuffle(lines 30–46) shuffles theCards in the deck. The method loops through all 52Cards (array indices 0 to 51). For eachCard, a number between0and51is picked randomly to select anotherCard. Next, the currentCardobject and the randomly selected

Cardobject are swapped in the array. This exchange is performed by the three assignments in lines 42–44. The extra variabletemptemporarily stores one of the twoCardobjects be- ing swapped.The swap cannot be performed with only the two statements

If deck[ first ] is the "Ace" of "Spades" and deck[ second ] is the "Queen" of

"Hearts", then after the first assignment, both array elements contain the "Queen" of

"Hearts", and the"Ace"of"Spades"is lost—hence, the extra variabletempis needed. Af- ter theforloop terminates, theCardobjects are randomly ordered. Only 52 swaps are made in a single pass of the entire array, and the array ofCardobjects is shuffled.

Recommendation: Use an Unbiased Shuffling Algorithm

It’s recommended that you use a so-called unbiased shuffling algorithm for real card games. Such an algorithm ensures that all possible shuffled card sequences are equally like- ly to occur. A popular unbiased shuffling algorithm is the Fisher-Yates algorithm—

en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle. This page also shows how to implement the algorithm in several programming languages.

ClassDeckOfCards:DealCardMethod

MethodDealCard(lines 49–56) deals oneCardin the array. Recall thatcurrentCardin- dicates the index of the nextCardto be dealt (i.e., theCardat the top of the deck). Thus, line 52 comparescurrentCardto the length of thedeckarray. If thedeckis not empty (i.e.,currentCardis less than52), line 53 returns the topCardand incrementscurrent-

Cardto prepare for the next call toDealCard—otherwise,nullis returned.

Shuffling and Dealing Cards

The app of Fig. 8.11 demonstrates the card shuffling and dealing capabilities of classDeck-

OfCards(Fig. 8.10). Line 10 creates aDeckOfCardsobject namedmyDeckOfCards. Recall that theDeckOfCardsconstructor creates the deck with the 52Cardobjects in order by suit and face. Line 11 invokesmyDeckOfCards’sShufflemethod to rearrange theCardobjects.

Theforstatement in lines 14–20 deals all 52Cards in the deck and displays them in four columns of 13Cards each. Line 16 deals and displays aCardobject by invokingmyDeckOf-

Cards’sDealCardmethod. WhenConsole.Writeoutputs aCardwithstringformatting, theCard’sToStringmethod (declared in lines 16–19 of Fig. 8.9) is invoked implicitly. Be- cause the field width isnegative, the result is outputleftjustified in a field of width 19.

deck[ first ] = deck[ second ];

deck[ second ] = deck[ first ];

1 // Fig. 8.11: DeckOfCardsTest.cs 2 // Card shuffling and dealing app.

3 using System;

4

Fig. 8.11 | Card shuffling and dealing app. (Part 1 of 2.)

Một phần của tài liệu Visual C 2012 How to Program _ www.bit.ly/taiho123 (Trang 340 - 344)

Tải bản đầy đủ (PDF)

(1.020 trang)