0

我正在尝试用 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;
}
4

2 回答 2

1

我将假设你想问的问题——但没有在你的问题中写下来——是“为什么我会收到这个错误消息?”

嗯,有一条不rps()返回值的路径。作为一个人,你可能知道总是只用“rock”、“paper”或“scissors”来调用它,但编译器不知道。在这种情况下,如果您将其称为,应该返回什么?它必须返回一些东西(或抛出异常),因为你已经承诺它会返回一个 std::string。rps()rps()rps(std::string("stone"),std::string("knife"))

你可以做各种各样的事情:

  • 如果没有获胜者,则返回一个空的 std::string,或其他一些特殊值
  • 如果没有任何条件为真,则引发异常
  • 将您的参数类型更改为枚举而不是字符串,以便编译器可以(可能)确定您已经处理了所有 9 种可能的情况

请注意,编译器在这里为您提供帮助为什么在不返回值的情况下从非 void 函数的末尾流出不会产生编译器错误?

于 2020-09-24T10:44:14.717 回答
0

正如在另一个答案中已经提到的,从编译器的角度来看,参数和可以p1包含任何值。p2std::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");
  }
}
于 2020-09-24T12:01:02.540 回答