Java程序设计-洗牌器
我正在尝试编写一个洗牌器,并且我知道我希望洗牌的方法。然而,我不知道最好的面向对象的编写方式。
该方法是一种相当常见的方法,如下所示:
- 为每个键分配一个随机数值,范围在 0 到 2,147,483,647 之间。
- 如果存在重复的键值(极不可能),则扔掉这副牌,然后重新开始。
- 将卡片存储在一个集合中,
- 按每个卡片的键值对集合进行排序
我的问题在于最好的 OOP 编写方式。首先,我想出了一个名为 Card
的对象,其中包含花色值、数字值和随机键值。然后我会有一个名为 Deck
的类,它扩展了 HashSet
,我会将每张卡存储到 HashSet
中,然后按键值对其进行排序。我纠结的地方是,首先“生成”52 个 Card
对象的最有效方法是什么,以及如何对集合进行排序。我会实现接口“SortedSet”吗?如果是这样,我将如何编写比较器?
这是一个相当广泛的问题,更多地基于 OOP 设计实践,但我希望这是一个非常流畅且基于对象的解决方案。
干杯,
蒂姆。
编辑:
感谢大家的帮助。我的解决方案如下:
- 2 个枚举(CardValues、CardSuits),包含 4 个花色和 13 个可能的值
- Card 类,将 CardValue 和 CardSuit 作为构造函数参数。
- 扩展 TreeMap 的 Deck 类
当创建并洗牌新牌组时,我会循环遍历 CardSuit 枚举并创建 Cards,然后在该循环内,我遍历 CardValue 枚举。这将创建卡片,然后生成一个随机密钥并将它们放入 TreeMap 中。
由于总是有很小的机会出现按键重复,因此如果最终的牌组大小不是 52,我会抛出一个新的 InvalidDeckException。
感谢您的建议,我对这个解决方案感到非常满意。
I am trying to write a card shuffler, and I know the method by which I wish to shuffle the cards. However, I am at a loss of the best object-oriented way in which to write it.
The method, a rather common one, is as follows:
- Assign each a random numeric value, between 0 and 2,147,483,647
- If there is a duplicate key value (very unlikely), throw away the deck, and start again.
- Store the cards in a set
- Order the set by each cards key value
My problem lies in the best OOP way to write this. At first I came up with an object called Card
, containing a suit value, a number value and the random key value. Then I would have a class called Deck
that extended a HashSet
, and I would store each card into the HashSet
and then sort it by key value. Where I struggled was, what is the most efficient way to 'generate' the 52 Card
objects in the first place, and how to order the set. Would I implement the interface, 'SortedSet', if so, how would I go about writing the comparators?
Quite a broad question, more based on OOP design practices, but I'd like this to be a really smooth and object based solution.
Cheers,
Tim.
EDIT:
Thanks for the help everyone. My solution was as follows:
- 2 Enums (CardValues, CardSuits), containing the 4 suits and 13 possible values
- Card class, that takes as constructor arguments a CardValue and a CardSuit.
- Deck class that extends a TreeMap
When a new deck is created and shuffled, I loop through the CardSuit Enum and created Cards, then inside that loop, I go through the CardValue Enum. This creates the cards, I then generate a random key and put them in the TreeMap.
As there is always a small chance of key repetition, if the final deck size is not 52, I throw a new InvalidDeckException.
Thanks for the suggestions, I am much happier with this solution.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
使用
TreeMap
,为每张卡生成一个地图中不存在的随机数,并将其插入地图中作为卡的键,完成。地图现在按生成的随机数排序。
另请参阅 http://en.wikipedia.org/wiki/Shuffling#Shuffling_algorithms
请注意这是一种延迟的随机播放方式,只需使用
Collections.shuffle()
即可。Use a
TreeMap
, for each card generate a random number that doesn't exist in the map, and insert it in the map as the key for the card, done.The map is now ordered by the random numbers generated.
See also http://en.wikipedia.org/wiki/Shuffling#Shuffling_algorithms
Note that this is a retarded way to shuffle, just use
Collections.shuffle()
.我写了一些扑克分析的东西。我为所有卡类型创建了一个枚举,其中包含
rank
和value
字段。然后我初始化了所有 52 个卡枚举的可能性。所以是的,我有 52 个枚举定义(以及一个单独的枚举,用于所有可能的 2 张牌起手牌——有时强力是最好的选择),然后我创建了一个
Deck
类,其中有一个
。Enum
类型列表初始化 Deck 就像生成 Enum 的
EnumSet
并将该集合传递给 List 一样简单。然后,您可以将shuffle
方法放在Deck
类上,并让它使用 Deck 的列表。这样做的优点是您的应用程序中只有 52 张卡 - 就像 FlyWeight 模式。
I wrote some poker analysis stuff. I created an Enum for all the card types, with
rank
andvalue
fields. I then initialized all 52 card enum possibilities. So yes, I had 52 enum defs (and a separate enum for all possible 2-card starting hands -- sometimes brute force is the best option)I then created a
Deck
class that had aList
ofEnum<Card>
types.Initializing the Deck is as simple as generating an
EnumSet
of the Enum, and passing that set to a List. You can then put yourshuffle
method on theDeck
class and have it use the list for the Deck.The advantage of this is you only ever have 52 cards in your app -- its like the FlyWeight pattern.
我将卡定义为持有套件和数值的类。卡不应该知道任何相关的随机数。
Deck 是一个包含卡片列表并具有洗牌方法的类,使用可能不需要存储在某处的随机数。
I would define the Card as a class holding the Suite and the number value. The Card shouldn't have any knowledge of the random number associated.
The Deck is a class containing a List of Cards and having the shuffle method, by use of the random numbers which maybe don't need to be stored somewhere.
Card.java:
Deal.java :
输出:
参考:
Card.java:
Deal.java :
Output:
Reference:
http://download .oracle.com/javase/6/docs/api/java/util/Collections.html#shuffle(java.util.List)
有关 java.util.Collections util 类中的 shuffle 方法,请参阅上述文档
}
简单地 使用:-
http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#shuffle(java.util.List)
See the above doc for shuffle method in java.util.Collections util class.
}
and simply use:-
最简单的事情就是为卡片类型分配一个值属性并对其进行排序(面卡 J、Q、K、A->11、12、13、14)。订购套装时,您必须选择一些任意顺序并组织成一个“包”卡片,其中包含一组已排序的每种套装。由于花色永远不会改变,因此包中总是有一组经过排序的梅花、红心、方块和黑桃。
生成卡片?每个包显然必须定义 4 套套装。拥有一个 CardFactory,根据给定的套装生成并返回每个套装的完整集合。工厂只是盲目地生成 2-10 和人头牌并返回排序后的集合。
The easiest thing is just assign a value attribute to the card types and sort on that (face cards J,Q,K,A->11,12,13, 14) . Ordering suits you'd have to pick some arbitrary order and organize into a "Pack" of cards which has a sorted set of each suit. Since the suits never change, the Pack always has a sorted set of each Clubs, Hearts, Diamonds, and Spades.
Generating the cards? Each pack obviously has to define 4 suits. Have a CardFactory that generates and returns a full set for each suit, given the Suit. The Factory would just blindly generate the 2-10 and face cards and return the sorted set.
您不应该进入不特定于给定卡的
Card
类数据。特别是,牌组内的顺序和随机数不是卡牌的属性(无论卡牌位于牌组的哪个位置,它都是相同的)。卡属性应该只是其值和状态(显示/隐藏)。该牌组可以用列表来实现。洗牌只是 Deck 的一种方法。
对于洗牌有几种选择:
1)单独列出随机数并对其进行排序;随机数列表中的每个变化都会在卡列表中再现。问题是您不能使用 List() 已有的排序方法
2) 您添加一个包含 Card 和随机数的中间类(我们称之为 ShufCard),并且:
a) 牌组是一个列表这些中间对象。
b) 对于洗牌,您可以创建一个包含牌组内容的临时列表,洗牌,然后从临时列表中检索纸牌并保持其顺序。像这样的东西:
You should not get into the
Card
class data that is not particular of a given card. In particular, the order inside a deck and the random number is not an attribute of the card (the card is the same no matter where in the deck it is).The card attributes should be just its value and state (shown/hidden). The deck may be implemented with a List. Shuffling would be just a method from Deck.
For shuffling there are several options:
1) you list the random numbers by themselves and order them; each change in the random number list is reproduced in the card list. The issue is that you cannot use the sort methods already available for List()
2) You add an intermediate class (lets call it ShufCard) that contains both a Card and the random number, and either:
a) The deck is a list of these intermediate objects.
b) For shuffling, you create a temporal list with the contents of the decks, shuffle, and then retrieve the cards from the temporal list mantaining its order. Something like: