Создание колоды карт

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

#include <iostream>
#include <vector>

using namespace std;

int main() {
    vector<char> deck;
    char suit[] = {'h','d','c','s'};
    char card[] = {'2','3','4','5','6','7','8','9','10','J','Q','K','A'};
    for (int j=0; j<13; j++) {
        for (int i=0; i<4; i++) {
            deck.push_back(card[j] suit[i]);
        }       
    }

    return 0;
}

Я знаю, что моя проблема начинается с того, что я пытаюсь присвоить символу значение «10». Очевидно, я не смог заставить это скомпилировать, но я уверен, что когда я попытаюсь присвоить значения карт векторной колоде, я также получу ошибку, так как я использовал тип переменной 'char'. Мне кажется, что знание того, какой тип переменной использовать, убивает. Кроме того, будет 'deck.push_back (card [j] suit [i]); » быть правильным кодом для объединения карты и масти, или вам нужно поставить что-то между картой [j] и мастью [i]? Я был бы признателен, если бы кто-нибудь из вас мог вести меня в правильном направлении. Также в качестве небольшого примечания, это часть домашнего задания, поэтому, пожалуйста, не давайте мне просто целые блоки кода. Спасибо за вашу помощь.

И ваш профессор подумает, что вы блестяще справитесь с домашним заданием на этой неделе :)

Chris Kessel 25.10.2008 02:07

Итак ... чем ты закончил?

dlamblin 28.10.2008 00:59
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
2
25 686
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

Используйте букву «Т» вместо 10.

Вы пробовали заменить J на ​​11, Q на 12 и K на 13? Тогда вы могли бы использовать integers вместо characters. Позже замените 11-13 соответствующей буквой.

Вы можете использовать uint8_t из stdint.h в качестве целочисленного типа, и ваша структура будет такого же размера, как если бы вы использовали char.

Ted Percival 11.07.2009 03:59
Ответ принят как подходящий

Попробуйте создать класс Card с мастью и картой в качестве члена и установить его как тип вектора. Нравиться

public class Card {
 public:
  Card(char suit, char card);
  char suit, card;
};

int main() {
    vector<Card> deck;
    char suit[] = {'h','d','c','s'};
    char card[] = {'2','3','4','5','6','7','8','9','T','J','Q','K','A'};
    for (int j=0; j<13; j++) {
        for (int i=0; i<4; i++) {
                deck.push_back(new Card(card[j],suit[i]));
        }               
    }
    return 0;
}

также использование перечислений вместо символов в масти и карте сделало бы его более понятным.

Я думаю, у вас все еще будет проблема с «10» в массиве символов.

Dave DuPlantis 24.10.2008 21:10

Подумайте о перечислениях для масти и ранга.

Martin York 24.10.2008 21:13

Используйте sizeof (карта) и sizeof (масть) вместо магических чисел 13 и 4.

Ted Percival 11.07.2009 03:57

Если вы используете Enums для лица и масти, как вы заполняете колоду? Вы не можете перебирать перечисления и не можете искать перечисления по их значениям, насколько мне известно?

Rimer 11.10.2011 07:50

это должна быть векторная колода <Card *>; если вы нажмете новую Карту в векторе.

neeta 25.02.2015 21:09

Как упоминалось другими, вы можете использовать «T» для десяти, J, Q и K для цифр. Что касается push_back .. поскольку колода - это вектор символов, вы можете передать только один символ в push_back в качестве аргумента. Передача значения карты (1 ... 9, T, J, Q, K) и его набора не работает.

Я лично создал бы небольшую структуру для представления карты со свойством Value и Suite. Затем вы можете сделать свою колоду вектором карт.

Отредактировано: исправлено последнее слово, так как вектор (меньше) Карточка (больше) визуализировалась как вектор (ничего).

Ну, во-первых, deck [0] - это один символ, но вы пытаетесь вставить в него «2h». (на данный момент мы проигнорируем то, как вы это делаете, неправильно.)

По сути, вам нужно сделать деку vector<std::string>. Сделайте card массивом const char * s и преобразуйте элементы в строку.

