Камень-Ножницы-Бумага-Ящерица-Спок Программа C ++ [closed]

Я пишу программу на C ++, которая включает в себя поворот «Камень, ножницы, бумага». Как добавленные Ящерица и Спок влияют на игру, очень просто, и вы можете найти его, если хотите, но в этом нет необходимости, поскольку я на 99% уверен, что моя проблема связана с форматированием моих операторов if-else.

На каждой итерации, независимо от того, какую конфигурацию выбирает компьютер или пользователь, результат всегда один и тот же, т. Е. «Ты победил! :)». Даже в тех случаях, когда пользователь должен был привязать, или пользователь должен был проиграть. Если у вас есть опыт, вы, вероятно, очень легко поймете, в чем я ошибаюсь, пожалуйста, посмотрите. Прошу прощения за запутанные фигурные скобки, но ввод моего кода был очень сложным, поэтому мне пришлось добавить случайные отступы, чтобы сделать его форматным.

#include <iostream>
int main(){

srand(time(NULL));
int computer = rand() % 5 + 1;

int user = 0;

std::cout << "=============================================n";
std::cout << "Rock    Paper    Scissors    Spock    Lizard!n";
std::cout << "=============================================n";
std::cout << "1) Rockn";
std::cout << "2) Papern";
std::cout << "3) Scissorsn";
std::cout << "4) Lizardn";
std::cout << "5) Spockn";
std::cout << "n";
std::cout << "Shoot!n";

std::cin >> user;
std::cout << "Computer chose: " << computer << "n";

if(user == 1){
if(computer == 3 || 4){
  std::cout << "You win! :)n";
}
else if(computer == 1){
  std::cout << "You tied! :/n";
}
else{
  std::cout << "Computer wins! :(n";
}
    } 
else if(user == 2){
if(computer == 1 || 5){
  std::cout << "You win! :)n";
}
else if(computer == 2){
  std::cout << "You tied! :/n";
}
else{
  std::cout << "Computer wins! :(n";
} 
 }
else if(user == 3){
if(computer == 2 || 4){
  std::cout << "You win! :)n";
}
else if(computer == 3){
  std::cout << "You tied! :/n";
}
else{
  std::cout << "Computer wins! :(n";
}    
}
else if(user == 4){
if(computer == 2 || 5){
  std::cout << "You win! :)n";
}
else if(computer == 4){
  std::cout << "You tied! :/n";
}
else{
  std::cout << "Computer wins! :(n";
} 
  }
else{
if(computer == 1 || 3){
  std::cout << "You win! :)n";
}
else if(computer == 5){
  std::cout << "You tied! :/n";
}
else{
  std::cout << "Computer wins! :(n";
}
 }
  }

2 ответа
2

Интервал

Прежде всего, я бы порекомендовал исправить ваш интервал и табуляцию. Рекомендуется четыре места для каждого уровня вложенности. Это делает ваш код много более читабельный.

Ошибка

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

if (user == 0 || 1)

Новичку это выглядит как if user == 0 OR user == 1, но здесь этого не происходит. Вместо этого это только проверка, равен ли пользователь 0, ИЛИ если 1 истинно. И 1 всегда верно. Это может привести к неожиданному поведению. Посмотри:

if (user == 0 || 1) { 
    std::cout << "Greetings!" << std::endl; 
} else {
    std::cout << "Hello!" << std::endl;
}

Теперь, если я только войду 0, Я получу ожидаемый результат только «Привет!». Однако, если я введу буквально любой другой номер, я получу только «Привет!», А не «Привет!».

Репетиция

У тебя есть тонны повторяющегося кода. Вы можете упростить это, сначала проверив, совпадают ли входные данные компьютеров с данными пользователей в начале программы. Тогда вам не придется постоянно проверять козу if/else кусок.

if (computer == user) {
    std::cout << "You tied! :/" << std::endl;
    return 0;
}

