Faccia da poker
introduzione
A Leo piace giocare a poker, ma il suo lavoro in Tech Inc. è troppo impegnativo per imparare a giocare bene. Leo, essendo un informatico, non è scoraggiato. Decide di dedicare più tempo di quanto ci sarebbe voluto solo per imparare il poker e usarlo per scrivere un bot di poker per aiutarlo a giocare meglio. Ma ora Leo ha un problema: per capire come giocare un po 'meglio, Leo deve osservare più giochi di più "persone", ma le "persone" hanno bisogno di stili di gioco diversi per migliorare la qualità e la realtà del gioco.
La sfida
Leo ricorda che in realtà esiste un sito Web dedicato alle sfide di programmazione e sta chiedendo aiuto! Il tuo compito è scrivere un programma che riproduca "Pokerface" una versione modificata del poker a 5 carte. Il programma prenderà l'input come una mano di 5 carte in qualsiasi formato desiderato, dopodiché il programma mostrerà:
- "True" "1" o "t" esatto (con distinzione tra maiuscole e minuscole) se il giocatore desidera scambiare carte, altrimenti qualsiasi altra uscita non vuota.
- Se vero, elenco di indici di carte e / o nomi di carte che il giocatore desidera scambiare.
- Un singolo numero compreso tra 0 e 3, che specifica quante carte aggiuntive desidera il giocatore.
- Stampa la mano che il giocatore desidera utilizzare.
(Vedi formattazione di seguito)
Regole di Pokerface
- Dato che pokerface è un gioco di avventura basato su testo, le carte devono essere presentate in modo coerente. Le carte sono rappresentate da due codici personaggio, il primo è il seme e il secondo è il nome della carta.
- Carte:
- 2-9 = 2-9
- 10 = T
- Jack = J
- Regina = Q
- Re = K
- Asso = A
- Suits:
- Picche = S
- Club = C
- Hearts = H
- Diamante = D
- Carte:
Quindi l'asso di picche sarebbe SA, il 10 di cuori è HT, il 4 di quadri è D4, ecc.
- Un singolo round di Pokerface consiste in quattro passaggi:
- Il mazzo viene rimescolato e una mano di cinque carte viene distribuita a ciascun giocatore.
- Ogni giocatore ha la possibilità di scambiare tutte le carte che vuole.
- Ogni giocatore ha la possibilità di guadagnare fino a tre carte in più.
- Ogni giocatore deve rivelare la sua mano migliore.
- La mano migliore vince e guadagna un punto per quel giocatore. In caso di pareggio, entrambi i giocatori ottengono un punto.
- In una singola partita, vengono giocati dieci round e il giocatore con il maggior numero di punti vince e guadagna un singolo "punto vittoria". In caso di pareggio, entrambi i giocatori guadagnano un punto vittoria.
- Leo non ha davvero una grande quantità di denaro, quindi il tuo bot può presumere che questo sia un mondo perfetto senza scommesse.
Mani
- Le mani hanno esattamente 5 carte di lunghezza (input iniziale e output finale).
- Le mani sono classificate coerentemente con le regole descritte qui .
Input Output
- Leo conosce solo Java, quindi il tuo programma deve essere eseguibile tramite l' API di processo (riga di comando) e utilizzare rispettivamente STDIN e STDOUT per l'input e l'output.
- Per ogni passaggio di input e output sopra descritto, l'input e l'output devono esistere ciascuno su una riga.
- Deve esserci almeno una nuova riga finale dopo l'output finale. (Ciò è dovuto al modo in cui l'input viene letto da STDIN)
- Non sono consentiti input / output estranei, tranne spazi finali e iniziali. Il parser semplicemente non capisce cose come
final_hand=...
odraw 0
. - Quando si disegna, l'output è un singolo intero, quando si scambia l'output è un elenco di numeri interi e / o carte definiti di seguito e quando viene distribuita la mano originale, l'output è un elenco di carte definito di seguito.
- Tutti i numeri di input / output devono essere numeri interi positivi nella base 10.
- È possibile definire il formato per l'immissione delle carte (vedere il formato dei post di seguito).
- Vero è definito esattamente come "vero", "1" o "t" e falso è qualsiasi altro valore non vuoto.
- Durante la fase di scambio:
- Gli indici delle carte devono essere emessi con almeno uno spazio tra loro (ad es.
3 4 0
) - I nomi delle carte devono essere emessi con almeno uno spazio tra loro (es.
H4 S8
) - Nomi e indici delle carte possono essere mescolati nell'output (ad es.
0 H7 3 D3
) - Sono consentiti spazi finali e iniziali.
- L'input come risultato del giocatore che emette quanto sopra sarà formattato come specificato dal
bot.jlsc
file, nello stesso ordine richiesto
- Gli indici delle carte devono essere emessi con almeno uno spazio tra loro (ad es.
- Il numero di carte che un giocatore vuole aggiungere alla propria mano può avere spazi iniziali e finali.
- Le mani devono essere emesse con almeno uno spazio tra loro (ad es.
H4 D5 CA
), Sono consentiti spazi finali e spazi iniziali. - Le mani non devono essere emessi in modo corretto (ad esempio,
H4 D4 C4 DA SA
edH4 DA D4 SA C4
entrambi rappresentano 4, 4, 4, Ace, Ace, che è una casa piena). - Se desideri costruire una strategia analizzando le mani degli avversari, puoi archiviare i dati in una
<botname>/data
directory.- Dopo che i robot in competizione hanno mostrato le loro mani, saranno scritti in ogni directory dei dati dei bot, in hands.txt, con ogni mano su una nuova linea (separate da \ n). Il file verrà codificato in US_ASCII.
- Dopo che il tuo bot richiede nuove carte o scambia carte, le carte verranno inserite in base al formato specificato nel
bot.jlsc
file.
Formato post
- Ogni post deve includere due cose:
- Il codice sorgente del bot o un collegamento a un repository pubblico.
- Un file zip contenente:
- La versione compilata / eseguibile del tuo bot (se il file è un file .exe o un altro file non decompilabile, includi semplicemente le istruzioni di compilazione nel tuo post).
- Un
bot.jlsc
file, vedi sotto (nota a margine: l'estensione .jlsc è solo a causa di un mio progetto laterale, un formato di configurazione. Il file seguente corrisponde alla sintassi corretta, quindi non preoccuparti).
- Il file .zip deve avere lo stesso nome del tuo bot.
- Se non hai accesso a Windows o ad altre utilità di zippatura o non riesci a creare un .zip per qualsiasi motivo, includi semplicemente il testo del file bot.jlsc nel tuo post
file bot.jlsc:
name= "Botty"
link= "example.com"
cmd= "java -jar Botty.jar"
input_hand= "${0} ${1} ${2} ${3} ${4}"
input_1= "${0}"
input_2= "${0} ${1}"
input_3= "${0} ${1} ${2}"
input_4= "${0} ${1} ${2} ${3}"
Dove:
- "cmd" è Windows comando da riga di comando di per eseguire il tuo bot. Nota che il tuo bot sarà nella directory
<botname>
, quindi regola il comando di conseguenza. - "nome" è il nome del tuo bot.
- "link" è il link alla tua risposta, dovrai modificarlo dopo aver pubblicato.
- "input_hand" è il modo in cui si desidera formattare la distribuzione originale (con $ {#} che rappresenta le carte 0-4).
- "input_1" è il modo in cui si desidera formattare l'ingresso di una scheda aggiuntiva.
- "input_2" è il modo in cui si desidera formattare l'ingresso di due schede aggiuntive.
- "input_3" è il modo in cui si desidera formattare l'ingresso di tre schede aggiuntive.
- "input_4" è il modo in cui si desidera formattare l'ingresso di quattro schede aggiuntive.
specifiche
- Queste scappatoie non sono ammesse (vedere "insidie comuni")
- Non puoi scrivere un bot, ma otterrai sempre la mano migliore possibile, ogni volta, all'interno del set di regole. (ovvero nessun robot a forza bruta di lunga durata, niente dovrebbe essere "buono" come LeoBot)
- Il tuo bot dovrebbe funzionare in ~ 100 ms o meno (Lenient su questo punto, max di ~ 1 secondo)
- Qualsiasi output del bot dopo la sua mano scelta verrà ignorato.
- Le scappatoie standard non sono ammesse.
- Sì, so che Linux è migliore, ma ho un PC Windows, quindi assicurati che la versione compilata / eseguibile del tuo programma possa essere eseguita dalla riga di comando di Windows.
- Ho già installato Python e Java sul mio computer, ma sono disposto ad aggiornare le nuove versioni e installare altri ambienti, quindi specifica il tipo di ambiente richiesto dal tuo programma.
- Non puoi scrivere un bot che faccia la stessa cosa di un altro bot in ogni caso. I robot spam sono consentiti, ma scoraggiati.
- Il tuo bot può usare solo le carte che ha. Le carte perse attraverso lo scambio o non distribuite all'inizio non sono prodotte nell'ultima mano.
- L'input e l'output possono contenere solo caratteri ASCII.
tornei
- I tornei si terranno quando avrò il tempo (il mio programma è quasi impacchettato come quello di Leo, quindi questo è un po 'raro. Ci scusiamo per l'inconveniente.).
- I robot si scontreranno a vicenda in partite a 4 persone e ci sarà una partita per ogni possibile sottoinsieme di robot (cioè molte partite).
- Questo processo verrà ripetuto cinque volte.
- A causa del modo in cui il gestore del torneo crea i gruppi di robot, verranno aggiunti fino a tre bot di riempimento per rendere il numero di bot divisibili per 4. Questi robot restituiranno semplicemente la mano in cui erano stati inizialmente distribuiti.
- Dopo ogni round e gioco, i punteggi dei robot verranno calcolati in base al numero di partite vinte.
- Più robot possono condividere una posizione (vincoli per il primo vinto per primo pubblicato).
- Al termine di un torneo, i punteggi verranno aggiunti in fondo a questo post.
punteggio
Regole normali di KoTH. I bot che vincono il maggior numero di giochi vincono la sfida.
LeoBot
Il robot di Leo è piuttosto intelligente. Non scambia nessuna carta, è troppo difficile, ma richiede il numero massimo di carte aggiuntive e determina la migliore mano possibile e gioca quella mano. La logica principale del leobot è di seguito.
package com.gmail.socraticphoenix.pokerface.leobot;
import com.gmail.socraticphoenix.pokerface.lib.card.Card;
import com.gmail.socraticphoenix.pokerface.lib.card.Deck;
import com.gmail.socraticphoenix.pokerface.lib.rule.HandRegistry;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class LeoBot {
public static void main(String[] args) {
List<Card> hand = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
hand.addAll(Card.parseHand(scanner.nextLine()));
System.out.println(false);
System.out.println(3);
hand.addAll(Card.parseHand(scanner.nextLine()));
List<List<Card>> possibleHands = LeoBot.getSubsets(hand, 5);
System.out.println(Deck.toString(possibleHands.stream().sorted((a, b) -> HandRegistry.determineWinner(b, a).comparable()).findFirst().get()));
}
private static <T> void getSubsets(List<T> superSet, int k, int idx, List<T> current, List<List<T>> solution) {
if (current.size() == k) {
solution.add(new ArrayList<>(current));
return;
}
if (idx == superSet.size()) return;
T x = superSet.get(idx);
if (!current.contains(x)) {
current.add(x);
}
getSubsets(superSet, k, idx + 1, current, solution);
current.remove(x);
getSubsets(superSet, k, idx + 1, current, solution);
}
public static <T> List<List<T>> getSubsets(List<T> superSet, int k) {
List<List<T>> res = new ArrayList<>();
getSubsets(superSet, k, 0, new ArrayList<T>(), res);
return res;
}
}
Nota che se LeoBot vince costantemente i tornei e ci sono molte iscrizioni, smetterò di includerlo nella corsa.
Link importanti
disconoscimento
Leo e Tech Inc. sono elementi della storia e qualsiasi somiglianza con le società o le persone nella vita reale è puramente involontaria. (Tuttavia, quando la "situazione" di Leo aggiunge o sottrae condizioni dalla domanda, quelle fanno effettivamente parte della domanda ...)
"f"q+
soddisfa i requisiti minimi. Se ci sono 10 persone in competizione, questo probabilmente batte tutte le voci non stupide (la voce non stupida ha probabilmente> 75 caratteri, 5 * 10 (punteggio del bot stupido, ultimo arrivato) = 50 <75 (punteggio del bot intelligente molto piccolo (prima di venire))). Quindi, probabilmente dovresti rimuovere codegolf da questa sfida