затем используйте:

deck.push_back(std::string(card[j]) + suit[i]);

Я думаю, что это хороший подход - использовать строки вместо символов.

Dave DuPlantis 24.10.2008 21:11

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

enum SUIT { HEART, CLUB, DIAMOND, SPADE }; 
enum VALUE { ONE, TWO, THREE, ..., TEN, JACK, QUEEN, KING};

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

В этом случае вы можете сэкономить дополнительное программирование и избавиться от лишних хлопот, задав для карт значения int (1-13) вместо значений символ.

За исключением того, что в блэкджеке несколько разных карт имеют одинаковое естественное значение, а одна карта имеет два значения.

DJClayworth 24.10.2008 21:35

Верно, но у вас будет та же проблема с символами, и вы можете упростить условия для проверки следующим образом: 1: значение по умолчанию 1 (Ace) равно 11, если ваша сумма уже не превышает 21, и в этом случае это 1 . 2: Если значение карты больше 10, сделайте его равным 10, иначе используйте его собственное значение.

Drek 24.10.2008 21:47

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

На выходе преобразовать в «A» или «ACE» и т. д.

То, как вы это моделируете, действительно зависит от того, что вы пытаетесь сделать.

Вы создаете настоящую игру, а структуры данных должны поддерживать игровой процесс?

Если это так, я бы создал класс карты с полем перечисления для масти и числовым типом (со значениями от 1 до 13) для номинала.

С другой стороны, если вы создаете приложение для анализа или ИИ-плеер, модель может немного отличаться.

Несколько лет назад я написал симулятор для расчета вероятностей в различных сценариях Техасского Холдема, и мне хотелось, чтобы он ДЕЙСТВИТЕЛЬНО быстро вычислял числа. Я начал с очень простой модели (класс карты, перечисление мастей и т. д.), Но после долгого профилирования и оптимизации я получил побитовое представление.

Каждая карта представляла собой шестнадцатибитовое значение, причем тринадцать старших битов представляли номинальную стоимость, два младших бита представляли масть, а бит [2] был специальным флагом, указывающим туз (использовался только в тех случаях, когда в стрите A2345 может появиться туз).

Вот несколько примеров:

0000000000001001  <----  Two of hearts
0100000000000011  <----  King of spades
1000000000000110  <----  Ace of diamonds

^^^^^^^^^^^^^            ("face-value" bits)
             ^           ("low-ace" flag)
              ^^         ("suit" bits)

Вы можете себе представить, как с таким дизайном очень быстро искать пары, тройки и стриты (флеши немного сложнее).

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

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

Так что хорошенько подумайте, как вы хотите моделировать:

  • Каждая карта
  • Рука игрока
  • Вся колода
  • Состояние стола ... включая все руки игроков (включая игроков, которые разделили свою начальную руку), возможно, башмак из шести колод, стопку сброса и т. д.

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

Веселиться!!!

Поскольку это домашнее задание для C++, я предполагаю, что вы должны использовать классы. В противном случае используйте перечисления, а если это был C, используйте структуру или что-то в этом роде.

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

Я никогда не писал простой C, но я имею в виду что-то вроде этого:

typedef struct struct_card {
  unsigned short int suit:2;
  unsigned short int card:4;
//  unsigned short int valu:4;
} card;

int main() {
  card a_card;
  card std_deck[52];
  const unsigned short int rummy_value[13] = {1,2,3,4,5,6,7,8,9,10,10,10,10};
  const char *std_card_name[13] = {"Ace","Two","Three","Four","Five","Six",
    "Seven","Eight","Nine","Ten","Jack","Queen","King"};
  const char *std_suit_name[4] = {"Spades","Clubs","Hearts","Diamonds"};

  int j, k, i=0;
  for(j=0; j<4; j++){
    for(k=0; k<13; k++){
      a_card.suit=j; a_card.card=k;
      std_deck[i++] = a_card;
    }
  }

  //check our work
  printf("In a game of rummy:\n");
  for(i=0;i<52;i++){
    printf("  %-5s of %-8s is worth %2d points.\n",
        std_card_name[std_deck[i].card],
        std_suit_name[std_deck[i].suit],
        rummy_value[std_deck[i].card]);
  }

  //a different kind of game.
  enum round_mode {SHEILD_TRUMP, FLOWER_TRUMP, BELL_TRUMP, ACORN_TRUMP, BOCK, GEISS} mode;
  const card jass_deck[36] = {
    {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},
    {1,1},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},
    {2,2},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},
    {3,3},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},
  };