Тогда вы можете просто предположить, что пользователь проигрывает в начале.

std::string message = "Computer wins! :(";

Теперь вам нужно только проверить условия выигрыша, и если они выполнены, вы измените переменную сообщения.

if (
    (user == 1 && (computer == 3 || computer == 4)) ||
    (user == 2 && (computer == 1 || computer == 5)) ||
    (user == 3 && (computer == 2 || computer == 4)) ||
    (user == 4 && (computer == 2 || computer == 5)) ||
    (user == 5 && (computer == 1 || computer == 3))
) message = "You win! :)";

Затем вы просто выводите переменную сообщения.

std::cout << message << std::endl;

Конец

В целом, после внесения этих изменений ваш код теперь выглядит так:

#include <iostream>

int main() {

    srand(time(NULL));
    int computer = rand() % 5 + 1;
    int user = 0;

    std::cout << "=============================================n";
    std::cout << "Rock    Paper    Scissors    Spock    Lizard!n";
    std::cout << "=============================================n";
    std::cout << "1) Rockn";
    std::cout << "2) Papern";
    std::cout << "3) Scissorsn";
    std::cout << "4) Lizardn";
    std::cout << "5) Spockn";
    std::cout << "n";
    std::cout << "Shoot!n";

    std::cin >> user;
    std::cout << "Computer chose: " << computer << "n";

    if (computer == user) {
        std::cout << "You tied! :/" << std::endl;
        return 0;
    }

    std::string message = "Computer wins! :(";

    if (
        (user == 1 && (computer == 3 || computer == 4)) ||
        (user == 2 && (computer == 1 || computer == 5)) ||
        (user == 3 && (computer == 2 || computer == 4)) ||
        (user == 4 && (computer == 2 || computer == 5)) ||
        (user == 5 && (computer == 1 || computer == 3))
    ) message = "You win! :)";

    std::cout << message << std::endl;

    return 0;
}

  • Обратите внимание, что вопросы, связанные с кодом, который не работает должным образом, на этом сайте не по теме. Если OP редактирует свое сообщение, чтобы решить проблему и сделать свое сообщение по теме, они могут сделать ваш ответ спорным. На такие вопросы рекомендуется не отвечать.. Совет: нужно ответить на множество вопросов по теме; вы быстрее заработаете себе репутацию, если проанализируете код в вопросах, которые получат большее количество просмотров из-за того, что они соответствуют теме.

    — БУДЕТ ВКЛЮЧЕНОᴇᴌᴀ

  • @ SᴀᴍOnᴇᴌᴀ Да, я просмотрел вопрос и пропустил, что они сказали, что это не сработало, моя ошибка.

    — Линни

Простые ошибки

в первую очередь, в вашем коде нет правильного интервала, что делает его нечитаемым.

во-вторых, много повторений. Когда вам нужно проверить множество условий, подумайте об использовании switch или автоматизировать каким-либо образом.

в-третьих, в вашем if утверждение:

if (computer == 2 || 5)

Здесь if оператор вернется true каждый раз с 5 не равно 0. Вы должны переписать его так:

if (computer == 2 || computer == 5)

Расширенный совет

Я нашел эти правила в другой ветке:
Объяснение правил
Простите за плохой рисунок.

Я рекомендую создать алгоритм поиска победителя. Глядя на «круг» выше, вы проигрываете, если у вашего оппонента что-то в двух шагах впереди вас или на один шаг позади. Во-первых, лучше создать enum для хранения этих вариантов.

enum Choice: int
{ 
    ROCK = 0,
    PAPER,
    SCISSORS,
    LIZARD,
    SPOCK,
    ITEMS_COUNT
};

Здесь я указал enum введите явно, потому что я использую это число позже в математике с целыми числами. Последний элемент здесь содержит точное количество вариантов, если мы не меняем значения предыдущих элементов.

Следующий шаг — найти победителя, используя указанное выше правило. Мы можем найти проигрышные условия таким простым способом:

