Search Unity

Number Guessing Game - Player able to play endlessly

Discussion in 'Scripting' started by pitmix, Oct 12, 2017.

  1. pitmix

    pitmix

    Joined:
    Jul 29, 2017
    Posts:
    4
    Hi peoples. I would really appreciate some help on this as I've been banging my head against the wall. My powers of logic have a long way to go yet:

    I'm creating a number guessing game. You simply think of a number in your head and the computer makes random guesses. You tell the computer using the buttons whether your number is Higher or Lower than its guess, then select You Guessed It when it gets the number right.

    The game works well except for when the player clicks continuously between Higher and Lower. The player can do this for a few times before the logic finally kicks in and tells you you've lost. I cannot fathom out why things are happening this way, and any extra code I add seems to either not help or make things worse.

    I would have thought that I need to add to the conditional checking in the GuessHigher() and GuessLower() methods, but I seem to be having a mental block on what to put in.

    As a little bonus, if anyone can suggest ways of improving their logical thinking (other than by just practising coding), I'd be really grateful as its something I'm not very confident about. Or, perhaps, if this is simply a case of learning more debugging tricks which could lead me to a solution more easily, I'd be grateful for some pointers on that too.

    Here's a link to the current playable build on gamebucket.io: https://gamebucket.io/game/3e0d5e3f-efd9-4a5e-9b72-c85e1eb0fbc4

    Here is the code behind the script:

    Code (csharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.SceneManagement;
    4. using UnityEngine.UI;
    5.  
    6. public class NumberWizard : MonoBehaviour
    7. {
    8.     int max;
    9.     int min;
    10.     public int guess;
    11.     public int maxGuessesAllowed = 10;
    12.  
    13.     public Text text;
    14.     public Text guessesRemaining;
    15.  
    16.     // Use this for initialization
    17.     void Start()
    18.     {
    19.         StartGame();
    20.         UpdateDisplay();
    21.     }
    22.  
    23.     void StartGame()
    24.     {
    25.         max = 1000;
    26.         min = 1;
    27.         guess = GenerateNumber();
    28.         Debug.Log("StartGame() Min: " + min + " Max: " + max + " Guess: " + guess);
    29.     }
    30.  
    31.     public void GuessHigher()
    32.     {
    33.         Debug.Log("=============\nPressed Higher");
    34.      
    35.         if (max > guess)
    36.         {
    37.             Debug.Log("Pre-NextGuess() Min: " + min + " Max: " + max + " Guess: " + guess);
    38.  
    39.             if (guess == min) min++;
    40.             else min = guess;
    41.  
    42.             NextGuess();
    43.  
    44.             Debug.Log("Post-NextGuess() Min: " + min + " Max: " + max + " Guess: " + guess);
    45.         }
    46.         else if (max <= guess) { SceneManager.LoadScene("Lose2"); }
    47.     }
    48.  
    49.     public void GuessLower()
    50.     {
    51.         Debug.Log("=============\nPressed Lower");
    52.  
    53.         if (min < guess)
    54.         {
    55.             Debug.Log("Pre-NextGuess() Min: " + min + " Max: " + max + " Guess: " + guess);
    56.  
    57.  
    58.             if (guess == max) max--;
    59.             else max = guess;
    60.  
    61.             NextGuess();
    62.  
    63.             Debug.Log("Post-NextGuess() Min: " + min + " Max: " + max + " Guess: " + guess);
    64.         }
    65.     }
    66.  
    67.     public void GuessCorrect()
    68.     {
    69.         SceneManager.LoadScene("Lose");
    70.         StartGame();
    71.     }
    72.  
    73.     void NextGuess()
    74.     {
    75.         if (maxGuessesAllowed <= 0) SceneManager.LoadScene("Win");
    76.         else
    77.         {
    78.             guess = GenerateNumber(guess);
    79.          
    80.             maxGuessesAllowed -= 1;
    81.             UpdateDisplay();
    82.         }
    83.     }
    84.  
    85.     void UpdateDisplay()
    86.     {
    87.         text.text = guess.ToString() + " ?";
    88.         guessesRemaining.text = maxGuessesAllowed.ToString();
    89.     }
    90.  
    91.     int GenerateNumber(int lastGuess)
    92.     {
    93.         // Use recursion to ensure a different number is generated each time
    94.         int randNum = UnityEngine.Random.Range(min, max + 1);
    95.         //Debug.Log("randNum: " + randNum + " lastGuess: " + lastGuess);
    96.  
    97.         if (randNum == lastGuess)
    98.         {
    99.             return GenerateNumber(randNum);
    100.         }
    101.         else
    102.         {
    103.             return randNum;
    104.         }
    105.     }
    106.  
    107.     int GenerateNumber()
    108.     {
    109.         // Use recursion to ensure a different number is generated each time
    110.         int randNum = UnityEngine.Random.Range(min, max + 1);
    111.         //Debug.Log("Random Number: " + randNum);
    112.         return randNum;
    113.     }
    114. }

    Many thanks in advance.
     
    Last edited: Oct 12, 2017
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
  3. pitmix

    pitmix

    Joined:
    Jul 29, 2017
    Posts:
    4
  4. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    I'm not 100% certain of your code logic atm as I can't look to deeply. But, if your range is 1-1000 and the computer guesses 500, if I hit the higher button (thus my number is higher), you would then set min = 500 +1 changing your range to 501-1000. (500 is not needed)

    If I hit lower, then you'll set max to 500 (no need for +1 as you know 500 isn't an option) and your range would be 1 - 499.

    Then after each guess, you'd check your number of guesses remaining to see if guesses is 0, and if so, do a lose popup/scene change, whatever you'd like.

    And of course, do add the win condition for if the correct guess button is hit.

    I'm just a little confused by all your if checks within the guess lower/higher methods.
     
    pitmix likes this.
  5. pitmix

    pitmix

    Joined:
    Jul 29, 2017
    Posts:
    4
    I like your description of the game flow in your first paragraph. By that alone, I can see that my issue could probably be fixed by settings min = guess + 1 in GuessHigher() - of course, I won't be needing to use the exact guess value again.

    I get it... My program is turning into spaghetti code. Still ,I believe I needed a special test case for when testing against the starting max and min values, thus the following:

    Code (csharp):
    1.  
    2. public void GuessHigher()
    3.     {
    4.         if (max <= guess) { SceneManager.LoadScene("Lose2"); Debug.Log("Lose case 1"); }
    5.         else if (guess + 1 == max && max != startMax) { SceneManager.LoadScene("Lose2"); Debug.Log("Lose case 2"); }
    6.         else if (max > guess)
    7.         {
    8.             min = guess + 1;
    9.  
    10.             NextGuess();
    11.         }
    12.     }
    13.  
    14.     public void GuessLower()
    15.     {
    16.         if (min >= guess) { SceneManager.LoadScene("Lose2"); Debug.Log("Lose case 1"); }
    17.         else if (guess == min && min != startMin) { SceneManager.LoadScene("Lose2"); Debug.Log("Lose case 2"); }
    18.         else if (min < guess)
    19.         {
    20.             max = guess;
    21.  
    22.             NextGuess();
    23.         }
    24.     }
    Thanks for your help!
     
  6. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    You're working harder than you need to. The logic is pretty simple: if they say higher, you set min = guess+1; and if they say lower, you say max = guess-1 (I disagree that you don't need "-1" here, because your guess range appears to be inclusive).

    Then you can simply check for the case where min > max, i.e., your guess range is empty. In that case you have to give up (although this will only happen if the player has cheated or made a mistake).

    While debugging, you should make max and min public so you can watch them in the Inspector while you play. That will give you much better insight as to what's going on. (Debug.Logs are good too, but in this case you pretty much want to just always see those two values, and this is the easiest way to do it.)
     
  7. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    If your values are ints, the max is exclusive, so -1 shouldn't be needed or you'll actually lose a number. If they are floats, the max is inclusive. He's using two ints, so it should follow the first rule.
     
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Except that he's explicitly adding 1 to it in his Random.Range call.

    Code (csharp):
    1. int randNum = UnityEngine.Random.Range(min, max + 1);
    Therefore, it's inclusive.
     
  9. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Yes, but that's his original script. He shouldn't be adding 1 anymore I hope in his modified script. lol. But he didn't post the update to that method, so who knows.
     
    JoeStrout likes this.
  10. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Fair enough. It really comes down to: what does he want min and max to mean? Is he more comfortable thinking of an inclusive range, a semi-inclusive range, or an exclusive range? Whatever makes most sense to him, he should store them that way (and then just adjust the GenerateNumber method accordingly).
     
  11. pitmix

    pitmix

    Joined:
    Jul 29, 2017
    Posts:
    4
    @JoeStrout and @Brathnann Thanks for all your input on this. The tip about making the max and min values public for debugging is a great idea. Will use that in the future.

    And yes, I did adjust my GenerateNumber() method to no longer add the 1 to the max:

    Code (csharp):
    1. int randNum = UnityEngine.Random.Range(min, max);