Примеры с использованием структур и объединений



 

Комплексные числа

Множество научных вычислений нуждается в комплексных числах. Напишем АТД для комплексных чисел.

Множество научных вычислений нуждается в комплексных числах. Напишем АТД для комплексных чисел.

В файле complex1.cpp

Struct complex { double real, imag; };

Void assign(complex* pc, double r, double i = 0.0)

{

 pc -> real = r;

 pc -> imag = i;

}

complex add(complex a, complex b)

{

complex temp;

temp.real = a.real + b.real;

temp.imag = a.imag + b.imag;

return temp;

}

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

В следующем фрагменте складываются действительное и комплексное числа:

Double f = 2.5;

Complex w, x, z;

Assign (&x, 5.5, -3.2);    //x = 5.5 – 3.2i

Assign (&w, f);              // w = 2.5 – 0i

Z = add(w, x) ;              // z = 8.0 – 3.2i

 

Пример: Флеш

Нужно определить вероятность раздачи флеша (flush). Флешем называется комбинация из по крайней мере пяти карт одинаковой масти. Смоделируем перетасовку колоды карт с помощью генератора случайных чисел. Программа написана с применением структур для представления необходимых типов данных и требуемой функциональности.

В файле poker . cpp

enum suit {clubs, diamonds, hearts, spades};

typedef int pips;

struct card {

  suit s;

  pips p;

};

struct deck {

card d[52];

};

Решение задать deck как отдельный тип, описывающий колоду, принято при проектировании. Мы можем разрабатывать программу как набор процедур, выполняющих действия исключительно с массивом карт. По сути, колода представляет собой больше, чем просто набор карт. Ведь это 52 совершенно различные карты: по 13 штук треф, бубен, червей и пик. Конечно, объединяя 52 карты в колоду, мы просто моделируем нашу задачу.

pips assign_pips(int n) // n – номер карты (от 0 до 51)  

{

return (n % 13 + 1);

}

suit assign_suit (int n)

{

return (static_cast<suit>(n / 13));

}

Эти две процедуры обеспечивают преобразование из области целых в значения типа pips и suit. Функции преобразования важны для того, чтобы позволить новым заданным пользователем типам взаимодействовать с собственными и заданными ранее типами.

void assign (int n, card& c)

{

c.s = assign_suit (n);

c.p = assign_pips (n);

}

pips get_pip (card c)

{

return c.p;

}

suit get_suit (card c)

{

return c.s;

}

Функция assign() устанавливает соответствие между целыми со значением от 0 до 51 и уникальной парой значений suit и pips. Значение 0 становится тузом треф, а значение 51 – королём пик. Следующие две функции обеспечивают читабельный вывод при распечатке колоды.

void print_card (card c)

{

 cout << c.;

 switch (c.s) {

case clubs:

cout << “T”; // трефы

break;

case diamonds:

cout << “Б”; // бубны

break;

case hearts:

cout << “Ч”; // черви

   break;

case spades:

cout << “П”; // пики

}

}

void print_deck(deck& dk)

{

for (int i = 0; i < 52; ++i)

    print_card (dk.d[i]);

}

Остальные функции используются для перетасовки и раздачи карт.

void shuffle(deck& dk) //перетасовка карт

{

card t;

for (int i = 0; i < 52; ++i) {

int k = ((rand() % (52 – i)));

t = dk.d[i];

dk.d[i] = dk.d[k];

dk.d[k] = t;        // меняем местами две карты

}

}

void deal (int n, int pos, card* hand, deck& dk)

{   // раздача

for (int i = pos; i < pos + n; ++i)

   hand[i - pos] = dk.d[i];

}

void init_deck(deck& dk) // инициализация колоды

{

for (int i = 9; i < 52; ++i)

  assign(i, dk.k[i]);

}

Функция init_deck() вызывает assign() для привязки целых значений к значениям карт. Функция shuffle() использует библиотечный генератор псевдослучайных чисел rand() для того чтобы попарно менять местами карты в колоде. Опыт показывает, что эта функция даёт приемлемое соответствие хорошей перетасовке. Функция deal() по очереди вынимает карты из колоды и раздаёт их по рукам.

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

