Хобрук: Ваш путь к мастерству в программировании

Попытка сделать программу "Камень, ножницы, бумага" с enum на С++

Я беру курс C++ и выполняю задание, включающее перечисления и случайный выбор. Мой код кажется сломанным. Мое перечисление продолжает рассматриваться как int, а не char, и XCode продолжает давать мне ожидаемый идентификатор в строке с моим перечислением. Логика игры использует символы, а не целые числа. Как я могу это исправить?

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <random>
#include <time.h>

int main()
{
    std::cout << "Let's play some Rock, Papers, and Scissors!\nEnter a choice to Start: R, P, or S!" << std::endl;
    char pInput;
    std::cin >> pInput;
    srand( time(NULL) );
    int cInput = rand() % 3; //Computer chooses number mapped to chars R, P, or S
    enum class RockPaperScissors { 'R', 'S', 'P' };
    if( pInput == 'R' && cInput == 'R' )
    {
        std::cout << "You tied with me!" << std::endl;
    }
    else if( pInput == 'R' && cInput == 'S' )
    {
    std::cout << "Drats! You win!" << std::endl;
    }
    else if( pInput == 'R' && cInput == 'P' )
    {
        std::cout << "Hah! Here comes the Hug of Death!" << std::endl;
    }
    else if( pInput == 'S' && cInput == 'S')
    {
        std::cout << "Looks like we tied!" << std::endl;
    }
    else if( pInput == 'S' && cInput == 'R')
    {
        std::cout << "Hah! I smashed you, so I win!" << std::endl;
    }
    else if( pInput == 'S' && cInput == 'P')
    {
        std::cout << "Drats! You win!" << std::endl;
    }
    else if( pInput == 'P' && cInput == 'P')
    {
        std::cout << "Drats! We tied!" << std::endl;
    }
    else if( pInput == 'P' && cInput == 'S')
    {
        std::cout << "Hah! I win, because I'm a scissor!" << std::endl;
    }
    else if( pInput == 'P' && cInput == 'R')
    {
        std::cout << "Drats! You gave me the Hug of Death!" << std::endl;
    }
}
12.09.2015

  • На этот вопрос, вероятно, лучше всего ответить ссылкой на хороший источник документации: en.cppreference.com /w/cpp/язык/перечисление 12.09.2015
  • Вы понимаете, что проблема может быть решена намного элегантнее и в 4 раза меньше кода без перечислений? Для реализации логики достаточно целого числа, сложения и модуля, а также опционально массив const char* с 3 элементами для отображения имен. Нет необходимости в длинной цепочке else ifs. 12.09.2015

Ответы:


1

ОП не хватает нескольких деталей, чтобы получить то, что они хотят

enum class RockPaperScissors { 'R', 'S', 'P' };

Не обращая внимания на то, что приведенное выше не компилируется, вернемся к этому через минуту, RockPaperScissors по умолчанию имеет целое число, потому что базовый тип не указан. Вы можете изменить тип, объявив его после имени следующим образом: RockPaperScissors:char

Перечислимый тип — это набор сопоставлений имени со значением. Если вы не вмешаетесь и не установите значение, первое значение начинается где-то и увеличивается. Кто-то, у кого есть копия стандарта, может подтвердить, гарантированно ли это 0 и увеличение на единицу. Я не могу. Дело в том, что фактические значения не должны иметь значения. Если они это делают, явно установите их, чтобы никто не получил сюрприз.

В этом случае мы хотим, чтобы они были конкретными символами. Это может быть так же просто, как

enum class RockPaperScissors:char { R = 'R', S = 'S', P = 'P' };

Но это глупо. Это побеждает смысл перечисления в использовании таких простых имен перечислителей. Перечисление должно, как и переменная, объяснять читателю, что оно представляет. В противном случае мы бы забыли об имени; просто используйте значение и покончите с этим. Итак, вместо этого

