Ответить
03.04.2011, 06:15 #1
Ветеран
Avatar
Регистрация: 16.02.2011
Сообщений: 455
Карма: 21
Инициализация массива строк в классе
 //  DeckOfCards.h
// Определение класса DeckOfCards, представляющего
// колоду игральных карт.

// определение класса DeckOfCards
class DeckOfCards
{
public:
DeckOfCards(); // конструктор инициализирует колоду
void shuffle(); // тасует карты в колоде
void deal(); // сдает карты

private:
int deck[ 4 ][ 13 ]; // представляет колоду карт
}; // конец класса DeckOfCards


//  DeckOfCards.срр
// Определения элемент-функций класса DeckOfCards,
// моделирующего тасование и сдачу колоды игральных карт.

#include <iostream>
using std::cout;
using std::left;
using std::right;

#include <iomanip>
using std::setw;

#include <cstdlib> // прототипы для rand и srand
using std::rand;
using std::srand;

#include <ctime> // прототип для time
using std::time;

#include "DeckOfCards.h" // определение класса DeckOfCards

// конструктор по умолчанию DeckOfCards инициализирует колоду
DeckOfCards::DeckOfCards()
{
// цикл по строкам deck
for ( int row = 0; row <= 3; row++ )
{
// цикл по столбцам в текущей строке deck
for ( int column = 0; column <= 12; column++ )
    {
    deck[ row ][ column ] =0; // установить ячейку в 0
    } // конец внутреннего for
} // конец внешнего for

srand( time( 0 ) ); // засеять генератор случайных чисел
} // конец конструктора по умолчанию DeckOfCards

// перетасовать карты в колоде
void DeckOfCards::shuffle()
{
int row; // представляет масть карты
int column; // представляет численный номинал карты

// для каждой иэ 52 карт случайно выбрать ячейку deck
for ( int card = 1; card <= 52; card++ )
{
do // выбрать новую позицию, пока не найдется свободная
    {
    row = rand() % 4; // случайно выбрать строку
    column = rand() % 13; // случайно выбрать столбец
    } while( deck[ row ][ column ] != 0 ); // конец do/while

// поместить номер карты в выбранную ячейку deck
deck[ row ][ column ] = card;
} // конец for
} // конец функции shuffle

// сдать карты
void DeckOfCards::deal()
{
// инициализировать массив мастей
static const char *suit[ 4 ] =
                            { "Hearts", "Diamonds", "Clubs", "Spades" };

// инициализировать массив номиналов
static const char *face[ 13 ] =
                { "Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven"
                        "Eight", "Nine", "Ten", "Jack", "Queen", "King" };

// для каждой иэ 52 карт
for ( int card = 1; card <= 52; card++ )
{
// цикл по строкам deck
for ( int row = 0; row <= 3; row++ )
    {
// цикл про столбцам в текущей строке deck
    for ( int column = 0; column <= 12; column++ )
        {
// если ячейка содержит текущую карту, вывести карту
        if ( deck[ row ][ column ] == card )
            {
            cout << setw( 5 ) << right << fасе[ column ]
            <<" of " << setw( 8 ) << left << suit[ row ]
            << ( card % 2 == 0 ? 'n' : 't' );
            } // конец if
        } // конец самого внутреннего for
    } // конец внутреннего for
} // конец внешнего for
} // конец функции deal


 //  fig08_27.cpp
// Программа тасования и сдачи карт.
#include "DeckOfCards.h" // определение класса DeckOfCards

int main()
{
DeckOfCards deckOfCards; // создать объект DeckOfCards

deckOfCards.shuffle(); // перетасовать карты колоды
deckOfCards.deal(); // сдать карты колоды
return 0; // успешное завершение
} // конец main 


В книге Дейтелов на стр.543 есть такая программа по тасованию и сдаче карт.
В конце главы есть задания по модернизации этой программы.
У меня возникла необходимость использовать массивы строк, которые служат для обозначения мастей и номиналов карт в других функциях, которые надо добавить согласно заданию. Я попробовал сделать их элементами данных и инициализировать в конструкторе,
чтобы не переписывать в каждую функцию. Программа компилируется, но при выполнении выдает сообщение о необработанном исключении. Как это сделать правильно, может использовать не массивы указателей, а что-то другое? Пока в классах не силен, только
начинаю осваивать.
Хотел в результате получить два массива, что-то типа массива deck к которым можно
было бы обращаться прямо из функций.
Реклама
03.04.2011, 17:21 #2
Ветеран
Avatar
Регистрация: 16.02.2011
Сообщений: 455
Карма: 21
Re: Инициализация массива строк в классе
Эта программа работает, а можно сделать так:

