- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在寻找一种有效的解决方案来确定一手牌在印度拉米纸牌游戏中是否获胜。印度拉米在融合方面类似于杜松子拉米。人们可以将相同花色的序列(直线)组合在一起,也可以将一组相同的值组合在一起。序列和系列都应至少包含 3 张牌。与金拉米不同,在印度拉米中,一手牌由 13 张牌组成。一手获胜的牌应包含至少两个序列,并且这些序列中至少有一个必须是纯序列。所谓纯粹,我的意思是不应该在 clown (通配符)的帮助下制作序列。这手牌的其余部分可以由带有或不带有王牌的序列和组合组成。注意:除了一副牌 (52 + 2) 中的 2 张王牌外,牌库中还有一张随机牌用作王牌。例如,如果黑桃 5 被随机选为王牌,则牌组中其他花色的剩余三个 5 可以用作 2 个常规王牌之上的王牌。
以下是一些不使用王牌的有效获胜手牌示例:
以下是一些使用王牌获胜的例子。假设 6(黑桃)是从一副牌中随机抽取的 clown ;所以剩下的所有 6 都可以用作 clown 。
以下是一些不是获胜手的例子:
我希望这已经解释了什么是获胜的手。下面的模型代表一张卡片:
public class Card {
public final static int SPADES = 0,
HEARTS = 1,
DIAMONDS = 2,
CLUBS = 3;
public final static int ACE = 1,
JACK = 11,
QUEEN = 12,
KING = 13,
JOKER = 0;
private final int suit;
private final int value;
public Card(int theValue, int theSuit) {
value = theValue;
suit = theSuit;
}
public int getSuit() {
return suit;
}
public int getValue() {
return value;
}
public String getSuitAsString() {
switch ( suit ) {
case SPADES: return "Spades";
case HEARTS: return "Hearts";
case DIAMONDS: return "Diamonds";
case CLUBS: return "Clubs";
default: return "??";
}
}
public String getValueAsString() {
switch ( value ) {
case 1: return "Ace";
case 2: return "2";
case 3: return "3";
case 4: return "4";
case 5: return "5";
case 6: return "6";
case 7: return "7";
case 8: return "8";
case 9: return "9";
case 10: return "10";
case 11: return "Jack";
case 12: return "Queen";
case 13: return "King";
default: return "JOKER";
}
}
@Override
public String toString() {
return getValueAsString().equals("JOKER") ? "JOKER" : getValueAsString() + "(" + getSuitAsString() + ")";
}
@Override
public boolean equals(Object card) {
return suit == ((Card) card).getSuit() && value == ((Card) card).getValue();
}
我还写了一些函数来获取卡片中可能的序列和集合。 getSequences 函数中的参数 (List) 已经按花色排序,然后按值排序。对于 getSets 函数中的参数,卡片仅按值排序。两个函数中第二个参数 (min) 的值均为 3。
private List<List<Card>> getSequences(List<Card> hand, int min) {
List<List<Card>> sequences = new ArrayList<>();
List<Card> sequence = new ArrayList<>();
for(int i=1; i<hand.size(); i++) {
if(hand.get(i).getSuit() == hand.get(i-1).getSuit() &&
(hand.get(i).getValue() - hand.get(i-1).getValue()) == 1) {
sequence.add(hand.get(i-1));
if(hand.get(i).getValue() == 13) {
int j = i;
while(hand.get(j).getSuit() == hand.get(i).getSuit()) {
j--;
if(hand.get(j).getValue() == 1) {
sequence.add(hand.get(j));
}
}
}
if(i == hand.size() -1) {
sequence.add(hand.get(i));
sequences.add(sequence);
}
} else {
sequence.add(hand.get(i-1));
if(sequence.size() >= min) {
sequences.add(sequence);
}
sequence = new ArrayList<>();
}
}
return sequences;
}
private List<List<Card>> getSets(List<Card> hand, int min) {
List<List<Card>> sets = new ArrayList<>();
List<Card> set = new ArrayList<>();
for(int i=1; i<hand.size(); i++) {
if(hand.get(i).getValue() != joker.getValue()) {
if(hand.get(i).getValue() == hand.get(i-1).getValue()) {
set.add(hand.get(i-1));
if(i == hand.size() -1) {
set.add(hand.get(i));
}
} else {
set.add(hand.get(i-1));
if(set.size() >= min) {
sets.add(set);
}
set = new ArrayList<>();
}
}
}
return sets;
}
我认为这不是查找序列和集合的最优雅的方法。因此,我欢迎任何关于如何改进它的建议。但我真正需要帮助的是我接下来该做什么?集合和序列之间可能存在重叠。例如,对于以下卡片:
请建议如何有效地确定获胜手。
P.S:在确定获胜手牌时,玩家手中将有14张牌。融合 13 张牌后,第 14 张牌将被丢弃。
最佳答案
我已经实现了 Rummikub 的 java 版本(具有类似限制的游戏)。
我的方法是给每张卡片一个隐藏的整数属性(质数)。
然后每个有效的组合都可以唯一地表示为一个整数。可以预先计算出构成有效组合的精确整数并将其放入 Set<Long>
中。当然。
检查一手牌是否只包含有效的组合然后简化为检查给定的长牌是否可以写成一组给定数字的乘积。 (可以使用递归和动态规划)
具体例子(一):
Set<Long> validMelds = {30, .., ..}
如果手牌(值 = 60)那么我们知道它包含 2 个有效的组合。
具体例子(二)
已知有效组合 = {30, 210, 226793, ..}
手牌值(value) = 6803790
简单(递归)算法:
递归算法得出结论这是一个有效的分支
备选
6803790能被210整除
递归算法结束分支在这里停止
如果您需要能够处理部分手牌并不总是有效组合的一部分的情况,您可能希望查看 linear algebra .
关于java - 确定 Indian Rummy 手牌是否获胜 - Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51225335/
我正在寻找一种有效的解决方案来确定一手牌在印度拉米纸牌游戏中是否获胜。印度拉米在融合方面类似于杜松子拉米。人们可以将相同花色的序列(直线)组合在一起,也可以将一组相同的值组合在一起。序列和系列都应至少
我是一名优秀的程序员,十分优秀!