Почему мой метод isFullHouse () также принимает простую тройку? - PullRequest
5 голосов
/ 04 октября 2010

У меня проблемы с моим методом полного дома. Я думал, что это так же просто, как проверка на три вида и пару. Но с моим текущим кодом я получаю фулл-хаус только с тремя в своем роде. Код isFullHouse () isThreeOfAKind () и isPair () ниже, спасибо за помощь!

 public boolean isPair() {
     Pips[] values = new Pips[5];
     int count =0;

     //Put each cards numeric value into array
     for(int i = 0; i < cards.length; i++){
         values[i] = cards[i].getPip();
     }

     //Loop through the values. Compare each value to all values
     //If exactly two matches are made - return true
     for(int x = 1; x < values.length; x++){
         for(int y = 0; y < x; y++){
             if(values[x].equals(values[y])) count++;
         }
         if (count == 1) return true;
         count = 0;
     }
     return false;  
 }

 public boolean isThreeOfAKind() {
    Pips[] values = new Pips[5];
    int counter = 0;

    for(int i = 0; i < cards.length; i++){
        values[i] = cards[i].getPip();
    }

    //Same process as isPair(), except return true for 3 matches
    for(int x = 2; x < values.length; x++){
         for(int y = 0; y < x; y++){
             if(values[x].equals(values[y]))
                 counter++;
         }
         if(counter == 2) return true;
         counter = 0;
    }

    return false;
}

public boolean isFullHouse(){
    if(isThreeOfAKind() && isPair())
        return true;
    return false;
}

Ответы [ 11 ]

9 голосов
/ 04 октября 2010

Убедитесь, что пара имеет другой ранг, чем тройка. В противном случае ваша функция isPair() найдет те же карты, что и три вида. Может быть так:

public boolean isFullHouse(){
    int three = isThreeOfAKind();
    int pair = isPair();
    if (three != 0 && pair != 0 && three != pair) {
        return true;
    }
    return false;
}

(я использовал int, но вы можете изменить свой тип Pips, если хотите.)

6 голосов
/ 04 октября 2010

Могу ли я предложить способ значительно упростить вашу логику?

Рассмотрим вспомогательный метод с именем partitionByRank():

public class RankSet {
    private int count;
    private Rank rank;
}

/**
 * Groups the hand into counts of cards with same rank, sorting first by
 * set size and then rank as secondary criteria
 */
public List<RankSet> partitionByRank() {
   //input e.g.: {Kh, Qs, 4s, Kd, Qs}
   //output e.g.: {[2, K], [2, Q], [1, 4]}
}

Получить тип руки действительно легко:

public boolean isFullHouse() {
    List<RankSet> sets = partitionByRank();
    return sets.length() == 2 && sets.get(0).count == 3 && sets.get(1).count() == 2;
}

public boolean isTrips() {
    //...
    return sets.length() == 3 && sets.get(0).count = 3;
}

Это также поможет позже, когда вам неизбежно потребуется проверить, больше ли одна пара, чем другая пара, например,

2 голосов
/ 04 октября 2010

Сначала вы должны удалить три одинаковых карты из пятикарточной руки.Три в своем роде - это правда, а два в другом - это правда.Наборы должны быть непересекающимися.

1 голос
/ 04 октября 2010

Вам не хватает третьего условия: тройка должна быть другой картой, чем пара.Так ... так как у вас есть этот общий массив "карт", вы, вероятно, могли бы "пометить" карты как подсчитанные и сбросить подсчитанный статус для каждого прохода:

//Same process as isPair(), except return true for 3 matches
for(int x = 2; x < values.length; x++){
     cards[x].setCounted(true);  // by default, count the start card
     for(int y = 0; y < x; y++){
         // make sure the card isn't already counted:
         if(!cards[y].isCounted() && values[x].equals(values[y])) {
             counter++;
             cards[x].setCounted(true); // count it
         }
     }
     if(counter == 2) return true;
     counter = 0;
     // reset counted cards
     for(int z=0, zlen=values.length; z < zlen; z++) { cards[z].setCounted(false); }
}
1 голос
/ 04 октября 2010

потому что у тройки тоже есть пара (на самом деле в вашем коде может быть 2 пары)

один из способов сделать это - отсортировать руку по рангу, а затем просто условно определитьЛодка.