//  DeckOfCards.h
// Определение класса DeckOfCards, представляющего
// колоду игральных карт.
// определение класса DeckOfCards

#include<string.h>
class DeckOfCards
{
public:
DeckOfCards(); // конструктор инициализирует колоду
void shuffle(); // тасует карты в колоде
void deal(); // сдает карты

private:
int deck[ 4 ][ 13 ]; // представляет колоду карт
string сolour[4];
string face_value[13];
}; // конец класса DeckOfCards



Т.е. добавить эти строки в класс, инициализировать их в конструкторе и пользоваться в функциях как и массивом колоды карт обращаясь напрямую.
Вот когда я эти массивы загоняю в элементы данных класса получаю это:

error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "colour"
error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "face_value"
error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
error C2065: face_value: необъявленный идентификатор
error C2065: colour: необъявленный идентификатор
error C2065: face_value: необъявленный идентификатор
error C2065: colour: необъявленный идентификатор


А то приходится в каждый метод класса переписывать эти два массива строк.
03.04.2011, 20:52 #3
Ветеран
Avatar
Регистрация: 21.08.2010
Сообщений: 321
Карма: 19
Re: Инициализация массива строк в классе
// инициализировать массив номиналов
static const char *face[ 13 ] =
                { "Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven"
                        "Eight", "Nine", "Ten", "Jack", "Queen", "King" };


В этой строке запятую поставили, после элемента массива "Seven"? Если нет, то ошибка будет выходить...
03.04.2011, 21:25 #4
Ветеран
Avatar
Регистрация: 16.02.2011
Сообщений: 455
Карма: 21
Re: Инициализация массива строк в классе
Да ,запятую поставил, она собственно и стояла, просто я когда копировал видимо не зацепил ее.
У меня проблемма в другом. Я если в объявление класса помещаю два массива строк
то сразу выходят те ошибки, которые я приводил выше.Нельзя ли эти два массива так же как и массив колоды карт в конструкторе определить, а не создавать его в каждом методе класса?
03.04.2011, 22:44 #5
Ветеран
Avatar
Регистрация: 21.08.2010
Сообщений: 321
Карма: 19
Re: Инициализация массива строк в классе
Алексей, а как задание полностью звучит, по которому вы пишите эту программу? Что-то в книге Дейтелов на указанной выше странице не нашел этого задания (возможно версия скана иная, или еще что-нить)
03.04.2011, 22:49 #6
Ветеран
Avatar
Регистрация: 21.08.2010
Сообщений: 321
Карма: 19
Re: Инициализация массива строк в классе
Алексей писал(а):
Нельзя ли эти два массива так же как и массив колоды карт в конструкторе определить, а не создавать его в каждом методе класса?


Не обязательно в каждом методе объявлять эти массивы строк. Удобнее как закрытые (инкапсулированные - private) поля их описать, а в конструкторе инициализировать один раз и все.

