Python AI Guessing Game

I made a Python AI Guessing Game. Here’s the code for those who want to copy and paste.

import random

Round1Num = 0
Round2Num = 0
Round3Num = 0
Round4Num = 5

Round = 0

while True:
    UserNum = input ("Choose a number from 1 to 10: ")
    Round = Round + 1
    AINum = 0

    if (Round == 1):
        if (Round1Num == 0):
            if (Round2Num == 0):
                if (Round3Num == 0):
                    if (Round4Num == 0):
                        Round1Num = UserNum
                        AINum = random.randint(1, 10)
                        print ("AI thinks your number is " + str(AINum))

                        if (str(AINum) == UserNum):
                            print ("AI guessed your number correctly!")

                        else:
                            print ("AI did NOT guess your number correctly!")

    elif (Round == 2):
        if not (Round1Num == 0):
                if (Round2Num == 0):
                    if (Round3Num == 0):
                        if (Round4Num == 0):
                            Round2Num = UserNum
                            AINum = Round1Num
                            print ("AI thinks your number is " + str(AINum))

                            if (str(AINum) == UserNum):
                                print ("AI guessed your number correctly!")

                            else:
                                print ("AI did NOT guess your number correctly!")

    elif (Round == 3):
        if not (Round1Num == 0):
                if not (Round2Num == 0):
                        if (Round3Num == 0):
                            if (Round4Num == 0):
                                Round3Num = UserNum
                                AINum = Round2Num
                                print ("AI thinks your number is " + str(AINum))

                                if (str(AINum) == UserNum):
                                    print ("AI guessed your number correctly!")

                                else:
                                    print ("AI did NOT guess your number correctly!")

    elif (Round == 4):
        if not (Round1Num == 0):
                if not (Round2Num == 0):
                        if not (Round3Num == 0):
                                if (Round4Num == 0):
                                    Round4Num = UserNum
                                    AINum = Round3Num
                                    print ("AI thinks your number is " + str(AINum))

                                    if (str(AINum) == UserNum):
                                        print ("AI guessed your number correctly!")

                                    else:
                                        print ("AI did NOT guess your number correctly!")

    elif (Round == 5):
        if not (Round1Num == 0):
                if not (Round2Num == 0):
                        if not (Round3Num == 0):
                                if not (Round4Num == 0):
                                        AINum = Round4Num
                                        print ("AI thinks your number is " + str(AINum))

                                        if (str(AINum) == UserNum):
                                            print ("AI guessed your number correctly!")

                                        else:
                                            print ("AI did NOT guess your number correctly!")

    elif (Round > 5):
        print ("Game Over!")
        input ("Press ENTER to reset the game... ")

        Round1Num = 0
        Round2Num = 0
        Round3Num = 0
        Round4Num = 0

        Round = 0

I worked on this for at least 3 days and then released the code.

Hi @Slate-Technologies. The #ideas category is for sharing ideas to modify the current Python behavior and related stuff (ideas for changing Python). This post might belong to the #users category.

Thanks for sharing your work. Next time, to allow others to be able to easily view and run your code, place it within a code block, like this:

```python
YOUR CODE HERE
```

This preserves indentation and other formatting, which is critically important in Python. I’ve reconstructed what it looks like you presumably intended, and included it below.

Reconstructed code
import random

Round1Num = 0
Round2Num = 0
Round3Num = 0
Round4Num = 5

Round = 0

while True:
    UserNum = input ("Choose a number from 1 to 10: ")
    Round = Round + 1
    AINum = 0

    if (Round == 1):
        if (Round1Num == 0):
            if (Round2Num == 0):
                if (Round3Num == 0):
                    if (Round4Num == 0):
                        Round1Num = UserNum
                        AINum = random.randint(1, 10)
                        print ("AI thinks your number is " + str(AINum))

                        if (str(AINum) == UserNum):
                            print ("AI guessed your number correctly!")

                        else:
                            print ("AI did NOT guess your number correctly!")

    elif (Round == 2):
        if not (Round1Num == 0):
                if (Round2Num == 0):
                    if (Round3Num == 0):
                        if (Round4Num == 0):
                            Round2Num = UserNum
                            AINum = Round1Num
                            print ("AI thinks your number is " + str(AINum))

                            if (str(AINum) == UserNum):
                                print ("AI guessed your number correctly!")

                            else:
                                print ("AI did NOT guess your number correctly!")

    elif (Round == 3):
        if not (Round1Num == 0):
                if not (Round2Num == 0):
                        if (Round3Num == 0):
                            if (Round4Num == 0):
                                Round3Num = UserNum
                                AINum = Round2Num
                                print ("AI thinks your number is " + str(AINum))

                                if (str(AINum) == UserNum):
                                    print ("AI guessed your number correctly!")

                                else:
                                    print ("AI did NOT guess your number correctly!")

    elif (Round == 4):
        if not (Round1Num == 0):
                if not (Round2Num == 0):
                        if not (Round3Num == 0):
                                if (Round4Num == 0):
                                    Round4Num = UserNum
                                    AINum = Round3Num
                                    print ("AI thinks your number is " + str(AINum))

                                    if (str(AINum) == UserNum):
                                        print ("AI guessed your number correctly!")

                                    else:
                                        print ("AI did NOT guess your number correctly!")

    elif (Round == 5):
        if not (Round1Num == 0):
                if not (Round2Num == 0):
                        if not (Round3Num == 0):
                                if not (Round4Num == 0):
                                        AINum = Round4Num
                                        print ("AI thinks your number is " + str(AINum))

                                        if (str(AINum) == UserNum):
                                            print ("AI guessed your number correctly!")

                                        else:
                                            print ("AI did NOT guess your number correctly!")

    elif (Round > 5):
        print ("Game Over!")
        input ("Press ENTER to reset the game... ")

        Round1Num = 0
        Round2Num = 0
        Round3Num = 0
        Round4Num = 0

        Round = 0