if ( ((c1.rank == c2.rank == c3.rank) && (c4.rank == c5.rank)) ||
     (c1.rank == c2.rank) && (c3.rank == c4.rank == c5.rank))

Они могут быть дополнительными (там, но вы поняли ...

0 голосов
/ 17 августа 2011

Согласно вашим комментариям в коде (exactly two matches слов), возможно, вы пытаетесь реализовать метод isPair таким образом, чтобы он возвращал false в случае комбинации трех типовЕсли это так, вам нужно изменить метод isPair, чтобы перебирать все элементы в массиве, например:

//Loop through the values. Compare each value to all values
     //If exactly two matches are made - return true
     for(int x = 0; x < values.length; x++){
         for(int y = 0; y < values.length; y++){
             if(y != x && values[x].equals(values[y])) count++;
         }
         if (count == 1) return true;
         count = 0;
     }
0 голосов
/ 05 октября 2010

Если вы имеете дело только с пятикарточными руками, подсчет количества пар должен дать один для пары, два для двух пар, три для тройки (например, если у вас есть As, Adи Ac - пары As-Ad, As-Ac и Ad-Ac), четыре для фулл-хауса и шесть для четверки в своем роде.Эта логика не будет работать с семью картами, так как она будет рассчитывать три, например, для AAKKQQJ (которые должны учитываться только как две пары, а не три в своем роде), и шесть для AAAKKKQ (которые должны рассматриваться как фулл-хаус, а не четверка).

0 голосов
/ 04 октября 2010

Лучший общий подход к проблеме - это C #, но преобразование его в Java должно быть простым:

int[] countOfRank = new int[13];
int[] countOfSuit = new int[4];
for(int i = 0; i < cards.length; i++)
{
     countOfRank[cards[i].Rank]++;
     countOfSuit[cards[i].Suit]++;
}

for (int i=0; i < countOfSuit.length; i++)
{
   isFlush = isFlush || countOfSuit[i] == 5;
}

int[] countOfTuple = new int[5];
int runLength=0;
for (int i=0; i < countOfRank.length; i++)
{
   if (countOfRank[i] == 1)
   {
      runLength++;
      isStraight = (isStraight || runLength == 5);
   }
   else
   {
      runLength=0;
   }
   countOfTuple[countOfRank[i]]++;
}
isPair = (countOfTuple[2] == 1 && countOfTuple[3] == 0);
isTwoPair = (countOfTuple[2] == 2);
isFullHouse = (countOfTuple[2] == 1 && countOfTuple[3] == 1);
isThreeOfAKind = (countOfTuple[2] == 0 && countOfTuple[3] == 1);
isFourOfAKind = (countOfTuple[4] == 1);
isStraightFlush = (isStraight && isFlush);
isStraight = (isStraight && !isStraightFlush);
isFlush = (isFlush && !isStraightFlush);
isRoyalFlush = (isStraightFlush && countOfRank[12] == 1);
isStraightFlush = (isStraightFlush && !isRoyalFlush);
0 голосов
/ 04 октября 2010

Просто идея, не будет ли проще сделать что-то вроде этого:

int[] count=new int[13];//size of all ranks
for (i=0;i<5;i++)
  count[ card[i].rank ] ++;

Таким образом, у вас будет, например: 0 0 0 0 0 3 0 0 0 2 0 0 0 0 для фулл-хауса. Стрит будет выглядеть как 5 подряд: 0 0 0 0 1 1 1 1 1 0 0 0.

Поскольку методы общедоступны, я бы не хотел, чтобы метод isPair() возвращал true, если есть пара. Он должен возвращать true, только если нет ничего лучше, чем одна пара.

0 голосов
/ 04 октября 2010

Ваш метод isPair () всегда будет возвращать true, когда есть три карты одного вида, потому что ваш внутренний цикл всегда проверяет значения y только до x.

, поэтому с этими данными AAA78, когда x = 1y = 0 вы получите count == 1 во внутреннем цикле и вернете true, хотя их три.Лучше обойти весь массив и подсчитать значения, когда

if(values[x].equals(values[y]) && x != y)

Кроме того - лучше использовать одну функцию в форме isNOfAKind (), которая получает количество карточек в качестве параметра, поскольку эти два метода по существусделай то же самое.

...