2009-11-18 27 views
1

J'écris un HandConverter d'une main de poker. C'est mon premier projet et j'essaye de le faire dès le début. J'ai déjà obtenu le plus de parties, comme les listes de joueurs, leur position, les tailles de tapis, les cartes pour différentes tables, quel jeu est joué et ainsi de suite, mais je me bats avec la représentation des paris, en particulier les différentes hausses , les paris et les appels multiples du même joueur.Représentation d'objet des tours d'enchères au poker

J'ai trouvé quelques cas où ma solution basée sur des cas naïfs ne fonctionne pas, et c'est vraiment compliqué et je ne l'aime pas. Comme cela fonctionne actuellement pour NL Hold'em, je pense que je vais avoir plus de solutions de rechange si je veux mettre en œuvre des jeux comme Stud, Razz et ainsi de suite, mais la structure de pari est probablement la même.

Pour l'instant j'utilise cette représentation et je voudrais améliorer en particulier les classes Round et Action. Avez-vous des suggestions pour moi?

public class HandHistory 
{ 
    public GameInfo GameInfo; 
    public TableInfo TableInfo; 
    public List<Player> Players; 
    public List<Round> Rounds; 
    public string rawtext; 
    public bool withHero; 

} 

public Round 
{ 
    public List<Action> Action; 
    public string Name; 
    public decimal Potsize; 
    public ulong Cards; //usually would have used a custom class, 
         //but I need them in a ulong mask for some library I use 
} 

public class Action 
{ 
    public Player Player; 
    public string Type; 
    public decimal Amount; 
} 

P.S. J'utilise également une liste pour stocker les différents tours, est-il préférable d'hériter de la classe ronde pour Flop, Turn et River, par exemple?

+1

Vous ne savez pas exactement ce que les cartes dans Round sont supposées représenter. – FrustratedWithFormsDesigner

+0

il représente un masque de carte 64 bits.Ceci est utilisé par l'évaluateur (calcul de la force de la main et ainsi de suite) J'utilise – Sven

Répondre

1

Quand vous dites premier projet que voulez-vous dire? Je suppose que vous êtes un étudiant ou un débutant en programmation. Dans cette hypothèse, je suggère de choisir quelque chose de plus simple et qu'une histoire de main de poker. Comme dans la programmation de jeux, il est déraisonnable de penser à votre premier tir de la programmation d'un jeu que vous créez le dernier Call of Duty. Vous commencez avec l'évasion et progressez à partir de là.

Si vous ne voulez pas commencer plus petit que je ne suggère de sauter dans le codage. Lorsque vous faites cela, vous passerez plus de temps à faire tourner vos roues plutôt que de faire quelque chose. Par exemple, vous devriez d'abord passer du temps à concevoir ce que votre programme fera et ce qu'il ne fera pas. Essayez d'être aussi complet que possible. Cela peut être fait à partir de quelque chose d'aussi compliqué en utilisant un programme UML ou aussi simple qu'un stylo et du papier.

Je voudrais savoir comment vous voulez qu'une main progresse. Informations que vous souhaitez suivre Une fois que vous aurez compris cela, vos structures de données commenceront à prendre vie.

Puisque vous êtes novice en programmation, je commencerais à écrire du code de preuve de concept. Puis déplacez-le vers votre projet final. Ce que je veux dire par preuve de concept est le code que vous essayez juste une idée pour voir comment cela fonctionne. Par exemple, comment l'histoire des mains fonctionnerait-elle? Pouvez-vous créer une histoire de simulation et les configurer? Idéalement, vous pourriez faire un test unitaire, mais commençons un peu plus petit.

Il est important de savoir que vous construisez un programme, tout comme une maison. Vous devez savoir ce que vous voulez faire et ne pas faire (impressions bleues). Quelle est chaque étape. Et vous construisez sur d'autres pièces lentement. C'est un processus qui prend du temps, mais à la fin, ça en vaut la peine.

2

Au lieu d'une chaîne pour votre Action.Type, vous pouvez utiliser un ENUM:

enum BettingAction 
{ 
    Check, 
    Bet, 
    Call, 
    Raise, 
    Fold 
} 
0

Les cartes pourraient avoir un meilleur nom, mais je suppose que vous voulez dire les cartes de la communauté. J'en ferais une liste de cartes, alors les sous-classes de tour et de rivière n'auraient jamais qu'une seule carte dans la liste. Je suggère également de représenter les cartes d'une manière qui a du sens pour vous et ensuite faire une conversion lorsque vous avez besoin d'interface avec la bibliothèque.

0

Pas vraiment une réponse liée à la programmation; mais les styles de paris pour Razz ou Stud sont différents de Hold'em de plusieurs façons.

1.) Il n'y a pas de stores; Antes plutôt
2.) L'ouverture de personne peut soit faire-ou compléter le pari
3.) Il y a plus de tours d'enchères