From a high-level perspective, you can make the game more fun and give it some replay value if the "AI’"s strategy wasn’t so easily predictable. Particularly since the number the AI picked is visible, it quickly becomes to obvious a player within the first few rounds (and certainly within the first 5 round game) that the “AI” is just going to guess whatever they chose last, so all they need to do to “win” is pick a different number each time, which isn’t much fun.

A more sophisticated strategy (say, remembering the player’s choices over multiple rounds, and guessing a number with a probability based on the frequency the player previously entered that number) would greatly improve this. But perhaps better yet, reverse the game and have the computer pick a number and have the player try to guess it, based on hints given by the computer (e.g. “higher”/“lower”, “warmer”/“colder”, etc. You can even write a bot to try to implement the optimal strategy to win the game in the fewest average number of guesses.

In any case, perhaps its intentional to somewhat obfuscate what the AI is doing, so it isn’t quite as easy for a player to beat it just by glancing at the code, but the code can be made far shorter, less complicated and easier to understand, change and improve using some simple but very useful techniques. In general, if you notice your program has a lot of nested layers, lines that aren’t actually necessary (e.g. if statements that will always evaluate True) or repeating patterns of similar or identical code, its a good sign that you should probably restructure it.

For example, you have nested if statements many layers deep:

if (Round == 1):
    if (Round1Num == 0):
        if (Round2Num == 0):
            if (Round3Num == 0):
                if (Round4Num == 0):

Since you don’t do anything unless all the levels evaluate true, this can be simplified to:

if Round == 1 and Round1Num == 0 and Round2Num == 0 and Round3Num == 0 and Round4Num == 0:
    Round1Num = UserNum
    # Your code here

It still looks a little redundant, though. Instead of checking each number equals zero, you can use a ternary conditional to check that they all equal 0 (and each other) all at once:

if Round == 1 and Round1Num == Round2Num == Round3Num == Round4Num == 0:
    Round1Num = UserNum
    # Your code here

But wait—if Round == 1, we know Round1Num and friends must all equal zero, because we set them so right before. Likewise, in the succeeding rounds, the rounds that have passed must not equal zero (so long as the user didn’t enter zero themself, which you should check for at input time). So, for each round, this check doesn’t actually do anything, because it is always true, and thus we can simplify this if statement to just

if Round == 1:
    Round1Num = UserNum
    # Your code here

Just in case you do want to check that your program is operating correctly and the various round numbers are indeed what you expect them to be, use an assert statement:

if Round == 1:
    assert Round1Num == Round2Num == Round3Num == Round4Num == 0

This separates your business logic from your correctness checks, and if the check isn’t true, your program immediately halts with an AssertionError giving the exact line that failed, rather than simply silently skips the block.

In any case, what’s more, now that you’ve simplified your logic, you might notice that each round’s number is only used once, in the round after the user enters it. As such, you don’t need four different variables, one for each round, but only one—called, say, user_num_previous. That’s one fourth the variables to keep track of and reset.

With that further simplification, the code blocks for rounds one through five all look identical (aside the AINum guess line being random instead of the previous number). Whenever you see code that looks similar or identical, your first thought should be to avoid this duplication by putting your code inside a loop (or a function). A literal translation of your logic into a nested while loop would look like this:

user_num_previous = 0
Round = 0
while True:
    if Round <= 5:
        # Print game over message, etc
        Round = 0        
    Round = Round + 1
    if Round == 1:    
        AINum = random.randint(1, 10)
    else:
        AINum = user_num_previous
    # [...] Existing logic to get and check user's number, and print results
    user_num_previous = UserNum

That said, we can simplify this further. Since we’re just iterating to 5 and then repeating every time, we can just nest a for loop with a range() inside the while loop instead of manually incrementing and keeping track of our counter variable Round, while the outer while loop runs the game again after the user presses Enter. This gives us:

user_num_previous = 0
while True:
    for Round in range(5):
        if Round == 1:    
            AINum = random.randint(1, 10)
        else:
            AINum = user_num_previous
        # [...] Existing logic to get and check user's number, and print results
        user_num_previous = UserNum

    # Print game over message, etc

Furthermore, if we move resetting the user number inside the outer while look, we don’t need to check the Round number at all. Instead, we can just check if user_num_previous is not 0—in fact, since 0 evaluates as true, while any non-zero integer evaluates as true, we can just check if user_num_previous. On top of that, result = var1 or var2 sets result equal to var1 if var1 evaluates true, otherwise it sets it equal to var2. We can use this to set AINum equal to user_num_previous if it isn’t the default 0 (i.e. if the user entered a number in previous round), otherwise random.randint(1, 10). Therefore, we have:

while True:
    user_num_previous = 0
    for __ in range(5):
        AINum = user_num_previous or random.randint(1, 10)
        # [...] Existing logic to get and check user's number, and print results
        user_num_previous = UserNum

    # Print game over message, etc

(Note that we don’t need Round anymore, so we set the loop variable equal to the dummy __)

There are a couple final improvements we can make to shorten this by a few more lines. AINum = 0 doesn’t do anything, since we reassign it (both in the above and the original) before we ever use it, so it can just be removed. Also, there’s no need to print() a “Game Over!” message then add another line for input(); just include Game Over! in the same string, separated by a line break (\n), i.e.:

input("Game Over!\nPress ENTER to reset the game... ")

In total, with these changes, we’ve shortened our program from around 100 lines to only a mere 15, including blank lines, while behaving exactly the same as the above. This makes it much simpler to read, understand and modify, which is pretty much always a good thing.

There’s a few other things we should do to our existing lines, that don’t make it any more complex or significantly change the behavior, but do make our code cleaner, more correct and more idiomatic. In particular:

  • Instead of converting our guessed int to a str and comparing it that way, it is more idiomatic and reliable to convert our user’s input string to an integer; then, you’ll automatically get an error if the user enters something other than an integer number, which you can then handle appropriately. I.e.:

    user_num = int(input("Choose a number from 1 to 10: "))
    if user_num == ai_num:
        # Etc
    
  • The print() function automatically concatenates its arguments into strings with a space betwen them, so instead of doing:

    print ("AI thinks your number is " + str(AINum))
    

    you can just do

    print("AI thinks your number is", AINum)
    

    Better yet, you can (and should) use format strings (f-strings) when building strings, as they are shorter, cleaner and faster than other approaches. Just put an f in front of the opening quote ("), and insert your variables inside braces ({}):

    print (f"AI thinks your number is {AINum}")
    
  • The canonical value used in Python to mean a non-valid or initial value is None, which is tested for with is rather than ==, so instead of

    user_num_previous = 0
    if user_num_previous == 0: ...
    

    you should use:

    user_num_previous = None
    if user_num_previous is None: ...
    
  • Finally, some Pythonic style notes. There’s no space between the function name and the opening paren in function calls, i.e.:

    print("Hello World!")
    

    not

    print ("Hello World!")
    

    and by standard convention, UpperCamelCase names are for classes, while regular variables use snake_case names, i.e.

    ai_num = random.randint(1, 10)
    

    not

    AINum = random.randint(1, 10)
    

I strongly advise going through the steps here and trying to modify your code yourself following the guidance, which is helpful so you can learn yourself. You should be able to get it down to only 15 lines with the techniques shown, with whitespace included (13 lines without).

However, once you’ve given it your best shot, here is what the result should look like:

Final result
import random

while True:
    user_num_previous = None
    for __ in range(5):
        user_num = int(input("Choose a number from 1 to 10: "))
        ai_num = user_num_previous or random.randint(1, 10)
        print(f"AI thinks your number is {ai_num}")
        if user_num == ai_num:
            print("AI guessed your number correctly!")
        else:
            print("AI did NOT guess your number correctly!")
        user_num_previous = user_num

    input("Game Over!\nPress ENTER to reset the game... ")

Once you’ve done this, here are some things other things you can add further improve the game, and learn more basic Python in the process:

  • Have the program keep track of its score versus the user’s and display it at the end of each game
  • If the player enters something that is not an integer, use a try-except block to catch the ValueError and give them an opportunity to try again (another nested while loop is useful here)
  • Similarly, if the number is not in the indicated range (1-10), do the same as the above
  • At the beginning, ask the user how many rounds they want to play
  • At the end, ask the user if they want to play again or not
1 Like