Массив для карт блэкджека, строк или целых чисел?

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

В моей игре в блэкджек тузы только 11, а 10, J, Q и K имеют значение 10, независимо от масти. Что упростило бы мне кодирование карт с помощью строк или целых чисел?

Visual Studio C # 2010, приложение Windows Form


person Mr. Bottell    schedule 11.06.2013    source источник
comment
Вопрос с подвохом: ни то, ни другое. Я бы создал специальный Card класс и, возможно, поддержку enum для 13 возможных значений.   -  person Chris Sinclair    schedule 11.06.2013
comment
это звучит намного проще   -  person Mr. Bottell    schedule 11.06.2013
comment
Нет лучшего или простого способа сделать это. Некоторые сказали бы, что это перечисление из 52 значений. Другие сказали бы объект Card со значением и, возможно, перечислениями для масти. Кто-то может найти причину использовать и то, и другое в одном приложении. Вы работаете с людьми, которые никогда не занимались ООП? Тогда, возможно, тебе не стоит использовать объект. Подобные вопросы не подходят для StackOverflow. Воспользуйтесь одним из способов и узнайте, почему он не сработал. Но поймите, что нет такого лучшего способа делать что-либо в программировании, поскольку у всех разные опыт и проекты.   -  person Mark Hildreth    schedule 12.06.2013
comment
Я написал эссе на эту тему здесь . Согласитесь, что разные представления лучше подходят для разных приложений, но строки никогда не являются лучшими.   -  person Lee Daniel Crocker    schedule 12.06.2013


Ответы (4)


Карта - это объект, поэтому сделайте ее отдельным классом.

Следует использовать перечисление масти (сердце, бриллиант, клуб, пика) и перечисление ранга (туз, валет, 10 и т. Д., Упорядоченные соответственно для простоты сравнения). Вы можете получить цвет из костюма, поэтому я бы не предлагал делать цвет параметром конструктора, поскольку он избыточен. На самом деле вам нужны только эти два поля в конструкторе, если вы не планируете дублировать карты, например, если вы используете несколько колод в своей игре. При использовании этих карточек настоятельно рекомендуется использовать список или аналогичный тип, потому что многие операции сортировки встроены. А когда вам нужно перетасовать колоду, используйте тасование Кнута! Вы можете легко найти его с помощью Google, его легко реализовать, он работает быстро и эффективно.

Этот подход принадлежит моему профессору CS, и я тоже склонен его ценить. Чем больше ваш код моделирует реальную жизнь, тем легче его понять и расширить. Вы можете обойтись int или строковыми константами, но это дополнительная работа, которую вам не нужно делать, и они не элегантны.

public class Card
{
    public Suit Suit { get; private set; }
    public Rank Rank { get; private set; }

    public Card(Suit suit, Rank rank)
    {
         this.suit = suit;
         this.rank = rank;
    }
} 
person dkoch74    schedule 11.06.2013

Строки почти никогда не являются лучшим внутренним представлением чего-либо, кроме фактического текста. Струны предназначены для людей; компьютеры используют числа. Для карт это особенно просто, так как карты часто нужно сравнивать по рангу и добавлять по стоимости. Требуется гораздо меньше кода, чтобы сообщить программе, что 12> 11 или добавить 10 к сумме, чем для того, чтобы сообщить ей, что «K»> «Q» или добавить «J» к сумме. Внутреннее использование строк - обычное дело, когда начинающие программисты слишком ленивы, чтобы узнать о представлении данных.

Конечно, в объектно-ориентированном языке, таком как C ++, вы можете использовать объекты, но переменные-члены тех объектов, которые содержат рейтинг и масти карт, должны быть целыми числами, чтобы вы могли индексировать таблицы поиска, сравнивать диапазоны и т. Д.

Я написал эссе о картах здесь.

Для блэкджека, если вам не нужно универсальное представление карты, то идеальным вариантом будет использование целых чисел от 1 до 10. Используйте 1 для тузов, а не 11, это ускорит ваши общие вычисления: вам нужно будет только повысить один туз с 1 до 11, но вам нужно будет понизить рейтинг нескольких с 11 до 1.

Например, если у вас есть массив этих целых чисел, представляющих руку, сложение общей суммы руки выглядит примерно так (конечно, конкретизировано):

int total = 0, acefound = 0, soft = 0;

for (int i = 0; i < cardsinhand; ++i) {
    total += hand[i];
    if (1 == hand[i]) acefound = 1;
}
if (acefound && total < 12) {
    soft = 1;
    total += 10;
}

Просто и невероятно быстро. Если вы представляете реальные карты, то есть у вас будут лицевые карты с рангами 11, 12, 13, тогда просто добавьте туда что-то вроде if (r > 10) r = 10; (еще одна причина сделать тузов 1). Я могу смоделировать миллиарды рук за такие минуты.

person Lee Daniel Crocker    schedule 12.06.2013
comment
Гораздо лучший ответ, чем мой, я должен был найти время, чтобы правильно разложить класс, вместо того, чтобы искать быстрый ответ, особенно будучи поклонником оптимизации, я должен был знать лучше, чем публиковать такой небрежный ответ, рад, что участники поддерживают друг друга до табака на этом сайте! - person Joshua Van Hoesen; 12.06.2013

Консольное приложение Blackjack Пример проекта (C #) GitHub:

https://github.com/koistya/Blackjack

public class Card
{
    public Card(Rank rank, Suite suite)
    {
        this.Rank = rank;
        this.Suite = suite;
        this.IsFaceUp = true;
    }

    public Rank Rank { get; private set; }

    public Suite Suite { get; private set; }

    public bool IsFaceUp { get; private set; }

    public void Flip()
    {
        this.IsFaceUp = !this.IsFaceUp;
    }
}

public enum Rank : byte
{
    Ace   = 1,
    Two   = 2,
    Three = 3,
    Four  = 4,
    Five  = 5,
    Six   = 6,
    Seven = 7,
    Eight = 8,
    Nine  = 9,
    Ten   = 10,
    Jack  = 11,
    Queen = 12,
    King  = 13,
}

public enum Suite : byte
{
    Club    = 1,
    Diamond = 2,
    Heart   = 3,
    Spades  = 4
}
person Konstantin Tarkus    schedule 27.12.2013

enum для 13 возможных значений было бы лучше

person Sunil B N    schedule 11.06.2013