0

The issue is that the number of stones the computer takes differs from the number that is displayed on the screen. I know it's cause the function is being repeated twice. But I can't find a way to store the random number generated and use that number for printing AND subtracting [Also I know this can be done without using functions but it is required]

Here is the code:

import random
stones = random.randint(15, 30)
turn = 0

while stones > 0:
    if turn == 0:
        def player_announce():
            print('There are', stones, 'stones. How many would you like?', end=' ')
        def invalid_entry():
            print('Enter a number from 1-3.')
        player_announce()
        player_stones = int(input(''))
        if player_stones > 3 or player_stones < 1:
            invalid_entry()
        else:
            stones = stones - player_stones
            turn = 1
    else:
        def draw_stones():
            computer_stones = random.randint(1, 3)
            return computer_stones
        print('There are', stones, 'stones. The computer takes', draw_stones())
        stones -= draw_stones()
        turn = 0
if turn == 0:
    print('The computer beats the player!')
else:
    print('The player beats the computer!')
Soda
  • 3
  • 3
  • 2
    Defining functions inline like that is quite odd.. – JeffUK Dec 02 '21 at 21:35
  • 1
    Can't say i've ever seen functions defined in a while loop before. – troy Dec 02 '21 at 21:38
  • 2
    and a single-line function that is called only once is somewhat redundant. – JeffUK Dec 02 '21 at 21:38
  • Because you call `draw_stones()` two separate and unrelated times: once for the print, once in the `stones -= draw_stones()` line. Those are going to be two separate unrelated random quantities. Hence the inconsistency. – smci Dec 02 '21 at 21:49
  • 1
    I strongly recommend you rewrite your code, to help debugging and make it more readable. a) Don't define simple one-line functions that are only used once (`player_announce`, `invalid_entry`). b) The whole sequence from `if turn == 0: ... player_announce():` only parses that the player took a valid number (1-3) of stones then does the updating. c) In fact both turn==0 and 1 boil down to getting the number of stones drawn into a variable, say `drawn_stones`, then you can do the update `stones -= drawn_stones` in the while-loop, not need a separate line under `if turn == 0/1` . – smci Dec 02 '21 at 21:56
  • Also, defining functions within a code body (like Java or C++ "inner functions"), instead of outside the while-loop, is generally a bad idea (except maybe for GUIs, which is not the case here) and we don't do that in Python. It reduces readability and means those functions can't be directly accessed from within the interpreter. – smci Dec 02 '21 at 22:03
  • add the fact that `player_announce` and `invalid_entry` are just print statements, no need for a function call there. – troy Dec 02 '21 at 22:04
  • Another tip: your variable `turn` isn't really counting the turns, it's only a one-bit counter (0: player, 1: computer). You could increment it with `turn += 1`, then in your if-statement compare `if (turn % 2) == 0:` to get even (player)/ odd(computer). Now you actually have a count of how many turns have been taken. You are of course hardcoding that player always goes first. – smci Dec 02 '21 at 22:05
  • In future, after you fix the functional bugs, you can then post your (working) code over on [CodeReview.SE](https://codereview.stackexchange.com/questions/tagged/python) to get feedback like this. It's pretty useful. – smci Dec 02 '21 at 22:08
  • Here's a second thing that's almost a bug: you just about get away with double-jobbing the main `while stones>0` -loop to also handle parsing/rejecting invalid player input (when player input is invalid, your if-code avoids updating `stones` or `turn` and silently loops without any explicit `continue`). But you sacrifice readability. This is being too clever, it will silently cause bugs in future. Just shunt all that code into a function `get_player_stones()` that you define at the top that has its own separate while-loop. Even if it feels wasteful, there's no tax on while-loops... – smci Dec 02 '21 at 22:18

1 Answers1

2

The simple answer is to call draw_stones once and store the result:

computers_stones = draw_stones()
print('There are', stones, 'stones. The computer takes', computers_stones)
stones -= computers_stones

Once you've got it working, I advise you get someone to read over the whole thing for you there are a lot of things you could do better!

JeffUK
  • 4,107
  • 2
  • 20
  • 34
  • 1
    SO is for specific problems, but when you have your code working you might want to visit http://codereview.stackexchange.com and ask for some more general feedback on style and approach. – JeffUK Dec 02 '21 at 21:37