Domanda

Per un compito a casa mi è stata data una classe di carta che ha enumerato i tipi per il Rank e Suit. Sono tenuto a confrontare due mani di poker (ogni mano è un ArrayList di 5 carte) e decidere il vincitore.

La funzione isStraight() è veramente mi dà fastidio, perché devo ricominciare da capo il conteggio dopo l'asso. Ad esempio,

regina, re, ACE, due, tre

è ancora considerato un diritto. Qual è il modo migliore per codificare questa funzionalità?

Ecco l'/ vestito enumerato tipo di codice Rank, se questo aiuta.

public enum Rank
{
    TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7), EIGHT(8), NINE(9),
    TEN(10), JACK(11), QUEEN(12), KING(13), ACE(14);

    private final int points;

    private Rank(int points)
    {
        this.points = points;
    }

    public int points()
    {
        return this.points;
    }
}

public enum Suit
{
    DIAMONDS, CLUBS, HEARTS, SPADES;
}
È stato utile?

Soluzione

Ti rendi conto che le regole di qualsiasi gioco di poker che io abbia mai giocato o sentito parlare di un diritto non può avvolgere giusto? Asso può essere bassa [A, 2,3,4,5] o alto [10, J, Q, K, A] ma non può avvolgere. Secondo tali norme (non il vostro) Ho implementato qualcosa di simile prima d'ora. In sostanza si ordina l'array e camminare, assicurandosi la scheda corrente è uno superiore al precedente. Nella prima iterazione, se si tratta di un asso, quindi di controllare in modo esplicito per [A, 2,3,4,5]. Se è vero ritorni e se non lo è si continua con la logica dritto normale. Questo dovrebbe impostare nella giusta direzione.

Altri suggerimenti

Un approccio piacevole per risolvere mani di poker in generale è quello di assegnare ogni carta un valore di bit con bit ((rango-2) * 2) (vestito + 28) impostare il bit impostato così come po ', (quindi 2 = 1, 3 = 4, 4 = 16, ecc fino a a = 0x1000000). Quindi aggiungere insieme tutte le carte (che chiamano risultato 'Sum'. Compute V1 = (Sum & 0x2AAAAAA) >> 1, V0 = (Sum & 0x1555555), e V2 = V1 e V0. Anche o insieme i valori delle cinque carte e calcolare V3 = OrValue & 0xF0000000;

  1. Per una coppia, V1 avrà un singolo bit impostato, V0 avrà più bit impostati, e V2 sarà zero.
  2. Per due coppie, V1 avrà due bit impostati e V2 sarà uguale a zero.
  3. Per un tre-di-un-genere, V1 avrà un singolo insieme di bit, e V2 sarà uguale a V1.
  4. Per una retta, V0 o sarà 0x1000055 oppure un multiplo di potere-di-due di 0x155.
  5. Per un colore, V2 avrà esattamente un bit impostato.
  6. Per un full, V1 avrà due bit impostati, e V2 sarà diverso da zero.
  7. Per quattro-di-un-tipo, sia V1 saranno due volte v0, con entrambi con un insieme di bit o V0 avranno esattamente due bit impostati e V1 sarà zero.
  8. Per una scala reale, saranno soddisfatte le condizioni per scala e colore.

Questo test richiesti per questo approccio dovrebbe essere implementabile rapidamente con una quantità minima di ramificazione.

Si potrebbe scrivere un algoritmo di fantasia per tornare vero nonostante il numero di possibili carte, ma se ti rendi conto che ci sono solo 10 combinazioni valide su una mano ordinato, si può solo cercare questi:

2-6, 3-7, 4-8, 5-9, 6-T, 7-J, 8-Q, 9-K, T-A, (2-5,A)

Dato che ci sono solo 5 carte in voi la lista, è possibile ordinare e determinare la differenza tra 2 carte consecutive. Se contiene un asso, è necessario considerare come una carta bassa troppo. se tutte le differenze sono 1 (o -1, a seconda del tipo di ordinamento), avete il vostro diritto.

Direi che, dato che la definizione di rango, che rettilinei può iniziare solo con un massimo di ACE.points () -. 4

