Card Shuffling and Dealing Simulation
In this section, we use random-number generation to develop a program that simulates card shuffling and dealing. These techniques can form the basis of programs that implement specific card games. We include several exercises at the end of this chapter that require card shuffling and dealing capabilities.
Class Card (Fig. 16.16) contains two string instance variablesface and suitthat store references to the face value and suit name of a specific card. The constructor for the class 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 and the suit of the card to identify the card when it is dealt.
Figure 16.16. Card class.
(This item is displayed on page 791 in the print version)
1 // Fig. 16.16: Card.cs 2 // Stores suit and face information on each card. 3 using System; 4 5 public class Card 6 { 7 private string face; 8 private string suit; 9 10 public Card( string faceValue, string suitValue ) 11 { 12 face = faceValue; 13 suit = suitValue; 14 } // end constructor 15 16 public override string ToString() 17 { 18 return face + " of " + suit; 19 } // end method ToString 20 } // end class Card |
We develop the DeckForm application (Fig. 16.17), which creates a deck of 52 playing cards, using Card objects. Users can deal each card by clicking the Deal Card button. Each dealt card is displayed in a Label. Users can also shuffle the deck at any time by clicking the Shuffle Cards button.
Figure 16.17. Card shuffling and dealing simulation.
(This item is displayed on pages 791 - 794 in the print version)
1 // Fig. 16.17: DeckForm.cs 2 // Simulating card shuffling and dealing. 3 using System; 4 using System.Windows.Forms; 5 6 public partial class DeckForm : Form 7 { 8 private Card[] deck = new Card[ 52 ]; // deak of 52 cards 9 private int currentCard; // count which card was just dealt 10 11 // default constructor 12 public DeckForm() 13 { 14 // Required for Windows Form Designer support 15 InitializeComponent(); 16 } // end constructor 17 18 // handles form at load time 19 private void DeckForm_Load( object sender, EventArgs e ) 20 { 21 string[] faces = { "Ace", "Deuce", "Three", "Four", "Five", 22 "Six", "Seven", "Eight", "Nine", "Ten", 23 "Jack", "Queen", "King" }; 24 string[] suits = { "Hearts", "Diamonds", "Clubs", "Spades" }; 25 26 currentCard = -1; // no cards have been dealt 27 28 // initialize deck 29 for ( int i = 0; i < deck.Length; i++ ) 30 deck[ i ] = new Card( faces[ i % 13 ], suits[ i / 13 ] ); 31 } // end method DeckForm_Load 32 33 // handles dealButton Click 34 private void dealButton_Click( object sender, EventArgs e ) 35 { 36 Card dealt = DealCard(); 37 38 // if dealt card is null, then no cards left 39 // player must shuffle cards 40 if ( dealt != null ) 41 { 42 displayLabel.Text = dealt.ToString(); 43 statusLabel.Text = "Card #: " + currentCard; 44 } // end if 45 else 46 { 47 displayLabel.Text = "NO MORE CARDS TO DEAL"; 48 statusLabel.Text = "Shuffle cards to continue"; 49 } // end else 50 } // end method dealButton_Click 51 52 // shuffle cards 53 private void Shuffle() 54 { 55 Random randomNumber = new Random(); 56 Card temporaryValue; 57 58 currentCard = -1; 59 60 // swap each card with randomly selected card (0-51) 61 for ( int i = 0; i < deck.Length; i++ ) 62 { 63 int j = randomNumber.Next( 52 ); 64 65 // swap cards 66 temporaryValue = deck[ i ]; 67 deck[ i ] = deck[ j ]; 68 deck[ j ] = temporaryValue; 69 } // end for 70 71 dealButton.Enabled = true; // shuffled deck can now deal cards 72 } // end method Shuffle 73 74 // deal a card if the deck is not empty 75 private Card DealCard() 76 { 77 // if there is a card to deal then deal it 78 // otherwise signal that cards need to be shuffled by 79 // disabling dealButton and returning null 80 if ( currentCard + 1 < deck.Length ) 81 { 82 currentCard++; // increment count 83 return deck[ currentCard ]; // return new card 84 } // end if 85 else 86 { 87 dealButton.Enabled = false; // empty deck cannot deal cards 88 return null; // do not return a card 89 } // end else 90 } // end method DealCard 91 92 // handles shuffleButton Click 93 private void shuffleButton_Click( object sender, EventArgs e ) 94 { 95 displayLabel.Text = "SHUFFLING..."; 96 Shuffle(); 97 displayLabel.Text = "DECK IS SHUFFLED"; 98 } // end method shuffleButton_Click 99 } // end class DeckForm (a) (b) (c) (d) |
Method DeckForm_Load (lines 1931 of Fig. 16.17) uses a for statement (lines 2930) to fill the deck array with Cards. Note that each Card is instantiated and initialized with two stringsone from the faces array (strings "Ace" tHRough "King") and one from the suits array ("Hearts", "Diamonds", "Clubs" or "Spades"). The calculation i % 13 always results in a value from 0 to 12 (the thirteen subscripts of the faces array), and the calculation i/13 always results in a value from 0 to 3 (the four subscripts in the suits array). The initialized deck array contains the cards with faces Ace through King for each suit.
When the user clicks the Deal Card button, event handler dealButton_Click (lines 3450) invokes method DealCard (defined in lines 7590) to get the next card in the deck array. If the deck is not empty, the method returns a Card object reference; otherwise, it returns null. If the reference is not null, lines 4243 display the Card in displayLabel and display the card number in statusLabel.
If DealCard returns null, the string "NO MORE CARDS TO DEAL" is displayed in displayLabel, and the string "Shuffle cards to continue" is displayed in statusLabel.
When the user clicks the Shuffle Cards button, event handler shuffleButton_Click (lines 9398) invokes method Shuffle (defined on lines 5372) to shuffle the cards. The method loops through all 52 cards (array subscripts 051). For each card, the method randomly picks a number in the range 051. Then the current Card object and the randomly selected Card object are swapped in the array. To shuffle the cards, method Shuffle makes a total of only 52 swaps during a single pass of the entire array. When the shuffling is complete, displayLabel displays the string "DECK IS SHUFFLED".