int main ()

{

card one_hand[9];  // максимум 9 карт при раздаче

deck dk;

int i, j, k, fcnt = 0, sval[4];

int ndeal, nc, nhand;

do {

cout << “\nПо сколько карт раздаём? (от 5 до 9): “;

cin >> nc;

} while (nc < 5 | | nc > 9);

nhand = 52 / nc;

cout << “\nСколько раз играем? “;

cin >> ndeal;

srand (time(null)); // time() для “затравки” rand()

init_deck(dk);

print_deck(dk);

for (k = 0; k < ndeal; k += nhand) {

       if ((nhand + k) > ndeal)

             nhand = ndeal – k;

      shuffle(dk);

       for (i = 0; i < nc * nhand; i += nc) {

          for (j = 0; j <4; ++j)        // обнуление счётчика масти

                sval[j] = 0;

       deal(nc, i, one_hand, dk);  // очередная сдача

       for (j = 0; j < nc; ++j)

           sval[one_hand[j].s]++;  // увеличение счётчика масти

       for (j = 0; j < 4; ++j)

            if (sval[j] >= 5)        // 5 или больше – это флеш

                       fcnt++;

              }

}

cout << “\n\nИз “ << ndeal << “ “;

cout << nc << “- карточных раздач выпало “;

cout << fcnt << “флешей\n”

}

                

Разбор программы poker

card one_hand[9]; // максимум 9 карт при раздаче

deck dk;

int i, j, k, fcnt = 0, sval[4];

int ndeal, nc, nhand;

Это переменные, размещаемые в памяти при входе в блок при выполнении main. Переменная one_hand – это массив из девяти элементов (наибольшего числа карт в одной руке). В нём содержаться розданные из колоды карты. Переменная dk представляет колоду и размещается автоматически. Число карт в одной раздаче хранится в переменной nc, а количество раздач содержится в переменной ndeal. Переменная fcnt служит счётчиком флешей. Массив sval содержит число карт одной масти у игрока.

do {

cout << “\nПо сколько карт раздаём? (от 5 до 9) : “;

cin >> nc;

} while (nc < 5 | | nc > 9);

nhand = 52 / nc;

cout << “\nСколько раз играем? “;

cin >> ndeal;

Программа запрашивает количество карт в одной раздаче. Для продолжения пользователь должен ввести число от 5 до 9. Число раздач, допускаемое размером колоды (52 карты) и количеством карт в одной раздаче (nc), вычисляется и помещается в переменную nhand. Затем программа запрашивает, сколько раз вы хотите «сыграть» в покер, то есть сколько всего раздач необходимо осуществить (ndeal).

srand (time(null));     

init_deck(dk);

print_deck(dk);

for (k = 0; k < ndeal; k += nhand) {

     if ((nhand + k) > ndeal)

            nhand = ndeal – k;

    shuffle(dk);

Функция time() используется генератором случайных чисел для затравки. Переменная dk инициализируется и колода перетасовывается каждый раз при проходе основного цикла.

for (i = 0; i < nc * nhand; i += nc) {

for (j = 0; j < nc; ++j)               // обнуление счётчика масти

    sval[j] = 0;

deal(nc, i, one_hand, dk);   // очередная сдача

for (j = 0; j < nc; ++j)

  sval[one_hand[j].s]++;  // увеличение счётчика масти

for (j = 0; j < 4; ++j)

       if (sval[j] >= 5)        // 5 или больше – это флеш

              fcnt++;

}

Массив slav содержит количество карт каждой масти и инициализируется нулём при каждой сдаче. Функция deal() сдаёт карты в массив one_hand. Выражение one_hand[j].s является значением масти конкретной карты – например 0, если карта трефовая. Затем это выражение служит индексом массива slav, в котором подсчитывают масти. С помощью переменной fcnt считаются флеши, выпавшие во всех этих испытаниях. Так как число испытаний равно ndeal, вероятность флеша будет fcnt/ndeal.

 


Дата добавления: 2020-12-12; просмотров: 70; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!