Quindi, se si ordina la tua mano e il rango più basso è> ACE.points (4) - quindi non si può avere una scala, altrimenti basta scorrere i mano per vedere che ogni carta è precedente RANK + 1.

Se ACE può essere alto o basso poi andare con quello che ha risposto SHS.

Con un ciclo interno è abbastanza banale, la sfida sarebbe quella di farlo senza un ciclo interno ...

Inoltre, dipende se hai capito il tuo insegnante o il vostro insegnante incompreso (o travisato) le regole del gioco.

Credo che sarei tentato di creare solo un array [2..14] e mettere le carte nella posizione che corrisponde al loro rango. Se si colpisce un duplicato, non è un diritto, e quando si è fatto, si dovrebbe avere 8 spazi di fila. Se si dispone di meno di 8 posti di fila, non è un diritto.

Tutte le altre soluzioni che posso venire con richiedono un ciclo interno - e cicli interni sono una di quelle cose sciatta programmazione che c'è da evitare ogni volta che è possibile, se si sta andando ad essere sempre un programmatore rispettabile

modifica: Inoltre, se si frainteso l'insegnante e l'unica condizione di avvolgimento è "10, j, q, k, a" (come nelle vere e proprie regole), quindi è necessario un ulteriore test che se tutti 2, 13 e 14 sono impostati, è anche un guasto (avvolgente 2-ak).

(A cura di nuovo per sostituire 1 per asso con 14 dopo aver riletto la domanda)

I dont utilizzare costanti enum molto, preferisco di nome ma darò per scontato che va da "ACE" a "14" è banale

Sono troppo pigro per scrivere codice java reale (accanto devi realmente fare il vostro lavoro ^^)

check if the list has 5 cards
convert card names to a card number list named array
sort the list array
for i=1 to 4
if not (array[i] + 1) % 13 == (array[i+1]) % 13
then it is not a straight

L'operatore% viene chiamato modulo in modo (15% 13) == 2 Io uso questo operatore ogni volta che affronto la sfida "wrap over"

Modifica: dopo aver riletto la tua domanda la mia soluzione non può funzionare out of the box. Si dovrebbe riordinare il vostro enum in modo che due == 0

Mi consiglia di utilizzare un vettore di bit per rappresentare le carte. Questo evita di dover ordinare. È possibile aggiungere l'asso due volte (una volta come 1 le altre volte come un re) oppure si può caso particolare della situazione di partenza, controllando se il bit asso viene impostato prima di controllare se il 2 è impostato). È possibile costruire una grande tabella di ricerca, se le questioni di velocità. Questo approccio anche la pulizia scale per trovare il resto delle mani (vampate, 2 accoppiamenti, case piene, viaggi, e così via). Ma rende anche facile capire se un determinato diritto è superiore a un altro. E si espande in modo pulito a 7 carte valutatore

In pseudo codice sembra qualcosa di simile per un caso molto generale (si può avere qualsiasi numero di carte. Si restituisce il primo rettilineo)

 long cardBitMask
 for each card in hand
   setBit in cardBitMask

 hearts = mask(cardBitMask)
 diamonds = mask(cardBitMask)
 clubs = mask(cardBitMask)
 spades = mask(cardBitMask)

 // find straight
 uniqueCards = hearts|diamonds|clubs|spades
 int cardsInaRow = 0
 if uniqueCards&AceCardMask:
    cardsInaRow = 1
 for card = 2...King
   if uniqueCards&(1<<card)
      cardsInARow++
   else 
      if cardsInARow == 5
         break
      cardsInARow = 0
 if cardsInARow==5:
     return true
 return false

Aggiungi tutti i ranghi al fine di una lista, due volte. Poi, per verificare se una mano è una scala, ordinare la mano per rango e quindi verificare se la mano è un elenco secondario di quella lista.

si potrebbe scrivere una classe che converte ogni carta a un valore di carta specifica

Joker = 11 Regina = 12 Re = 13 Ace = 0 o 14

renderà molto più facile movimentazione della carta e alla ricerca di possibili mani.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top