【问题标题】:Program to guess number gets incredibly slow猜测数字的程序变得非常慢
【发布时间】:2018-09-12 19:10:27
【问题描述】:

所以,我决定找点乐子,并制作一个程序,它会得出一个数字,你必须猜它,它会告诉你是否太高/太低。但是,我认为如果计算机能自己计算出随机数会更有趣。

我在这里使用了一个简单的方法,它基本上让程序检查一个值是否在array 中,如果是,则提出另一个随机数。当一个数字太高时,从这个数字的大小开始,然后一直下降到那个数字(这样,如果这个数字太高,它就永远不会再猜到那个高或更高了)。

所以,这对小数字很有用。我认为当做 1,000 之类的数字时,它会在 15 次尝试内猜到。然而,当我做了 10,000,000 次时(我知道这有点极端,但我想看看 C# 的强大功能,因为我对这门语言还很陌生)。

该程序进行了大约 10 次猜测,然后开始慢得令人难以置信。我设置了一个 250 毫秒的睡眠定时器,让它看起来更像是在猜测(因为它对于 1,000 或 10,000 之类的东西是即时的),但是当它取出时,它仍然变慢了。我认为这可能是因为如果它猜到一个像 300 万这样的数字,它必须将 700 万个值添加到一个数组中(我使用的是List,因此它具有“无限”值)。

那么此时我究竟能做些什么呢?我希望它能够猜测大数字,但在这一点上似乎不太可能。我怎么能这样做?

这是我的代码:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Program {
    class Program {
        static void Main(string[] args) {
            Random random = new Random();
            int selectedNumber = random.Next(1, 101);
            int maxNumber;
            int guessNumber = 0;
            int inputNumber = 0;
            // Intro
            Console.ForegroundColor = ConsoleColor.DarkGreen;
            Console.WriteLine("Welcome to the High Low - Computer version program!");
            System.Threading.Thread.Sleep(4000);
            Console.WriteLine("\n--------------------------------------------------------");
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            // This way the computer guesses rather than you
            char who = 'C';
            Console.Write("\nHow high do you want the computer's number to be max > ");
            maxNumber = Convert.ToInt32(Console.ReadLine());
            List<int> guessedNumbers = new List<int>();
            selectedNumber = random.Next(1, maxNumber);
            do {
                // System.Threading.Thread.Sleep(250);
                Console.ForegroundColor = ConsoleColor.DarkYellow;
                if (who == 'M') {
                    Console.Write("\nPlease enter your guess > ");
                    guessNumber = Convert.ToInt32(Console.ReadLine());
                }
                else {
                    while (true) {
                        guessNumber = random.Next(1, maxNumber);
                        if (!(guessedNumbers.Contains(guessNumber))) {
                            guessedNumbers.Add(guessNumber);
                            inputNumber++;
                            break;
                        }
                    }
                    Console.WriteLine("Please enter your guess > {0}", guessNumber);
                }
                Console.ForegroundColor = ConsoleColor.DarkGreen;
                if (guessNumber < selectedNumber) {
                    Console.WriteLine("\nYou're guessing too low!\n");
                    for (int i = 0; i < guessNumber; i++) {
                        guessedNumbers.Add(i);
                        inputNumber++;
                    }
                }
                else if (guessNumber > selectedNumber) {
                    Console.WriteLine("\nYou're guessing too high!\n");
                    for (int i = maxNumber; i > guessNumber; i--) {
                        guessedNumbers.Add(i);
                        inputNumber++;
                    }
                }
            } while (guessNumber != selectedNumber);
            Console.ForegroundColor = ConsoleColor.DarkGreen;
            Console.WriteLine("\nCongratulations! You correctly guessed that {0} is the computer's number!", selectedNumber);
            Console.ReadKey();
        }
    }
}

编辑:我想我会尝试一种方法,以便它只添加更高或更低的数字(如果它们不存在的话),以避免出现重复的数字.

【问题讨论】:

  • ListArray 不同。
  • 我相信您的假设是正确的,即添加列表会减慢速度。尝试修改它,也许,使用布尔值代替,甚至是一个简单的整数,告诉它它猜到的最后一个数字?我认为有很多方法可以做到这一点,对于像你这样的初学者来说,最好继续尝试不同的想法,看看会发生什么。
  • 为什么不将“保存”的猜测数字的数量限制在可行的范围内?为什么你仍然需要保存它们?
  • 我要提出一个激进的建议:保留两个变量,“高”和“低”,当你猜测时,将其设为“(高+低)/2”。然后如果猜测太高,将“高”设置为猜测-1,否则如果太低,将“低”设置为猜测+1。并重复。这样你根本不需要数组。 I'm guessing that some people might recognise this approach...
  • @Bigiansen 好主意,我会尝试实施一种方法,如果它还没有,我会尝试只保存更高或更低的数字。

标签: c# arrays list random numbers


【解决方案1】:
for (int i = 0; i < guessNumber; i++) 
{
    guessedNumbers.Add(i);
    inputNumber++;
}

每次输入这些类型的循环时,都会将“guessnumber”项添加到列表中,可能数百万。

考虑重新阅读您的代码并了解它的作用。

此外,您应该考虑封装您的代码以避免使您的 main() 成为庞然大物

【讨论】:

    【解决方案2】:

    另一种方法是使用Binary Search 的方法来猜测数字,避免写入和搜索猜测值带来的额外开销。

    这应该在O(log n). 中运行

    int minGuess = 0;
    int maxGuess = 1000000;
    
    Random random = new Random();
    int selectedNumber = random.Next(minGuess, maxGuess);
    
    Console.WriteLine($"Selected number: {selectedNumber}");
    
    int guess;
    
    int count = 0;
    
    do
    {
        count++;
    
        guess = (minGuess + maxGuess) / 2;
    
        Console.WriteLine($"Guess: {guess}");
    
        if (selectedNumber < guess)
            maxGuess = guess - 1;
        else
            minGuess = guess + 1;
    
    } while (guess != selectedNumber);
    
    Console.WriteLine($"Guessed it in {count} tries");
    Console.ReadLine();
    

    【讨论】:

      【解决方案3】:

      您尝试使用计算机的能力来查找数字的方式并不是很有效,您为什么不根据先前猜测的数字高于或低于正确的数字是这样的:

      class Program
          {
              static void Main(string[] args)
              {
                  Console.WriteLine("Highest number:");
                  int maxNumber = Convert.ToInt32(Console.ReadLine());
                  Random rand = new Random();
                  int correctNumber = rand.Next(0, maxNumber);
      
                  Console.WriteLine("Trying to guess number now..");
                  int guessedNumber = 0;
      
                  int lowBound = 0;
                  int highBound = maxNumber;
                  int guesses = 0;
                  while(guessedNumber != correctNumber)
                  {
                      guessedNumber = rand.Next(lowBound, highBound);
                      if(guessedNumber > correctNumber)
                      {
                          highBound /= 2;
                          lowBound /= 2;
                      }
                      else if(guessedNumber < correctNumber)
                      {
                          lowBound *= 2;
                          highBound *= 2;
                      }
                      ++guesses;
                  }
                  Console.WriteLine($"Took me {guesses} guesses.");
                  Console.ReadKey();
              }
          }
      

      对于我的机器上的 10,000,000 个条目,这需要不到一秒钟的时间。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-01
        • 1970-01-01
        • 2019-11-11
        相关资源
        最近更新 更多