在if语句中使用return

3

我正在使用C#编写一款文本冒险游戏。我想做一个场景,让你遇到一个神奇宝贝。我想要有3个随机出现的神奇宝贝,并且我已经写了一个方法来返回你发现的神奇宝贝的名称。代码如下:

public string choosePokemon()  
{  
    Random random = new Random();  
    int pokemonChosen = random.Next();  
    if (pokemonChosen == 1)  
    {  
        string pokemon = "Pidgey";  
        return pokemon;  
    }  
    if (pokemonChosen == 2)   
    {  
        string pokemon = "Charmander";  
        return pokemon;  
    }  
    if (pokemonChosen == 3)  
    {  
        string pokemon = "Geodude";  
        return pokemon;  
    }  
    return "missingno";  
} 

每当我执行代码时,它会显示“您遇到了missingno!”。 我希望它返回名称并中断方法,返回场景方法。 我在结尾处放置了return“missingno”;,因为Studio会给出错误提示,指出不是所有的代码路径都返回一个值。

2
你认为 random.Next(); 可以产生哪些数字?编辑:好吧,你删掉了没有参数的 Next() 调用。 - Jeppe Stig Nielsen
1
除了下面所有的答案都已经解释了这个问题,你可能不应该在每次调用方法时创建一个新的 Random 实例。 - HasaniH
您每次调用都在重新创建随机类,这将一遍又一遍地从相同的种子开始。因此,它将始终返回相同的序列,但仅选择第一个(请参见我的答案)。 - Jeroen van Langen
这个方法只会被调用一次,因为它只针对一个场景。但是,如果用户死亡,那么游戏就结束了并重新开始。也就是说,这个方法可能会再次被调用(随机情况)。 - Ilan
10个回答

10
问题在于你的random.Next()调用返回一个范围内的任何数字-你需要一种替代版本的random.Next(),它只返回1、2或3,或者你需要自己执行这个操作。尝试改为使用以下代码:int pokemonChosen = random.Next(1, 4)(下限包括在内而上限不包括)

10

Random.Next()(没有参数)将返回一个随机的非负整数。您可能想要限制它在某个范围内,像这样:

int pokemonChosen = random.Next(1, 4);

同时需要注意的是,你可以通过在 if 块中返回一个常量来使你的代码更加简洁,像这样:

也就是说,将常量值直接作为 if 块的返回值,可以避免在块外定义变量并且使代码更加易于理解。

请注意,您可以通过仅在if块内部返回一个常量来使您的代码更加简洁,例如:

if (pokemonChosen == 1)  
{  
    return "Pidgey";  
}  

甚至更好的方法是将随机选项封装在一个数组中。这样,您就可以完全摆脱所有的if块:

var options = new [] { "Pidgey", "Charmander", "Geodude" };
int pokemonChosen = random.Next(options.Length); // array indexes start at 0
return options[pokemonChosen];

9

通过我自己的宝可梦游戏试验,一个很好的方法是将New Random()放在函数外部。同样,你也可以在函数外实例化字符串,以防在游戏的不同部分有不同的宝可梦选项。这样,你就不需要返回任何东西,只需调用函数然后使用字符串。假设你正在进行一个基于Windows的故事输出标签:

Random random = new Random();
string pokemon;

    public void choosePokemon()  
    {   
        int pokemonChosen = random.Next(2);  
        if (pokemonChosen == 0) {
        pokemon = "Pidgey";
        }
        if (pokemonChosen == 1) {
        pokemon = "Charmander";
        }
        if (pokemonChosen == 2) {
        pokemon = "Geodude";
        }
    } 

    lblStory.Text += "You encountered a wild " + pokemon + "!";

我曾为我朋友制作的游戏做了类似的事情。
编辑:在我的游戏中,我还将pokemon缩写成pkmn用作变量名。这样打起来更短,并且正如主要游戏所显示的那样,是被广泛接受的。虽然玩家不会读你的代码。

8

让我们从随机数生成器Random开始。为了有效,您应该只实例化一次Random。要做到这一点,您可以为类创建一个静态实例。如果您不这样做,每次调用random.Next()都可能得到相同的数字。

public class PokemonChooser
{
    private static Random random = new Random();

    public static string ChoosePokemon() { ... }
}