enum class RockPaperScissors:char { ROCK = 'R', SCISSORS = 'S', PAPER = 'P' };

Используй это

if( pInput == RockPaperScissors::ROCK && cInput == RockPaperScissors::ROCK )
{
    std::cout << "You tied with me!" << std::endl;
}

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

enum RockPaperScissors:char { ROCK = 'R', SCISSORS = 'S', PAPER = 'P' };
if( pInput == ROCK && cInput == ROCK )
{
    std::cout << "You tied with me!" << std::endl;
}

Круто, да?

Хотя это соответствует требованию ОП, это не принесет большой пользы.

srand( time(NULL) );
int cInput = rand() % 3; //Computer chooses number mapped to chars R, P, or S

Комментарий лежит. Отображение не выполняется, поэтому

if( pInput == ROCK && cInput == ROCK ) 

сравнивает перечисление на основе char с целым числом. Компилятор разрешит это, я надеюсь, с предупреждением, но предоставленное целое число будет 0, 1 или 2. ROCK - это R или 82. Сравнение всегда будет неудачным. Итак, давайте побалуемся с массивами (и полностью проигнорируем тот факт, что rand — отстой. Для реальной работы, а не для работы с заданиями, используйте библиотеку случайных чисел С++ 11. В частности, std::uniform_int_distribution).

enum RockPaperScissors:char { ROCK = 'R', SCISSORS = 'S', PAPER = 'P' };
enum RockPaperScissors rpsmap[] = 
{
    ROCK,
    SCISSORS,
    PAPER
};
enum RockPaperScissors cInput = rpsmap[rand() % 3]; //Computer chooses number mapped to chars R, P, or S

Теперь cInput отображается на R, P или S. Теперь мы можем осмысленно сравнивать pInput и cInput.

Но что, если пользователь введет «Q»? Что тогда?

std::cin >> pInput;

Допускает всевозможные злоупотребления. OP также должен будет охранять это, и после этого будет тонна оптимизации этого if/else if....

12.09.2015

2

enum всегда присваивает своему значению целое число, начиная с 0.

Использовать

pInput == S   //S without quotes

Or

pInput == 1   //Corresponding integer value

И pInput & cInput должны быть типа enum или ineger

12.09.2015
  • Близко, но нет. Не обязательно начинать с нуля. Не обязательно целое число. 12.09.2015
  • Да, я согласен. Но в данном случае происходит вот что. 12.09.2015
  • Новые материалы

    ВЫ РЕГРЕСС ЭТО?
    Чтобы понять, когда использовать регрессионный анализ, мы должны сначала понять, что именно он делает. Вот простой ответ, который появляется, когда вы используете Google: Регрессионный..

    Не зря же это называют интеллектом
    Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..

    LeetCode Проблема 41. Первый пропущенный положительный результат
    LeetCode Проблема 41. Первый пропущенный положительный результат Учитывая несортированный массив целых чисел, найдите наименьшее пропущенное положительное целое число. Пример 1: Input:..

    Расистский и сексистский робот, обученный в Интернете
    Его ИИ основан на предвзятых данных, которые создают предрассудки. Он словно переходит из одного эпизода в другой из серии Черное зеркало , а вместо этого представляет собой хронику..

    Управление состоянием в микрофронтендах
    Стратегии бесперебойного сотрудничества Микро-фронтенды — это быстро растущая тенденция в сфере фронтенда, гарантирующая, что удовольствие не ограничивается исключительно бэкэнд-системами..

    Декларативное и функциональное программирование в стиле LINQ с использованием JavaScript с использованием каррирования и генератора ...
    LINQ - одна из лучших функций C #, которая обеспечивает элегантный способ написания кода декларативного и функционального стиля, который легко читать и понимать. Благодаря таким функциям ES6,..

    Структуры данных в C ++ - Часть 1
    Реализация общих структур данных в C ++ C ++ - это расширение языка программирования C, которое поддерживает создание классов, поэтому оно известно как C с классами . Он используется для..