Камень-ножницы для бумаги C++
Я пытаюсь сделать игру Rock Paper Scissors на C++. Я протестировал свой код на codecademy.com, и он работал правильно, но когда я выполняю его на codewars.com, я получаю эту ошибку:
main.cpp:29:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^
Это мой код:
#include <string>
#include <iostream>
std::string rps(const std::string& p1, const std::string& p2)
{
if (p1 == "rock" && p2 == "paper") {
return "Player 2 won!";
} else if (p1 == "rock" && p2 == "scissors") {
return "Player 1 won!";
} else if (p1 == "rock" && p2 == "rock") {
return "Draw";
} else if (p1 == "paper" && p2 == "rock") {
return "Player 1 won!";
} else if (p1 == "paper" && p2 == "scissors") {
return "Player 2 won!";
} else if (p1 == "paper" && p2 == "paper") {
return "Draw";
} else if (p1 == "scissors" && p2 == "rock") {
return "Player 2 won!";
} else if (p1 == "scissors" && p2 == "paper") {
return "Player 1 won!";
} else if (p1 == "scissors" && p2 == "scissors") {
return "Draw";
}
}
int main() {
std::cout << rps("rock", "scissors") << "\n";
std::cout << rps("rock", "paper") << "\n";
std::cout << rps("rock", "rock") << "\n";
std::cout << rps("scissors", "paper") << "\n";
std::cout << rps("scissors", "rock") << "\n";
return 1;
}
2 ответа
Я предполагаю, что вопрос, который вы хотели задать - но не записали в своем вопросе, - это "почему я получаю это сообщение об ошибке?"
Что ж, есть путь через
rps()
который не возвращает значения. Вы, как человек, могли бы знать, что
rps()
всегда вызывается только с помощью "камень", "бумага" или "ножницы", но компилятор этого не делает. В таком случае, что должно
rps()
вернуться, если вы назовете это как
rps(std::string("stone"),std::string("knife"))
? Он должен что-то вернуть (или вызвать исключение), потому что вы обещали, что он вернет std::string.
Вы можете делать разные вещи:
- вернуть пустой std::string, если нет победителя, или какое-то другое специальное значение
- вызвать исключение, если ни одно из условий не выполняется
- измените тип параметра на перечисление вместо строки, чтобы компилятор мог (возможно) определить, что вы обработали все 9 возможных случаев
Обратите внимание, что здесь вам помогает компилятор. Почему завершение непустой функции без возврата значения не приводит к ошибке компилятора?
Как уже упоминалось в другом ответе, параметры
p1
и
p2
из
std::string rps(const std::string& p1, const std::string& p2)
находятся
std::strings
и может - с точки зрения компилятора - содержать любое значение.
Учитывая, что может быть комбинация
p1
и
p2
для которого не выполняется ни одно из условий. Если вы не вернете значение из
void
функция (кроме
main
) это вызовет неопределенное поведение.
Таким образом, вам нужно либо сгенерировать исключение в этот момент, либо вернуть, например, пустую строку.
Но было бы лучше изменить код, чтобы параметры и возвращаемые типы были перечислениями, а функция сначала проверяла выигрышные ситуации и по умолчанию возвращала, что никто не выиграл.
#include <iostream>
#include <vector>
enum class Winner { kPlayerOne, kPlayerTwo, kNone };
enum class Hand { kRock, kScissors, kPaper };
Winner rps(const Hand &p1, const Hand &p2) {
if (p1 == Hand::kRock && p2 == Hand::kPaper) {
return Winner::kPlayerTwo;
} else if (p1 == Hand::kRock && p2 == Hand::kScissors) {
return Winner::kPlayerOne;
} else if (p1 == Hand::kPaper && p2 == Hand::kRock) {
return Winner::kPlayerOne;
} else if (p1 == Hand::kPaper && p2 == Hand::kScissors) {
return Winner::kPlayerTwo;
} else if (p1 == Hand::kScissors && p2 == Hand::kRock) {
return Winner::kPlayerTwo;
} else if (p1 == Hand::kScissors && p2 == Hand::kPaper) {
return Winner::kPlayerOne;
}
return Winner::kNone;
}
std::string to_string(const Winner &winner) {
if (winner == Winner::kPlayerOne) {
return "Player 1 won!";
} else if (winner == Winner::kPlayerTwo) {
return "Player 2 won!";
} else {
return "Draw";
}
}
int main() {
std::cout << to_string(rps(Hand::kRock, Hand::kScissors)) << "\n";
std::cout << to_string(rps(Hand::kRock, Hand::kPaper)) << "\n";
std::cout << to_string(rps(Hand::kRock, Hand::kRock)) << "\n";
std::cout << to_string(rps(Hand::kScissors, Hand::kPaper)) << "\n";
std::cout << to_string(rps(Hand::kScissors, Hand::kRock)) << "\n";
return 1;
}
Если вам действительно нужно использовать строки в качестве входных данных, вы хотите проверить / преобразовать их за пределами вашего
rps
функция с чем-то вроде этого:
Hand string_to_hand(const std::string &str) {
if (str == "rock") {
return Hand::kRock;
} else if (str == "scissors") {
return Hand::kScissors;
} else if (str == "paper") {
return Hand::kPaper;
} else {
throw std::runtime_error("input is not a valid hand");
}
}