然后,我们需要认识到random.Next()返回的是任何非负整数值,而不仅仅是您想要的那些。因此,我们需要将结果四舍五入为对您的情况有用的内容。由于您希望从中随机选择3个项目,因此我们可以使用模运算符(%)进行四舍五入,它基本上会给您除法操作(/)的余数。例如:(int)(5 / 2) == 2,并且5 % 2 == 1var pokemonChosen = random.Next() % 3; 接下来,由于这个结果以零为基础,我们需要在if语句中考虑到这一点。
      if (pokemonChosen == 0)
      {
        string pokemon = "Pidgey";
        return pokemon;
      }

      if (pokemonChosen == 1)
      {
        string pokemon = "Charmander";
        return pokemon;
      }

      if (pokemonChosen == 2)
      {
        string pokemon = "Geodude";
        return pokemon;
      }

由于Pokemon名称很明显,我们可以删除pokemon变量而不会失去任何可读性。

      if (pokemonChosen == 0)
      {
        return "Pidgey";
      }

      if (pokemonChosen == 1)
      {
        return "Charmander";
      }

      if (pokemonChosen == 2)
      {
        return "Geodude";
      }

如果我们使用case语句而不是多个if语句,可能会使这一点更清晰简洁。

      switch (pokemonChosen) {
        case (0): return "Pidgey";
        case (1): return "Charmander";
        case (2): return "Geodude";
      }

如果我们无法通过编号找到 Pokemon,则只需返回"missingno",因此可以使用默认情况:

      switch (pokemonChosen) {
        case (0): return "Pidgey";
        case (1): return "Charmander";
        case (2): return "Geodude";
        default: return "missingno";
      }

总之,我们最终得到如下结果:
public class PokemonChooser
{
    private static Random random = new Random();

    public static string ChoosePokemon()
    {
      var pokemonChosen = random.Next() % 3;

      switch (pokemonChosen) {
        case (0): return "Pidgey";
        case (1): return "Charmander";
        case (2): return "Geodude";
        default: return "missingno";
      }
    }
}

我们可以这样使用:

var pokemon = PokemonChooser.ChoosePokemon();

然而,你可能想要选择比random.Next() % 3中的3更高的数字,否则,"missingno"永远不会被返回。


不要使用模操作来限制返回随机整数的函数的输出,因为这样做会使最大可能的数字出现的概率降低(在这种情况下,“random.Next()%3”比“1”和“0”更不可能返回2)。相反,你应该将 random.Next() / 2147483647.0 乘以3,然后使用 Math.Floor() 将结果向下取整。 - dorukayhan
从技术上讲,你是正确的。但是,这个答案主要是为了演示原始代码中错误的范围错误。增加多余的数学计算会分散读者对潜在问题的理解,我的看法是如此。如果问题是关于随机数的公平性和准确性,那么使用 random.Next() % n 就是一个非常糟糕的想法。 - cwharris

4
您需要为random.Next()指定上限:
int pokemonChosen = random.Next(4);

该函数将返回0-3范围内的整数。

如果要返回1-4,您可以使用以下代码:

int pokemonChosen = random.Next(1, 5);

3

您需要指定随机值的范围:

int pokemonChosen = random.Next(3) + 1;

否则,值的范围高达Int32.MaxValue,这给了您约十亿分之一的机会处于1-4之间。

我在发布后一分钟意识到了我的错误,非常感谢! - Ilan

3

Random.next()会返回0到2,147,483,647(= Integer.MaxValue)之间的值,因此你得到1、2或3的概率很小,这就是通常会返回最后一个值的原因。你需要限制这个值:

random.Next(1, 4);

3

每次调用时不应该重新创建Random类。应该这样调用:_random.Next(3) + 1

Random _random = new Random();  

public string choosePokemon()  
{  
     int pokemonChosen = _random.Next(3) + 1;  
     if (pokemonChosen == 1)  
     {  
         string pokemon = "Pidgey";  
         return pokemon;  
     }  
     if (pokemonChosen == 2)   
     {  
         string pokemon = "Charmander";  
         return pokemon;  
     }  
     if (pokemonChosen == 3)  
     {  
         string pokemon = "Geodude";  
         return pokemon;  
    }  
    return "missingno";  
} 

2

如果您得到的值不是1、2或3,请对其进行调试并检查pokemonChosen的值。您可能希望将随机值的最大值限制为3。

int pokemonChosen = random.Next(4);

2

测试过了,你的代码正常工作 - 不确定你实际使用的是什么代码,但你一直使用的确切方法是正确的。 然而,你应该将其更改为

int pokemonChosen = random.Next(1, 4);  

更新:嘿,你在原问题中更改了那一行,当我打开它时,你在那里写的是 int pokemonChosen = random.Next(1, 3);...


是的,我进行了编辑,因为它有一个错误,然后我意识到那就是错误。抱歉,现在已经恢复了。 - Ilan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接