Vous avez un très bon départ. Vous voudrez probablement créer un List<Hands> qui a List<Rounds> à l'intérieur. Sinon, vous aurez une énorme liste de tours sans être capable de dire quand une main a commencé/terminé et un autre a commencé.

Je pense que vous devez probablement définir vos types d'action, et que les choses vont probablement commencer à se mettre en place. Voici ce que j'aurais pour les types:

Vérifiez
Bet
Fold
Appel
Raise (essentiellement un appel et pari)

pourrait aussi penser à mettre en œuvre quelque chose comme "action préalable" sur votre classe d'action; comme chaque joueur réagit à l'action avant eux.

Vous voudriez également adresser quelques nuances du jeu; où le joueur a misé 500 et le joueur b fait tout pour 250; puisque, sauf dans ce cas, l'appel doit correspondre au pari précédent.

+0

Chaque main est représentée par cet objet, Rounds est la représentation de Preflop, Flop, Turn et River. – Sven

0

Le terme Round est un peu ambigu. BettingRound le rend plus évident. Je ne vois pas le besoin d'avoir des cartes, de nommer et de puiser ici. Potsize est une fonction des actions et des changements tout au long du tour d'enchères. Sièges représentent le jeu un peu mieux que la liste des joueurs car cela vous permet de représenter l'état du jeu (tailles de pile, etc) un peu plus évidemment. Je ne vois pas la nécessité de rendre le flop, les cartes river explicitement assignées aux rounds - il suffit d'utiliser une liste de cartes et quelques conventions. par exemple. trois premières cartes = flop ... premier tour d'enchères = flop. Utilisez des méthodes d'extension pour plus de commodité en vous référant au flop pour holdem. Utilisez la version ulong des cartes via la conversion lorsque vous avez besoin de l'utiliser plutôt que d'encombrer votre modèle de domaine.

Voici comment je vois le modèle d'un jeu individuel particulier (c'est-à-dire 1 flop, rivière, virage, etc.). Il y a encore beaucoup de travail à faire pour modéliser tous les jeux (par exemple, les jeux à limite utilisent les petites mises/grosses mises au lieu des blinds pour définir les enjeux).

classe publique Carte { public Suit Suit; classement public; public ulong ToCardMask(); }

public enum Suit 
{ 
    Clubs, 
    Diamonds, 
    Hearts, 
    Spades 
} 

public enum Rank 
{ 
    Ace, 
    Deuce, 
    Trey, 
    //... 
    Jack, 
    Queen, 
    King 
} 

public class Game 
{ 
    public GameInfo GameInfo; 
    public TableInfo TableInfo; 
    public List<BettingRound> BettingRounds; 
    public List<Card> CommunityCards; 
    public string Rawtext; 
    public bool WithHero; //?? 
} 

public static class GameExtensions 
{ 
    public static BettingRound Flop(this Game game) 
    { 
     return game.BettingRounds[0]; 
    } 

    public static List<Card> FlopCards(this Game game) 
    { 
     return game.CommunityCards.Take(3).ToList(); 
    } 
} 

public class GameInfo 
{ 
    public GameType GameType; 
    public GameBettingStructure BettingStructure; // Limit, PotLimit, NoLimit 
    public Stakes Stakes; // e.g. { $1, $2 } 
    public long Id; 
    public List<Seat> Seats; 
} 

enum GameType // prob change to a class for extensibility 
{ 
    HoldEm, 
    Razz, 
    StudHi, 
    StudHiLo, 
    OmahaHi, 
    OmahaHiLo 
} 

enum GameBettingStructure 
{ 
    Limit, 
    PotLimit, 
    NoLimit 
} 

class Stakes // probably needs some tweeking for stud games (e.g. bring-in ...) 
{ 
    public Money Ante; 
    public List<Money> Blinds; 
} 

public class Seat 
{ 
    public Player Player; 
    public Money InitialStackAmount; 
    public Money FinalStackAmount; // convienience field can be calculated 
    public List<Card> Hand; 
} 

class Money 
{ 
    public decimal Amount; 
    public Unit Unit; 
} 

enum Unit 
{ 
    USD, 
    EUR, 
    AUD, 
    TournamentDollars 
} 

public class Player 
{ 
    public string Name; 
} 

public class TableInfo 
{ 
    public string Name; 
} 

public class BettingRound 
{ 
    public List<BettingAction> BettingActions; 
} 

public class BettingAction 
{ 
    public abstract Money PotSizeAfter(); 
    public byte SeatNumber; 
} 

public class Fold : BettingAction { } 
public class Call : BettingAction { } 
public class BringIn : BettingAction { } 
public class Complete : BettingAction { } 
public class Bet : BettingAction 
{ 
    public Money Amount; 
} 

public class Raise : Bet { } 
0

au lieu de ronde dans le sous-classement FlopRound TurnRound etc, je voudrais utiliser un attribut dans la rue autour et à l'intérieur d'action ainsi. Statique enum rue {PREFLOP, FLOP, TURN, RIVER};

...