#define JASS_V {11,0,0,0,0,10,2,3,4}
  const unsigned short int jass_value[9] = JASS_V;
#define JASS_TRUMP_V {11,0,0,0,14,10,20,3,4}
  const unsigned short int jass_trump_value[9] = JASS_TRUMP_V;
#define JASS_BOCK_V {11,0,0,8,0,10,2,3,4}
  const unsigned short int jass_bock_value[9] = JASS_BOCK_V;
#define JASS_GEISS_V {0,11,0,8,0,10,2,3,4}
  const unsigned short int jass_geiss_value[9] = JASS_GEISS_V;
  const char *jass_card_name[9] = {"Ace","Six","Seven","Eight","Nine","Banner",
    "Under","Ober","King"};
  const char *jass_suit_name[4] = {"Sheilds","Flowers","Bells","Acorns"};
  const unsigned short int jass_all_value[6][4][9] = {
    { JASS_TRUMP_V, JASS_V, JASS_V, JASS_V },
    { JASS_V, JASS_TRUMP_V, JASS_V, JASS_V },
    { JASS_V, JASS_V, JASS_TRUMP_V, JASS_V },
    { JASS_V, JASS_V, JASS_V, JASS_TRUMP_V },
    { JASS_BOCK_V, JASS_BOCK_V, JASS_BOCK_V, JASS_BOCK_V },
    { JASS_GEISS_V, JASS_GEISS_V, JASS_GEISS_V, JASS_GEISS_V }
  };

  //check our work 2: work goes on summer vacation
  printf("In a game of jass with trump (Sheilds | Flowers | Bells | Acorns) | Bock | Geiss\n");
  for(i=0;i<36;i++){
    printf("  %-6s of %-7s is worth %8d%10d%8d%9d%8d%8d\n",
        jass_card_name[jass_deck[i].card],
        jass_suit_name[jass_deck[i].suit],
        jass_all_value[SHEILD_TRUMP][jass_deck[i].suit][jass_deck[i].card],
        jass_all_value[FLOWER_TRUMP][jass_deck[i].suit][jass_deck[i].card],
        jass_all_value[BELL_TRUMP][jass_deck[i].suit][jass_deck[i].card],
        jass_all_value[ACORN_TRUMP][jass_deck[i].suit][jass_deck[i].card],
        jass_all_value[BOCK][jass_deck[i].suit][jass_deck[i].card],
        jass_all_value[GEISS][jass_deck[i].suit][jass_deck[i].card]);
  }
  return 0;
}

Результат выглядит так:

In a game of rummy:
  Ace   of Spades   is worth  1 points.
  Two   of Spades   is worth  2 points.
  Three of Spades   is worth  3 points.
  Four  of Spades   is worth  4 points.
  Five  of Spades   is worth  5 points.
...
  Nine  of Diamonds is worth  9 points.
  Ten   of Diamonds is worth 10 points.
  Jack  of Diamonds is worth 10 points.
  Queen of Diamonds is worth 10 points.
  King  of Diamonds is worth 10 points.
In a game of jass with trump (Sheilds | Flowers | Bells | Acorns) | Bock | Geiss
  Ace    of Sheilds is worth       11        11      11       11      11       0
  Six    of Sheilds is worth        0         0       0        0       0      11
  Seven  of Sheilds is worth        0         0       0        0       0       0
  Eight  of Sheilds is worth        0         0       0        0       8       8
  Nine   of Sheilds is worth       14         0       0        0       0       0
  Banner of Sheilds is worth       10        10      10       10      10      10