Но все же лучше напишите задание, я попробую сейчас сам реализовать, а там по ходу и разберемся со всеми ошибками
03.04.2011, 23:06 #7
Ветеран
Avatar
Регистрация: 16.02.2011
Сообщений: 455
Карма: 21
Re: Инициализация массива строк в классе
Задания там в конце главы: Указатели и строки-указатели.
Измените программу на рис. 8.27 так, чтобы функция раздачи сдавала по пять
карт для игры в покер. Затем напишите следующие дополнительные функции,
которые могут:
a) Определить, имеется ли на руках у игрока пара.
b) Определить, имеется ли на руках у игрока две пары.
c) Определить, имеется ли на руках тройка (например, три валета).
d) Определить, имеет ли игрок каре (например, четыре туза).
e) Определить, имеется ли на руках флеш (т.е. пять карт одной масти).
f) Определить, имеется ли на руках стрит (т.е. пять карт последовательных
номиналов).
8.13. Используя функции, разработанные в упражнении 8.12, напишите программу,
которая сдает двум игрокам в покер на руки по пять карт и оценивает, чья карта
лучше.
572
Глава 8
8.14. Измените программу, разработанную в упражнении 8.13, таким образом, чтобы
она исполняла роль сдающего. Карты сдающего кладутся «лицом вниз», так что
играющий с программой их не видит. Программа должна затем оценить карту
сдающего и, основываясь на качестве карт, сдающий должен взять себе одну, две
или три карты взамен не устраивающих его карт из первоначально розданных.
После этого программа должна оценить карты сдающего еще раз.
[Предостережение, Это трудная задача!]
8.15. Измените программу из упражнения 8.14 так, чтобы она манипулировала
картами сдающего, а играющий с программой решал бы сам, какие карты ему нужно
менять. Программа должна затем оценивать карты играющих и определять
победителя. Теперь сыграйте с этой программой 20 игр. Кто выиграет большее
количество игр, вы или компьютер? После этого пусть один из ваших друзей сыграет
еще 20 игр с компьютером. Кто выиграет большее количество игр? Основываясь
на результатах этих игр, сделайте соответствующие изменения, которые
позволили бы усовершенствовать вашу программу игры в покер (это также будет трудной
задачей). Сыграйте еще 20 игр. Не стала ли ваша программа играть лучше?
8.16. В программе тасования и сдачи карт, приведенной на рис. 8.25-8.27, мы
преднамеренно использовали неэффективный алгоритм тасования, который может
приводить к бесконечным отсрочкам. В связи с этой проблемой вам предстоит
создать быстродействующий алгоритм тасования, в котором этой опасности просто
не существует.
Модифицируйте программу на рис. 8.25-8.27следующим образом. Начните
с инициализации массива deck так, как показано на рис. 8.36. Измените
функцию shuffle таким образом, чтобы она в цикле по строкам и столбцам массива
перебирала элементы массива по разу и меняла местами значения текущего
элемента и случайно выбранного элемента массива.
Неперетасованный массив deck


Модифицировать надо ту программу, которую я в самом начале выложил
Не обязательно в каждом методе объявлять эти массивы строк. Удобнее как закрытые (инкапсулированные - private) поля их описать, а в конструкторе инициализировать один раз и все.



Вот именно это у меня и не получается. Я тоже хотел по аналогии с массивом:
deck[4][13]

и массивы строк объявить ПРИВАТ, а инициализацию также запихнуть в конструктор , но получаю те самые ошибки(см. выше)
Постараюсь еще раз все по-порядку объяснить: Вот мы имеем ту самую верхнюю программу из учебника состоящую из трех файлов. Она работает, проблем нет. Стал я придумывать по заданию эти дополнительные функции, и у меня получается, что каждый раз приходится массивы эти строковые переписывать, а когда я попытался сделать так, как Вы советуете,
выдаются ошибки. Может я их как-то не так инициализирую в конструкторе. Инициализирую я их точно так, как они написаны в программе, только заменил
static const char *
на string

Заголовок тоже добавил.
А если оставить
static const char *

тоже ошибки какие-то идут. Вобщем-то у меня как раз вопрос о том как правильно пихнуть масситвы строк в ПРИВАТ данные и инициализировать их в конструкторе, чтобы из функций напрямую обращаться как и к колоде карт.
03.04.2011, 23:38 #8
Ветеран
Avatar
Регистрация: 21.08.2010
Сообщений: 321
Карма: 19
Re: Инициализация массива строк в классе
Стал я придумывать по заданию эти дополнительные функции, и у меня получается, что каждый раз приходится массивы эти строковые переписывать...


static const char * 


const нельзя перезаписывать
03.04.2011, 23:39 #9
Ветеран
Avatar
Регистрация: 16.02.2011
Сообщений: 455
Карма: 21
Re: Инициализация массива строк в классе
То есть я что хотел сделать: Допустим программа остается как есть только в функции
 void DeckOfCards::deal()

там где эти массивы строк и используются я хотел оотуда перенести инициализацию этих массивов в конструктор,предварительно записав их в объявлении класса как ПРИВАТ-данные, а в функции пользоваться уже не инициализируя. Ведь массив колоды "виден" во всех методах класса, вот и их как-бы так прописать.
Ответить