Я пишу программу на 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 ответа
Интервал
Прежде всего, я бы порекомендовал исправить ваш интервал и табуляцию. Рекомендуется четыре места для каждого уровня вложенности. Это делает ваш код много более читабельный.
Ошибка
В вашем коде есть довольно очевидная ошибка, которую я заметил при первом проходе. Это то, как вы сравниваете количество компьютеров с количеством пользователей. Например, взгляните на эту строку:
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;
}
Простые ошибки
в первую очередь, в вашем коде нет правильного интервала, что делает его нечитаемым.
во-вторых, много повторений. Когда вам нужно проверить множество условий, подумайте об использовании 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 редактирует свое сообщение, чтобы решить проблему и сделать свое сообщение по теме, они могут сделать ваш ответ спорным. На такие вопросы рекомендуется не отвечать.. Совет: нужно ответить на множество вопросов по теме; вы быстрее заработаете себе репутацию, если проанализируете код в вопросах, которые получат большее количество просмотров из-за того, что они соответствуют теме.
— БУДЕТ ВКЛЮЧЕНОᴇᴌᴀ
Обратите внимание, что вопросы, связанные с кодом, который не работает должным образом, на этом сайте не по теме. Если OP редактирует свое сообщение, чтобы решить проблему и сделать свое сообщение по теме, они могут сделать ваш ответ спорным. На такие вопросы рекомендуется не отвечать.. Совет: нужно ответить на множество вопросов по теме; вы быстрее заработаете себе репутацию, если проанализируете код в вопросах, которые получат большее количество просмотров из-за того, что они соответствуют теме.
— БУДЕТ ВКЛЮЧЕНОᴇᴌᴀ
@ SᴀᴍOnᴇᴌᴀ Да, я просмотрел вопрос и пропустил, что они сказали, что это не сработало, моя ошибка.
— Линни