Условие задачи.
Дана колода из 52 карт. Необходимо выдать 5 не повторяющихся карт. Масти и номиналы хранить в двух разных массивах. Использовать класс string нельзя.
Что сделал я?
#include <iostream>
#include <ctime> // если старый компилятор, то заменить на "time.h"
// для отображения используемых в программе символов, измените шрифт консоли на "точечные шрифты"
int main()
{
srand(time(0)); // для генерации псевдорандомных чисел с привязкой к текущему времени
// объявляем и инициализируем константы
const short jack = 11;
const short queen = 12;
const short king = 13;
const short ace = 14;
// используем только нужные объекты
using std::cout;
using std::endl;
using std::cin;
// создаем два массива для хранения мастей и номиналов
char *suit = new char[4]{ 3, 4, 5, 6 }; // 3 ... 6 - коды в ascii для символов мастей
short *face = new short[13]; // номиналы
// заполняем массив номиналов цифрами от 2 до 14,
// где 2 ... 10 - будут выводится как простые числа,
// а 11 ... 14 - как символы, в соотвествии с константами
for (int i = 0; i < 13; i++)
face[i] = i + 2;
cout << " Your Deck : " << endl;
// случайные индексы элементов, которые мы будем выводить
short rand_index_suit;
short rand_index_face;
for (int i = 1; i <= 5; i++) // выдаем 5 карт
{
// генерируем псевдорандомные числа (тут, индексы) и заполняем ими переменные
rand_index_suit = rand() % 4; // от 0 до 3
rand_index_face = rand() % 13; // от 0 до 12
cout << " " << i << ". "; // выводим номер карты
// если элемент с рандомным индексом равен следующему числу, то выводим его в соответствии с написанным ниже
switch (face[rand_index_face])
{
case jack: { // валет
cout << " J";
break;
}
case queen: { // дама
cout << " Q";
break;
}
case king: { // король
cout << " K";
break;
}
case ace: { // туз
cout << " A";
break;
}
default: { // обычное число
cout << " " << face[rand_index_face];
break;
}
}
// выводим масть с рандомным индексом
cout << suit[rand_index_suit] << endl;
}
return 0; // если Visual Studio
}
Что не так с моей программой? Что нужно добавить?
В этом вся суть вопроса. Нужно выдать 5 не повторяющихся карт. А мое решение в худшем случае может выдать такие 5 карт:
K♠ K♠ K♠ K♠ K♠
Здесь я подразумеваю то, что карты могут повторяться в выводе моей программы.
Есть ли варианты решения этой проблемы, придуманные мной?
Откровенно говоря, за ними я и обратился сюда :).
Но один есть:
Выбрать начальную позицию (сгенерировать начальный индекс) в массиве номиналов и с каждым разом увеличивать его на один. Выход за границы массива предусмотрен.
5♠ 6♥ 7♥ 8♣ 9♠
Этот вариант не интересный и простой, как по мне.
Коротко о том, что не так и что нужно сделать
Мое решение может выдать 2 и больше одинаковых карт.
Примеры работы моей программы:
7♦ Q♠ A♣ 2♣ Q♠ - дважды повторилась карта Q♠;
2♦ 5♠ J♣ 2♦ 2♦ - трижды повторилась карта 2♦.
Нужно запретить программе делать такую ересь :).
Точнее говоря, нужно чтобы программа выдала 5 карт без повторов.
Напоминаю, использование класса string в решении этой задачи запрещено.
Надеюсь, я понятно описал свой вопрос. Заранее благодарен за любую вашу помощь!
Вот. Только, простите уж, десятку выдает как 0 :)
int main()
{
int cards[52];
for(int i = 0; i < 52; ++i) cards[i] = i; // Заполнение колоды
for(int i = 0; i < 5; ++i) // Равномерное случайное перемешивание
{ // первых 5 карт с выводом
int j = rand()%(52-i)+i;
int t = cards[j];
cards[j] = cards[i];
cards[i] = t;
cout << "A234567890JQK"[t%13] << "♦♠♥♣"[t/13] << endl;
}
}
Нужно где-то запоминать уже использованные карты.
#include <iostream>
#include <ctime> // если старый компилятор, то заменить на "time.h"
// для отображения используемых в программе символов, измените шрифт консоли на "точечные шрифты"
int main()
{
srand(time(0)); // для генерации псевдорандомных чисел с привязкой к текущему времени
// объявляем и инициализируем константы
const short jack = 11;
const short queen = 12;
const short king = 13;
const short ace = 14;
// используем только нужные объекты
using std::cout;
using std::endl;
using std::cin;
// создаем два массива для хранения мастей и номиналов
char *suit = new char[4]{ 3, 4, 5, 6 }; // 3 ... 6 - коды в ascii для символов мастей
short *face = new short[13]; // номиналы
// заполняем массив номиналов цифрами от 2 до 14,
// где 2 ... 10 - будут выводится как простые числа,
// а 11 ... 14 - как символы, в соотвествии с константами
for (int i = 0; i < 13; i++)
face[i] = i + 2;
cout << " Your Deck : " << endl;
// случайные индексы элементов, которые мы будем выводить
short rand_index_suit;
short rand_index_face;
const short N=5;
short deck_face[N]={};
short deck_suit[N]={};
for (int i = 0; i < N; i++) // выдаем 5 карт
{
bool used=true;
// генерируем псевдорандомные числа (тут, индексы) и заполняем ими переменные
while(used)
{
used = false;
rand_index_suit = rand() % 4; // от 0 до 3
rand_index_face = rand() % 13; // от 0 до 12
for (int j = 0; j < i; j++)
{
if(deck_face[j]==face[rand_index_face] && deck_suit[j]==suit[rand_index_suit])
{
used = true;
break;
}
}
if(!used)
{
deck_face[i] = face[rand_index_face];
deck_suit[i] = suit[rand_index_suit];
}
}
cout << " " << i+1 << ". "; // выводим номер карты
// если элемент с рандомным индексом равен следующему числу, то выводим его в соответствии с написанным ниже
switch (face[rand_index_face])
{
case jack: { // валет
cout << " J";
break;
}
case queen: { // дама
cout << " Q";
break;
}
case king: { // король
cout << " K";
break;
}
case ace: { // туз
cout << " A";
break;
}
default: { // обычное число
cout << " " << face[rand_index_face];
break;
}
}
// выводим масть с рандомным индексом
cout << suit[rand_index_suit] << endl;
}
return 0; // если Visual Studio
}
Как пример, вместо 5 карт сгенерируем все 52 карты в случайном порядке. (изменил только N).
(не могу добавить комментарий так как <50 реп. Напишу тут)
@Harry у Вас, некорректно работает код. Как уже сделали в замечание, иногда могут попасться повторяющиеся карты.
Если количество выбираемых карт настолько сильно меньше размера множества, из которого делается выбор (5 из 52), то эффективнее всего применить "студенческий" алгоритм с запоминанием выбранных карт и повторным выбором
#include <iostream>
#include <cstdlib>
int main(int argc, const char * argv[])
{
const char *const SUITS = "\x3\x4\x5\x6";
const char *const FACES[] = { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" };
unsigned char flags[4][13] = {};
for (unsigned n = 5; n > 0; --n)
{
unsigned suit, face;
do suit = std::rand() % 4, face = std::rand() % 13; while (flags[suit][face]);
flags[suit][face] = true;
std::cout << SUITS[suit] << FACES[face] << std::endl;
}
}
Для задач, в которых количество выбираемых карт сравнимо с размером множества, такой алгоритм подходил бы плохо.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей