我正在为扑克游戏建模,我有一点设计疑问:
我有一个PokerHand
,由5 PokerCard
组成。 Straight
,ThreeOfAKind
,Poker
等应该是PokerHand
的子类吗?或者它们应该是PokerHand
方法返回的符号,它计算它是什么样的手?
我对PokerHand
进行子类化的理由是,它会让检查胜利者的手更容易,更快,但我不确定这是好工程......
这里有适合的设计模式吗?
谢谢!
答案 0 :(得分:3)
上个学期,我不得不用Java作为家庭作业设计这样一个系统。虽然需要我们使用责任链模式来检查手,我很确定这是一个解决问题的方法,而且大多只是将模式插入作业的方法。
如果我不得不在没有责任链模式的情况下重做它,并使用更健全,更有凝聚力的策略列表,我会使用如下设计。
会有Card
类,有'颜色'(黑桃,棍棒,钻石,心形)和数字(都是enum
s);一个Hand
课程,可以持有5张卡片(或者只有n
张卡片;实现HandRank
接口的抽象Comparable<HandRank>
类,以及每种类型的手(两种,三种,直,等)的子类,每种都可以与另一种相媲美(这样{ {1}}优于StraightFlush
);和基类TwoOfAKind
。这个AbstractHandAnalyzer
会有AbstractHandAnalyzer
方法返回Analyze(Hand)
个对象。
现在,您为HandRank
每个AbstractHandAnalyzer
子类创建一个子类。如果手匹配,那些子类检查给定的手并返回HandRank
实例(例如,如果HandRank
发现你有两个国王,它会返回TwoOfAKindAnalyzer
,告诉它找到两个国王,并在以后的比较中保存踢球者以防万一。)
分析一只手的所有工作就是按顺序排列一个手动分析器列表(所以你从同花顺开始),然后在手上运行每个分析器直到一个匹配,不再返回{ {1}}。
这里的重要部分是将扑克牌与队伍本身分开。对于大多数语言(尽管Smalltalk可能不是这种情况),如果你构造一个TwoOfAKindRank
对象,你就不能神奇地将它变形为另一个类,所以继承null
来限定等级可能很难取决于在你的对象实例化方案中,如果手是可变的(一些扑克变种允许交换卡),可以使其成为接下来的不可能。这种方法允许您重用Hand
并轻松实现各种分析器。
答案 1 :(得分:2)
PokerHand
应该有一个方法:GetCombination
,返回enum
或object
。手是手,如果玩家有Straigt,它不会添加任何新的行为或状态。所以组合可以通过卡片来计算。
编辑:我会创建具有以下属性的类Combination
:
Type
- 代表组合的枚举。Player
- 参考播放器。Cards
- 参与卡片的参考数组。然后实施比较逻辑,以便可以比较任何两种组合:首先是Type
,然后是Cards
(最高卡)。
答案 2 :(得分:0)
我可能会用扑克牌作为一组(大概是5张)牌。然后,为了检查它是什么样的手,我会创建一个CalculateValue()
方法,返回1对,2对2对,3对3,等等。当手是构建,然后只需在需要时重复使用。
答案 3 :(得分:0)
我一直在想它:
我的理由是,所有人都可以归类为HighCard
,Pair
,TwoPairs
,ThreeOfAKind
,Straight
,Flush
,{ {1}},FullHouse
和FourOfAKind
。所有这些都是种(或类)的手,StraightFlush
只是一个抽象类。
所有这些子类只需覆盖Hand
和<
,然后询问一只手是否比另一只更好,就像做>
一样简单,看起来非常自然。 / p>
在现实生活中,我们会先拿双手并比较它们,先看看他们的种类(班级),然后(并且只在必要时)查看他们卡片的价值。因此,使用此方法,aHand < anotherHand
和<
的行为与此完全相同:检查类是否不同,以防我们自动获得答案。如果不是,我们递归检查哪一张卡最好。