【发布时间】:2015-08-07 14:13:17
【问题描述】:
我知道here 中描述的 Java(以及一般情况)中的比较规则。
我有一个字符串数组列表。
每个字符串代表忽略花色的德州扑克手牌。
每个字符串的长度正好是 13 个字符。
每个字符串仅由和为 7 的数字组成。
例如,“0100300200100”代表一手牌,由一张 3、三张 6、两张 9 和一张 Q 组成。
(在这种情况下,这手牌代表满屋 - 满是 9 的 6)。
我想根据扑克牌的强度对这个列表进行排序。
我有以下实现 Comparator 的比较方法的 java 代码。
final Comparator<String> COMBINATION_ORDER = new Comparator<String>() {
@Override
public int compare(String c1, String c2) {
if (c1.indexOf('4') != -1 || c2.indexOf('4') != -1) { // Four of a kind
if (c1.indexOf('4') == c2.indexOf('4')) {
for (int i = 12; i >= 0; i--) {
if (c1.charAt(i) != '0' && c1.charAt(i) != '4') {
if (c2.charAt(i) != '0' && c2.charAt(i) != '4') {
return 0;
}
return 1;
}
if (c2.charAt(i) != '0' && c2.charAt(i) != '4') {
return -1;
}
}
}
return c1.indexOf('4') - c2.indexOf('4');
}
int tripleCount1 = StringFunctions.countOccurrencesOf(c1, "3");
int tripleCount2 = StringFunctions.countOccurrencesOf(c2, "3");
if (tripleCount1 > 1 || (tripleCount1 == 1 && c1.indexOf('2') != -1) || tripleCount2 > 1 || (tripleCount2 == 1 && c2.indexOf('2') != -1)) { // Full house
int higherTriple = c1.lastIndexOf('3');
if (higherTriple == c2.lastIndexOf('3')) {
for (int i = 12; i >= 0; i--) {
if (i == higherTriple) {
continue;
}
if (c1.charAt(i) == '2' || c1.charAt(i) == '3') {
if (c2.charAt(i) == '2' || c2.charAt(i) == '3') {
return 0;
}
return 1;
}
if (c2.charAt(i) == '2' || c2.charAt(i) == '3') {
return -1;
}
}
}
return higherTriple - c2.lastIndexOf('3');
}
return 0;
}
};
同时,我仅指四种类型和满屋。 这意味着每一手牌都将被视为彼此平等(但不如四牌或满屋)。
但是当我在排序时:
combinations.sort(COMBINATION_ORDER);
(其中 combinations 是我的 ArrayList)。
我得到一个异常。
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:773)
at java.util.TimSort.mergeAt(TimSort.java:510)
at java.util.TimSort.mergeCollapse(TimSort.java:437)
at java.util.TimSort.sort(TimSort.java:241)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1454)
at Poker.main(Poker.java:120)
请帮助我了解代码有什么问题。
非常感谢。
编辑:
正如@ajb 所说,我没有考虑没有满屋的三类。
解决方案:
final Comparator<String> COMBINATION_ORDER = new Comparator<String>() {
@Override
public int compare(String c1, String c2) {
if (c1.indexOf('4') != -1 || c2.indexOf('4') != -1) { // Four of a kind
if (c1.indexOf('4') == c2.indexOf('4')) {
for (int i = 12; i >= 0; i--) {
if (c1.charAt(i) != '0' && c1.charAt(i) != '4') {
if (c2.charAt(i) != '0' && c2.charAt(i) != '4') {
return 0;
}
return 1;
}
if (c2.charAt(i) != '0' && c2.charAt(i) != '4') {
return -1;
}
}
}
return c1.indexOf('4') - c2.indexOf('4');
}
int tripleCount1 = StringFunctions.countOccurrencesOf(c1, "3");
int tripleCount2 = StringFunctions.countOccurrencesOf(c2, "3");
if (tripleCount1 > 1 || (tripleCount1 == 1 && c1.indexOf('2') != -1)) { // c1 Full house
if (tripleCount2 > 1 || (tripleCount2 == 1 && c2.indexOf('2') != -1)) { // c2 Full house too
int higherTriple = c1.lastIndexOf('3');
if (higherTriple == c2.lastIndexOf('3')) {
for (int i = 12; i >= 0; i--) {
if (i == higherTriple) {
continue;
}
if (c1.charAt(i) == '2' || c1.charAt(i) == '3') {
if (c2.charAt(i) == '2' || c2.charAt(i) == '3') {
return 0;
}
return 1; // only c1 Full house
}
if (c2.charAt(i) == '2' || c2.charAt(i) == '3') { // only c2 Full house
return -1;
}
}
}
return higherTriple - c2.lastIndexOf('3');
}
return 1;
}
if (tripleCount2 > 1 || (tripleCount2 == 1 && c2.indexOf('2') != -1)) {
return -1;
}
return 0;
}
};
【问题讨论】:
-
this question 的可能重复项?
-
那么你将如何检测冲洗? :)
-
不仔细看,我认为你的逻辑是错误的。如果
(c1.indexOf('4') == c2.indexOf('4'))为真,那么你有一副牌,里面有八张相同的牌。这并不能解释异常,但它让我认为您的算法可能存在其他错误。 -
@ajb,为了检测 Flush 我使用了另一个代码。当我确定没有 Flush 时使用此代码。
标签: java collections compare comparator comparable