Path: csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Eric Sosman Newsgroups: comp.lang.java.programmer Subject: Re: Help with Deck of cards assignment and getting it to deal... Date: Sun, 03 Aug 2014 10:23:28 -0400 Organization: A noiseless patient Spider Lines: 119 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Sun, 3 Aug 2014 14:23:29 +0000 (UTC) Injection-Info: mx05.eternal-september.org; posting-host="bd4e1cba8d8592bec5d5ed9e4537fbfd"; logging-data="20564"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/lHxRsL+IvGxgZaby3fdNO" User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.0 In-Reply-To: Cancel-Lock: sha1:NMOuXYNVPUF6VqWsDQjQhS0whdQ= Xref: csiph.com comp.lang.java.programmer:29515 On 8/1/2014 9:16 PM, Scott Dunning wrote: > [...] > //shuffle(n): shuffle the deck > public void shuffle(int n) { > int i, j, k; > for ( k = 0; k < n; k++ ) { > i = (int) ( NEWCARDS * Math.random() ); // Pick 2 random > cards > j = (int) ( NEWCARDS * Math.random() ); // in the deck? > > //swap these randomly picked cards > Card temp = deckOfCards[i]; > deckOfCards[i] = deckOfCards[j]; > deckOfCards[j] = temp; > } > currentCard = 0; // Reset current card to deal > } > } Others have observed that this shuffling procedure is biased, and suggested alternatives. I'd just like to point out that it may not be necessary to shuffle at all! Here's the idea: The fundamental operation is "deal one card" (you can do this N times in succession to deal N cards). Judging by your `currentCard' variable, you plan to shuffle the deck and then march through it in sequence, dealing the first, second, ... card in succession. That will work fine (if you shuffle well). But what if you just left the deck in any old order at all, even "factory-fresh" with all the suits and ranks in order, *but* instead of dealing sequentially you dealt a randomly-chosen card? You'd need to ensure that a card already dealt wouldn't be dealt again (in the Wild West, the presence of two Aces of Spades in a single poker game might well provoke a gunfight), so after dealing the randomly-chosen card you'd need to remove it from the deck. That's a fairly natural idea, though: If you start with a deck of fifty-two cards and deal one of them, you expect to be holding a deck of fifty-one, right? Okay, so this suggests not a `currentCard' variable that marches through a shuffled array, but a `cardCount' variable that keeps track of how many un-dealt cards remain. In a fresh deck this variable would be 52, and it would decrease as cards were plucked out and dealt away. Here's an outline: public class DeckOfCards { private final Card[] cards; private int cardCount; public DeckOfCards() { cards = new Card[52]; // ... fill the array with Cards ... cardCount = 52; } public Card dealOneCard() { // Sanity check: if (cardCount <= 0) { throw new IllegalStateException("no cards left!"); } // Choose the card to deal: int which = (int) (cardCount * Math.random()); Card dealt = cards[which]; // Remove the dealt card from the deck by moving // the last card into the vacated place (this works // even when dealing the last card): cards[which] = cards[cardCount - 1]; // There's one less card than there used to be: --cardCount; return dealt; } // ... other methods ... } (I've written this for clarity; there are ways to tighten it up a little, and Mike Amling has suggested a better way to get a random integer, but I've tried to stick with things you've already shown you're familiar with.) Your assignment says you're supposed to write a shuffle() method, and perhaps your instructor will give you poor marks if you don't. But then you might pacify him with public void shuffle() { if (cardCount != 52) { throw new IllegalStateException( "not playing with a full deck (as promised)!"); } } If he objects that the method is vacuous, your comeback could be that *by using the other methods of DeckOfCards* there's no way to detect the vacuousness! He can create as many decks and deal as many cards as he likes and subject them to every statistical test at his disposal, and although he might uncover problems with Math.random() and so on he will never be able to show that you're not shuffling! ... and *that* is another important aspect of programming, called "encapsulation." The idea is that a class promises to provide various behaviors but does not promise to do so in any particular way. You describe *what* the (exposed) methods of your class will do, but you don't say *how* they'll do it. This means that next week when you think of a better way (like, how to deal a random card without shuffling), you're free to change how you've done things. A short-order cook filling two orders for scrambled eggs needn't reveal whether he cooked two small batches or one big one; all he needs to do is serve up two platefuls by whatever means he finds convenient. If your classes follow a similar philosophy, you'll write better classes. -- esosman@comcast-dot-net.invalid