...
  Under  of Acorns  is worth        2         2       2       20       2       2
  Ober   of Acorns  is worth        3         3       3        3       3       3
  King   of Acorns  is worth        4         4       4        4       4       4

Блэкджек - это скучно. Этот код компилируется.

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

class Card
{
public:
    enum ESuit
    {
        kSuit_Heart,
        kSuit_Club,
        kSuit_Diamond,
        kSuit_Spade,
        kSuit_Count
    };

    enum ERank
    {
        kRank_Ace,
        kRank_Two,
        kRank_Three,
        kRank_Four,
        kRank_Five,
        kRank_Six,
        kRank_Seven,
        kRank_Eight,
        kRank_Nine,
        kRank_Ten,
        kRank_Jack,
        kRank_Queen,
        kRank_King,
        kRank_Count
    };

    static int const skNumCards = kSuit_Count * kRank_Count;

    Card( int cardIndex )
    : mSuit( static_cast<ESuit>( cardIndex / kRank_Count ) )
    , mRank( static_cast<ERank>( cardIndex % kRank_Count ) )
    {}

    ESuit GetSuit() const { return mSuit );
    ERank GetRank() const { return mRank );

private:
    ESuit mSuit;
    ERank mRank;
}

Теперь его очень просто добавить к этому классу, чтобы получить от него все, что вы хотите. Создать список так же просто, как показано ниже.

rstl::vector<Card> mCards;
mCards.reserve( Card::skNumCards );

for ( int cardValue = 0; cardValue < Card::skNumCards; ++cardValue )
{
    mCards.push_back( Card( cardValue ) );
}

Вам нужно перетасовать?

#include <algorithm>
std::random_shuffle( mCards.begin(), mCards.end() );

Как насчет того, чтобы посмотреть, какова ценность первой карты?

if ( mCards[0].GetSuit() == Card::kRank_Club && mCards[0].GetRank() == Card::kRank_Ace )
{
    std::cout << "ACE OF CLUBS!" << std::endl;
}

Я не компилировал ничего из этого, но это должно быть близко.

Когда я создал мой класс колоды карт C++, я столкнулся с несколькими собственными проблемами. Во-первых, я пытался преобразовать мой класс колоды карт PHP в C++ с минимальной удачей. Я решил сесть и просто изложил это на бумаге. Я решил использовать объектно-ориентированную установку, в основном потому, что считаю ее наиболее простой в использовании для расширения. Я использую объекты Открытка и Палуба, поэтому, например, если вы хотите поместить 10 колод в Обувь вашей игры в блэкджек, вы можете создать 10 колод, что было бы достаточно просто, потому что я решил сделать все самодостаточным. Фактически, он настолько самодостаточен, что для создания вашей обуви код будет следующим:

#include "AnubisCards.cpp"

int main() {

    Deck *shoe = new Deck(10);

}

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

В любом случае, я сгенерировал колоду, создав массив из 52 объектов Card. Колоды достаточно просты, потому что вы знаете, что у вас есть 4 костюма и 13 карт в каждой масти, вы также знаете, что у вас есть 2,3,4,5,6,7,8,9,10, валет, дама, король, туз в каждой масти. Это никогда не изменится. Поэтому я использовал две петли, одну для Подходить, а другую для Ценить.

Это было примерно так:

for(int suit = 1; suit <= 4; suit++){
    for(int card = 1; card <= 13; card++){
        // Add card to array
    }
}

Теперь вы заметите, что в каждом из этих циклов я использую целочисленное значение. Причина проста, карты - это числа. 4 костюма. 13 значений. Даже числовое значение в игре Блэкджек. Номинальное значение, пока вы не нажмете лицевые карты, которые имеют числовое значение 10, пока вы не нажмете туз, который имеет числовое значение 1 или 11. Все - числа. Таким образом, вы можете использовать эти числа не только для определения значения карты, но и для определения масти карты и числа в числовой последовательности.

Одна из идей - хранить карту в классе Card с символьными или строковыми именами карт, где 1,2,3 ... являются индексами для каждой.

Другие вопросы по теме