Объектное представление раундов ставок в покере

Я пишу HandConverter покерной руки. Это мой первый проект, и я стараюсь делать его с самого начала.

У меня уже есть большинство частей, таких как списки игроков, их позиции, размеры стэков, карты для разных досок, какая игра и так далее, но мне сложно представить ставки, особенно различные рейзы, ставки и множественные ставки. звонки от того же игрока.

Я нашел несколько случаев, когда мое наивное решение, основанное на кейсе, не работает, и оно действительно сложно, и мне это не нравится. Поскольку в настоящее время он работает в безлимитном холдеме, я думаю, что у меня будет больше обходных путей, если я захочу реализовать такие игры, как стад, разз и т. Д., Хотя структура ставок, вероятно, такая же.

На данный момент я использую это представление, и я хотел бы особенно улучшить классы Round и Action. Есть ли у вас какие-нибудь предложения для меня?

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. Я также использую список для хранения различных раундов, есть ли лучший способ, например, наследовать класс раунда для флопа, терна и ривера?


person Sven    schedule 18.11.2009    source источник
comment
Не уверен, что должны представлять карты в раунде.   -  person FrustratedWithFormsDesigner    schedule 18.11.2009
comment
он представляет собой 64-битную маску карты. Это используется оценщиком (вычисление силы руки и т. Д.). Я использую   -  person Sven    schedule 18.11.2009


Ответы (6)


Когда вы говорите «первый проект», что вы имеете в виду? Я предполагаю, что вы студент или новичок в программировании.

Исходя из этого предположения, я бы предложил выбрать что-нибудь попроще, чем история покерных рук. Как и в программировании игр, неразумно думать, что на первом этапе программирования игры вы создаете последнюю Call of Duty. Вы начинаете с прорыва и продвигаетесь оттуда.

Если вы не хотите начинать с меньшего, чем я предлагаю, никогда не переходите к кодированию. Когда вы это сделаете, вы будете тратить больше времени на то, чтобы просто крутить колеса, вместо того, чтобы что-то делать.

Например, сначала вам следует подумать о том, что ваша программа будет делать, а что нет. Постарайтесь быть как можно более полным. Это можно сделать из чего-то столь же сложного, используя программу UML, или столь же простого, как ручка и бумага.

Я бы вылил, как хочешь, рука продвигается. Информация, которую вы хотите отслеживать. Как только вы действительно поймете это, ваши структуры данных начнут оживать.

Поскольку вы новичок в программировании, я бы начал писать доказательство концептуального кода. Затем переместите его в свой последний проект. Под доказательством концепции я подразумеваю код, в котором вы просто тестируете идею, чтобы увидеть, как она работает. Например, как будет работать история рук? Можете ли вы создать какую-нибудь «фиктивную» историю и настроить их? В идеале вы должны провести модульное тестирование, но давайте начнем с меньшего.

Важно знать, что вы строите программу, как дом. Вы должны знать, чего вы хотите, а чего не хотите (чертежи). Что такое каждый шаг. И вы медленно наращиваете другие части. Это процесс, который требует времени, но, в конце концов, он того стоит.

person David Basarab    schedule 18.11.2009

Вместо строки для вашего Action.Type вы можете использовать перечисление:

enum BettingAction
{
   Check,
   Bet,
   Call,
   Raise,
   Fold
}
person msergeant    schedule 18.11.2009

Карты могли бы иметь лучшее название, но я предполагаю, что вы имеете в виду общие карты. Я бы сделал его списком карт, тогда подклассы терна и ривера будут иметь только одну карту в списке. Я также предлагаю представить карты так, чтобы это было вам понятно, а затем выполнить преобразование, когда вам нужно взаимодействовать с библиотекой.

person unholysampler    schedule 18.11.2009

Не совсем ответ, связанный с программированием; но стили ставок в Разз или Стад несколько отличаются от Холдема.

1.) Жалюзи нет; скорее анте
2.) Открывающий игрок может сделать ставку или завершить ставку.
3.) Есть больше раундов торговли

У вас довольно хорошее начало. Вы, вероятно, захотите создать List<Hands>, внутри которого List<Rounds>. В противном случае у вас будет огромный список раундов, и вы не сможете сказать, когда началась / закончилась одна рука и началась другая.

Я думаю, вам, вероятно, нужно определить типы ваших действий, и тогда все, вероятно, начнет становиться на свои места. Вот что у меня было бы с типами:

Проверить
Ставка
Фолд
Колл
Рейз (по сути, колл и ставка)

Вы также можете подумать о реализации чего-то вроде «Prior Action» в вашем классе действий; поскольку каждый игрок реагирует на действие перед ним.

Вы также захотите затронуть некоторые нюансы игры; где игрок А ставит 500, а игрок В идет олл-ин 250; поскольку, за исключением этого случая, колл должен соответствовать предыдущей ставке.

person Jim B    schedule 18.11.2009
comment
Каждая рука представлена ​​этим объектом, раунды - это представление префлопа, флопа, терна и ривера. - person Sven; 18.11.2009

Термин Round немного двусмысленен. BettingRound делает это более очевидным. Я не вижу необходимости здесь указывать карты, имя и размер. Размер банка - это функция действий и изменений в течение раунда ставок. Места представляют игру немного лучше, чем список игроков, поскольку это позволяет вам более четко представлять состояние игры (размеры стека и т. Д.). Я не вижу необходимости явно назначать карты на флопе и ривере раундам - ​​просто используйте список карт и некоторые соглашения. например первые три карты = флоп ... первый круг торговли = флоп. Используйте некоторые методы расширения для удобства обращения к флопу для холдема. Используйте версию карточек ulong через преобразование, когда вам нужно ее использовать, вместо того, чтобы загромождать вашу модель предметной области.

Вот как я вижу модель отдельной отдельной игры (например, 1 флоп, ривер, терн и т. Д.). Еще предстоит проделать огромную работу по моделированию всех игр (например, в лимитированных играх для определения ставок используются малые / большие ставки вместо блайндов).

общедоступный класс Card {общедоступный костюмный костюм; общественный ранг; публичный 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 { }
person Joshka    schedule 28.11.2009

вместо SubClassing Round в FlopRound TurnRound и т. д. я бы использовал атрибут Street внутри раунда, а также в Action.

статическое общедоступное перечисление Street {PREFLOP, FLOP, TURN, RIVER};

...

person Alix Martin    schedule 16.12.2009