【问题标题】:Pick a random random from a list. If it's not the chosen one, pick another one.从列表中随机选择一个。如果不是选择的,请选择另一个。
【发布时间】:2014-04-02 21:56:37
【问题描述】:

我有这个猜数字游戏。用户想出一个数字,计算机就会猜出来。我有这段代码,但问题是,计算机所做的每一次尝试都有随机数重复的机会。我想知道如何创建一个随机列表,计算机将从列表中选择一个数字,如果不正确,我想删除该数字,这样就不会再被选中。我是这个领域的新手,所以我非常感谢任何帮助。

private void btnStartTheGame_Click(object sender, EventArgs e)
{
    int guessTheNumber = Convert.ToInt32(txtNumberGuess.Text);
    DialogResult dialogResult;
    do
    {
        Random newNumberGenerator = new Random();
        number = newNumberGenerator.Next(0, 10);
        dialogResult = MessageBox.Show("Is number" + number.ToString() + " you are thinking about?", "Answer the question!", MessageBoxButtons.YesNo);
    }while (dialogResult == DialogResult.No);

    MessageBox.Show("Congratulation! You guessed the number!!");       
}

【问题讨论】:

    标签: c# list random


    【解决方案1】:

    这是一个简短但完整的程序,可以按您的要求执行(我使用的是控制台应用程序而不是表单):

    private static void Main(string[] args)
    {
        string dialogResult = "";
        bool[] alreadyGuessed = new bool[10];
        int guesses = 0;
    
        Random newNumberGenerator = new Random();
        do
        {
            int number = newNumberGenerator.Next(0, 10);
            if (!alreadyGuessed[number])
            {
                guesses++;
                alreadyGuessed[number] = true;
                Console.WriteLine("Are you thinking of the number " + number.ToString() + "?")
                dialogResult = Console.ReadLine();
            }
        }
        while (dialogResult.ToUpper() != "Y" && guesses < 10);
    
        if (dialogResult.ToUpper() == "Y")
        {
            Console.WriteLine("I guessed the number!");
        }
        else
        {
            Console.WriteLine("No numbers left!");
        }
        Console.ReadLine();
    }
    

    您原来程序中的逻辑似乎有些倒退;目前尚不清楚是用户还是计算机在猜测。该程序假定您正在考虑一个介于 0 和 9(含)之间的数字并让计算机尝试猜测它,但您显然可以根据您的需要调整它。我也省略了任何验证逻辑。

    编辑:正如 Tarec 正确指出的那样,这不会扩展到非常大的数字集。为此,您需要一个像这样的适当洗牌算法:

    public static void Shuffle(int[] array)
    {
        var random = new Random();
        for (int i = array.Length; i > 1; i--)
        {
            int j = random.Next(i);
            int temp = array[j];
            array[j] = array[i - 1];
            array[i - 1] = temp;
        }
    }
    

    然后你可以把你的程序改成这样:

    private static void Main(string[] args)
    {
        string dialogResult = "";
        int size = 10;
    
        int[] array = Enumerable.Range(0, size).ToArray();
        Shuffle(array);
    
        for (int i = 0; i < size; i++)
        {
            int number = array[i];
            Console.WriteLine("Are you thinking of the number " + number.ToString() + "?");
            dialogResult = Console.ReadLine();
            if (dialogResult.ToUpper() == "Y")
            {
                break;
            }
        }
    
        if (dialogResult.ToUpper() == "Y")
        {
            Console.WriteLine("I guessed the number!");
        }
        else
        {
            Console.WriteLine("No numbers left!");
        }
        Console.ReadLine();
    }
    

    现在您可以将“大小”更改为您喜欢的任何内容,程序将正常运行。不过,这对于原始海报的需求来说可能有点过头了。

    【讨论】:

    • 这不是最佳解决方案。它是不确定的,因为您正在运行循环,直到使用了所有随机数,这是错误的。在最后一位数字的一些悲观变体中,您在每次迭代中都有 1/10 的机会实际命中正确的数字。想象一下,如果您针对 1000 或 1 000 000 个数字而不是 10 个数字运行它,那么您注定要失败。
    • 当然。但是我们不是针对 1,000 或 1,000,000 个数字,我们针对的是 10。这不是一个可扩展的解决方案,但它确实解决了 OP 的特定问题。 (另外,更改为一百万个数字(自动检查)大约需要三秒钟,所以我认为“注定”有点夸张!)
    • 不客气。感谢@Tarec 让我做得很好!
    【解决方案2】:
    List<int> randomNumbers = Enumerable.Range(0,10).ToList();
    DialogResult dialogResult;
    Random newNumberGenerator = new Random();
    do
    {
        int index = newNumberGenerator.Next(0, randomNumbers.Count);
        dialogResult = MessageBox.Show("Is number" + randomNumbers[index] + " you are thinking about?", "Answer the question!", MessageBoxButtons.YesNo);
        if(dialogResult==DialogResult.No)
        {
            randomNumbers.RemoveAt(index);
        }
    }
    while (dialogResult == DialogResult.No);
    

    【讨论】:

    • 我没有投反对票,但我认为您的回答仍然允许选择重复的条目。 (另外我不认为List&lt;int&gt; randomNumbers = Enumerable.Range(0, 10); 编译)
    • 我不是一个反对者,但我想他也想从这些 randomNumbers 中删除猜测的数字 ;-) 否则,它看起来没问题。
    • 这是我的错,我显然忘记了删除使用过的项目。当然 dialogResult 对象必须在循环之前声明。此方法也不会检查是否还有任何号码,用户可以轻松回答“否”10 次,然后它会在randomNumbers[index] 调用时崩溃。
    • @Tarec 你应该在循环之前声明 dialogResult。
    【解决方案3】:

    我通过添加要选择的数字数组来修改您的代码。然后我只随机排列数组的索引。如果数字不正确,则将数字从数组中删除并重做。

    int guessTheNumber = Convert.ToInt32(txtNumberGuess.Text);
    DialogResult dialogResult;
    ArrayList numberList = new ArrayList();
    for(int i=1; i<10; i++)
       numberList.Add(i);
    int length = index.Count;
    do
    {
       Random newNumberGenerator = new Random();
       index = newNumberGenerator.Next(length);
       dialogResult = MessageBox.Show("Is number" + numberList[index].ToString() + " you are thinking about?", "Answer the question!", MessageBoxButtons.YesNo);
       if( dialogResult == DialogResult.No) 
       {
          numberList.RemoveAt(index);
          length = length - 1;
          if(length == 0)
          {
              MessageBox.Show("No number left!!");  
              return;
          }
       }
    }while (dialogResult == DialogResult.No);
    MessageBox.Show("Congratulation! You guessed the number!!");
    

    【讨论】:

      猜你喜欢
      • 2010-12-17
      • 1970-01-01
      • 2016-07-22
      • 2013-03-08
      • 1970-01-01
      • 1970-01-01
      • 2015-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多