#cpp #разработка_игр #случайные_числа
Условие задачи. Дана колода из 52 карт. Необходимо выдать 5 не повторяющихся карт. Масти и номиналы хранить в двух разных массивах. Использовать класс string нельзя. Что сделал я? #include#include // если старый компилятор, то заменить на "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 в решении этой задачи запрещено. Надеюсь, я понятно описал свой вопрос. Заранее благодарен за любую вашу помощь!
Ответы
Ответ 1
Вот. Только, простите уж, десятку выдает как 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; } }Ответ 2
Нужно где-то запоминать уже использованные карты. #include#include // если старый компилятор, то заменить на "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 у Вас, некорректно работает код. Как уже сделали в замечание, иногда могут попасться повторяющиеся карты. Ответ 3
Если количество выбираемых карт настолько сильно меньше размера множества, из которого делается выбор (5 из 52), то эффективнее всего применить "студенческий" алгоритм с запоминанием выбранных карт и повторным выбором #include#include 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; } } Для задач, в которых количество выбираемых карт сравнимо с размером множества, такой алгоритм подходил бы плохо.
Комментариев нет:
Отправить комментарий