Case Study: Card Shuffling and Dealing Simulation

Case Study Card Shuffling and Dealing Simulation

The examples in the chapter thus far have used arrays containing value-type elements. This section uses random-number generation and an array of reference-type elementsnamely, objects representing playing cardsto develop a class that simulates card shuffling and dealing. This class can then be used to implement applications that play card games. The exercises at the end of the chapter use the techniques developed here to build a poker application.

We first develop class Card (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 the DeckOfCards class (Fig. 8.10), which creates a deck of 52 playing cards in which each element is a Card object. Then we build a test application (Fig. 8.11) that demonstrates class DeckOfCards's card shuffling and dealing capabilities.

Figure 8.9. Card class represents a playing card.

 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
 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 public override string ToString()
17 { 
18  return face + " of " + suit; 
19 } // end method ToString 
20 } // end class Card

Figure 8.10. DeckOfCards class represents a deck of playing cards.

(This item is displayed on pages 349 - 350 in the print version)

 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
 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 string[] faces = { "Ace", "Deuce", "Three", "Four", "Five", "Six",
16  "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" }; 
17 string[] suits = { "Hearts", "Diamonds", "Clubs", "Spades" }; 
18
19 deck = new Card[ NUMBER_OF_CARDS ]; // create array of Card objects
20 currentCard = 0; // set currentCard so first Card dealt is deck[ 0 ]
21 randomNumbers = new Random(); // create random number generator
22
23 // populate deck with Card objects 
24 for ( int count = 0; count < deck.Length; count++ ) 
25  deck[ count ] = 
26  new Card( faces[ count % 13 ], suits[ count / 13 ] );
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 Card temp = deck[ first ]; 43 deck[ first ] = deck[ second ]; 44 deck[ second ] = temp; 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 ( currentCard < deck.Length ) 53 return deck[ currentCard++ ]; // return current Card in array 54 else 55 return null; // return null to indicate that all Cards were dealt 56 } // end method DealCard 57 } // end class DeckOfCards

Figure 8.11. Card shuffling and dealing application.

(This item is displayed on page 351 in the print version)

 1 // Fig. 8.11: DeckOfCardsTest.cs
 2 // Card shuffling and dealing application.
 3 using System;
 4
 5 public class DeckOfCardsTest
 6 {
 7 // execute application
 8 public static void Main( string[] args )
 9 {
10 DeckOfCards myDeckOfCards = new DeckOfCards();
11 myDeckOfCards.Shuffle(); // place Cards in random order
12
13 // print all 52 Cards in the order in which they are dealt
14 for ( int i = 0; i < 13; i++ )
15 {
16 // deal and print 4 Cards
17 Console.WriteLine( "{0,-20}{1,-20}{2,-20}{3,-20}",
18 myDeckOfCards.DealCard(), myDeckOfCards.DealCard(),
19 myDeckOfCards.DealCard(), myDeckOfCards.DealCard() );
20 } // end for
21 } // end Main
22 } // end class DeckOfCardsTest
 
 Ten of Hearts Ace of Diamonds Jack of Spades Queen of Diamonds
 Six of Clubs Seven of Hearts Deuce of Spades Seven of Diamonds
 Queen of Spades King of Hearts Nine of Hearts Deuce of Clubs
 Eight of Clubs Five of Diamonds Three of Hearts Five of Hearts
 Three of Spades Four of Diamonds Six of Hearts Nine of Diamonds
 Queen of Clubs Deuce of Diamonds Queen of Hearts Four of Clubs
 Seven of Spades Four of Hearts Three of Diamonds Seven of Clubs
 Ten of Clubs Ten of Spades Jack of Diamonds Jack of Clubs
 Nine of Clubs Six of Diamonds Eight of Hearts Eight of Spades
 King of Spades Three of Clubs King of Diamonds Six of Spades
 Jack of Hearts Ace of Clubs Five of Spades Nine of Spades
 Deuce of Hearts Five of Clubs Ten of Diamonds Ace of Hearts
 Ace of Spades Four of Spades Eight of Diamonds King of Clubs

Class Card

Class Card (Fig. 8.9) contains two string instance variablesface and suitthat are used to store references to the face value and suit name for a specific Card. The constructor for the class (lines 913) receives two strings that it uses to initialize face and suit. Method ToString (lines 1619) creates a string consisting of the face of the card, the string " of " and the suit of the card. Recall from Chapter 7 that the + operator can be used to concatenate (i.e., combine) several strings to form one larger string. Card's ToString method can be invoked explicitly to obtain a string representation of a Card object (e.g., "Ace of Spades"). The ToString method of an object is called implicitly in many cases when the object is used where a string is expected (e.g., when WriteLine outputs the object with a format item or when the object is concatenated to a string using the + operator). For this behavior to occur, ToString must be declared with the header exactly as shown in line 16 of Fig. 8.9. We will explain the purpose of the override keyword in more detail when we discuss inheritance in Chapter 10.

Class DeckOfCards

Class DeckOfCards (Fig. 8.10) declares an instance-variable array named deck that contains Card objects (line 7). Like simple-type array declarations, the declaration of an array of objects includes the type of the elements in the array, followed by square brackets and the name of the array variable (e.g., Card[] deck). Class DeckOfCards also declares int instance variable currentCard (line 8), representing the next Card to be dealt from the deck array, and named constant NUMBER_OF_CARDS (line 9), indicating the number of Cards in the deck (52).

The class's constructor instantiates the deck array (line 19) to be of size NUMBER_OF_CARDS. When first created, the elements of the deck array are null by default, so the constructor uses a for statement (lines 2426) to fill the deck array with Cards. The for statement initializes control variable count to 0 and loops while count is less than deck.Length, causing count to take on each integer value from 0 to 51 (the indices of the deck array). Each Card is instantiated and initialized with two stringsone from the faces array (which contains the strings "Ace" tHRough "King") and one from the suits array (which contains the strings "Hearts", "Diamonds", "Clubs" and "Spades"). The calculation count % 13 always results in a value from 0 to 12 (the 13 indices of the faces array in lines 1516), and the calculation count/13 always results in a value from 0 to 3 (the four indices of the suits array in line 17). When the deck array is initialized, it contains the Cards with faces "Ace" through "King" in order for each suit.

Method Shuffle (lines 3046) shuffles the Cards in the deck. The method loops through all 52 Cards (array indices 0 to 51). For each Card, a number between 0 and 51 is picked randomly to select another Card. Next, the current Card object and the randomly selected Card object are swapped in the array. This exchange is performed by the three assignments in lines 4244. The extra variable temp temporarily stores one of the two Card objects being swapped. The swap cannot be performed with only the two statements

deck[ first ] = deck[ second ];
deck[ second ] = deck[ first ];

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 losthence, the extra variable temp is needed. After the for loop terminates, the Card objects are randomly ordered. Only 52 swaps are made in a single pass of the entire array, and the array of Card objects is shuffled.

Method DealCard (lines 4956) deals one Card in the array. Recall that currentCard indicates the index of the next Card to be dealt (i.e., the Card at the top of the deck). Thus, line 52 compares currentCard to the length of the deck array. If the deck is not empty (i.e., currentCard is less than 52), line 53 returns the top Card and increments currentCard to prepare for the next call to DealCardotherwise, null is returned.

Shuffling and Dealing Cards

The application of Fig. 8.11 demonstrates the card dealing and shuffling capabilities of class DeckOfCards (Fig. 8.10). Line 10 creates a DeckOfCards object named myDeckOfCards. Recall that the DeckOfCards constructor creates the deck with the 52 Card objects in order by suit and face. Line 11 invokes myDeckOfCards's Shuffle method to rearrange the Card objects. The for statement in lines 1420 deals all 52 Cards in the deck and prints them in four columns of 13 Cards each. Lines 1719 deal and print four Card objects, each obtained by invoking myDeckOfCards's DealCard method. When WriteLine outputs a Card with string formatting, the Card's ToString method (declared in lines 1619 of Fig. 8.9) is invoked implicitly. Because the field width is negative, the result is output left justified in a field of width 20.

foreach Statement

Preface

Index

    Introduction to Computers, the Internet and Visual C#

    Introduction to the Visual C# 2005 Express Edition IDE

    Introduction to C# Applications

    Introduction to Classes and Objects

    Control Statements: Part 1

    Control Statements: Part 2

    Methods: A Deeper Look

    Arrays

    Classes and Objects: A Deeper Look

    Object-Oriented Programming: Inheritance

    Polymorphism, Interfaces & Operator Overloading

    Exception Handling

    Graphical User Interface Concepts: Part 1

    Graphical User Interface Concepts: Part 2

    Multithreading

    Strings, Characters and Regular Expressions

    Graphics and Multimedia

    Files and Streams

    Extensible Markup Language (XML)

    Database, SQL and ADO.NET

    ASP.NET 2.0, Web Forms and Web Controls

    Web Services

    Networking: Streams-Based Sockets and Datagrams

    Searching and Sorting

    Data Structures

    Generics

    Collections

    Appendix A. Operator Precedence Chart

    Appendix B. Number Systems

    Appendix C. Using the Visual Studio 2005 Debugger

    Appendix D. ASCII Character Set

    Appendix E. Unicode®

    Appendix F. Introduction to XHTML: Part 1

    Appendix G. Introduction to XHTML: Part 2

    Appendix H. HTML/XHTML Special Characters

    Appendix I. HTML/XHTML Colors

    Appendix J. ATM Case Study Code

    Appendix K. UML 2: Additional Diagram Types

    Appendix L. Simple Types

    Index



    Visual C# How to Program
    Visual C# 2005 How to Program (2nd Edition)
    ISBN: 0131525239
    EAN: 2147483647
    Year: 2004
    Pages: 600

    Flylib.com © 2008-2020.
    If you may any questions please contact us: flylib@qtcs.net