int lose1 = ( user + 2 ) % Choice::ITEMS_COUNT,
    lose2 = ( user - 2 ) % Choice::ITEMS_COUNT;

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


Другая рекомендация касается вывода вашего меню. Конкатенация строк и cout вызовы каналов могут иногда сказываться на вашей производительности. В этой конкретной ситуации лучше сохранить полную таблицу меню в постоянной памяти, а затем просто распечатать ее с помощью cout. Вероятно, вы захотите распечатать его в игровом цикле, поэтому лучше перенести этот код в функцию. Вы также можете сделать это inline так как функция довольно мала.

inline void printMenu()
{
    static const std::string menu =
    "=============================================n"
    "Rock    Paper    Scissors    Spock    Lizard!n"
    "=============================================n"
    "1) Rockn"
    "2) Papern"
    "3) Scissorsn"
    "4) Lizardn"
    "5) Spockn"
    "n"
    "Shoot!n";
    std::cout << menu;
}

И последнее, но не менее важное: вы должны проверить ввод, потому что это может привести к сбою вашего приложения. Рассмотрите возможность использования while петля с cin.fail() и проверка границ. Можно написать примерно так:

int user = -1;
printMenu();
std::cin >> user;
while(std::cin.fail() || user < 0 || user > 5)
{
    std::cout<<"Error!n";
    std::cin.clear();
    printMenu();
    std::cin>>user;
}

cin.clear() здесь важен, поскольку он сбрасывает состояние отказа.


Код

Вот мой код для этой проблемы:

#include <iostream>
#include <string>

enum Choice: int
{ 
    ROCK = 0,
    PAPER,
    SCISSORS,
    LIZARD,
    SPOCK,
    ITEMS_COUNT
};

int userWon(const int&, const int&);

inline void printMenu();

int getInput();

int main()
{
    srand(time(NULL));
    int user = getInput();
    int computer = rand() % 5 + 1;
    std::cout << "Computer chose: " << computer << "n";
    int result = userWon(user, computer);
    if( result == 1)
        std::cout << "You win!";
    else if ( result == -1 )
        std::cout << "Computer wins!";
    else
        std::cout << "Tie!";
    
    return 0;
}

inline void printMenu()
{
    static const std::string menu =
    "=============================================n"
    "Rock    Paper    Scissors    Spock    Lizard!n"
    "=============================================n"
    "1) Rockn"
    "2) Papern"
    "3) Scissorsn"
    "4) Lizardn"
    "5) Spockn"
    "n"
    "Shoot!n";
    std::cout << menu;
}

int getInput()
{
    int user = -1;
    printMenu();
    std::cin >> user;
    while(std::cin.fail() || user < 0 || user > 5)
    {
        std::cout<<"Error!n";
        std::cin.clear();
        printMenu();
        std::cin>>user;
    }
    return user;
}

int userWon(const int& user, const int& computer)
{
    int res = 0;
    if( user != computer )
    {
        int lose1 = ( user + 2 ) % Choice::ITEMS_COUNT,
            lose2 = ( user - 2 ) % Choice::ITEMS_COUNT;
        if( computer == lose1 || computer == lose2 )
            res = -1;
        else
            res = 1;
    }
    return res;
}

Вы также можете проверить это на godbolt.org.

  • Обратите внимание, что вопросы, связанные с кодом, который не работает должным образом, на этом сайте не по теме. Если OP редактирует свое сообщение, чтобы решить проблему и сделать свое сообщение по теме, они могут сделать ваш ответ спорным. На такие вопросы рекомендуется не отвечать.. Совет: нужно ответить на множество вопросов по теме; вы быстрее заработаете себе репутацию, если проанализируете код в вопросах, которые получат большее количество просмотров из-за того, что они соответствуют теме.

    — БУДЕТ ВКЛЮЧЕНОᴇᴌᴀ

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *