Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialKevin Faust
15,353 PointsPython: Number Game Refinement
im debugging what i have right now and so when i type in a number, it tells me "local variable 'count' referenced before assignment. But I initialized my count variable at the very top so i dont understand why it is telling me this. The error occurs in my guessed() method which is the first function below.
import random
# variables
n1 = 1
n2 = 10
count = 0
guess_count = 10
again = False
guess = ""
secret_numer = ""
# functions
def guessed():
count += 1
guess_count -= 1
def isValid(input):
try:
int(input)
return True
except ValueError:
return False
def winMessage():
print("You guessed the number! It took you {} tries and you had {} guess left".format(count, guess_count))
def loseMessage():
print("You have used all your guesses. Game over")
def incorrectGuessMessage():
if guess > secret_number:
print("{} was incorrect. Your guess was too high. You have {} guesses left".format(guess, guess_count))
else:
print("{} was incorrect. Your guess was too low. You have {} guesses left".format(guess, guess_count))
def promptPlayAgain():
response = input("Would you like to play again? Type 'Y' or 'N'")
if response.upper() == "Y":
main()
# main
def main():
print("Welcome. You have {} guesses to guess the number. Guess a number between {} and {}: ".format(guess_count, n1, n2))
secret_num = random.randint(n1, n2)
while True:
if guess_count != 0:
guess = int(input("> "))
if isValid(guess):
if guess == secret_num:
winMessage()
break
else:
guessed()
incorrectGuessMessage()
else:
print("That is not a proper number")
continue
else:
loseMessage()
break
promptPlayAgain()
main()
3 Answers
Chris Freeman
Treehouse Moderator 68,423 PointsTo avoid using global
pass the variables as arguments:
# functions
def guessed(count, guess_count):
count += 1
guess_count-=1
EDIT: Above trivial example does not modify the variables in the global scope because the int
arguments are immutable. Pass arguments as list or dict:
>>> counts = {'count': 0, 'global_guesses': 0}
>>> def test_modifies_global(counts):
... counts['count'] += 1
... counts['global_guesses'] += 2
... print("counts", counts)
...
Kevin Faust
15,353 PointsThat's actually what I did at first but it wasn't updating the "count" and "guess_count" variables located inside my main() method
I tried again and still doesnt work
Am I supposed to return the count and guess_count variables from the guessed() method? and then update the variables from my main method?
Kevin Faust
15,353 Pointsi dont think im doing this right
Chris Freeman
Treehouse Moderator 68,423 PointsMy fault. The example I used was too trivial.
If you pass immutable arguments like integers, strings or tuples to a function, the passing acts like call-by-value. The object reference is passed to the function parameters. They can't be changed within the function, because they can't be changed at all, i.e. they are immutable. It's different, if we pass mutable arguments [like lists, dicts, classes]. They are also passed by object reference, but they can be changed in place in the function. If we pass a list to a function, we have to consider two cases: Elements of a list can be changed in place, i.e. the list will be changed even in the caller's scope. If a new list is assigned to the name, the old list will not be affected, i.e. the list in the caller's scope will remain untouched.
Reference
If count
were a list:
>>> count = [0]
>>> def test_modifies_global(count):
... count[0] += 1
... print("count:", count)
...
>>> count
[0]
>>> test_modifies_global(count)
count: [1]
>>> test_modifies_global(count)
count: [2]
>>> test_modifies_global(count)
count: [3]
>>> test_modifies_global(count)
count: [4]
Or a dict:
>>> counts = {'count': 0, 'global_guesses': 0}
>>> def test_modifies_global(counts):
... counts['count'] += 1
... counts['global_guesses'] += 2
... print("counts", counts)
...
>>> counts
{'count': 0, 'global_guesses': 0}
>>> test_modifies_global(counts)
counts {'count': 1, 'global_guesses': 2}
>>> test_modifies_global(counts)
counts {'count': 2, 'global_guesses': 4}
>>> test_modifies_global(counts)
counts {'count': 3, 'global_guesses': 6}
>>> counts
{'count': 3, 'global_guesses': 6}
Kevin Faust
15,353 Pointsthanks alot for that. I didn't understand the dict part as we haven't learned that yet but I do understand what you wrote with the list. Lists are mutable and so if we pass in a parameter that takes in a list and we modify that parameter, the list will be changed even from outside that function. if we pass in string or ints, then a local variable of that parameter will be created. makes sense
i encountered some problems now. This is a snippet from my guessed method. I tried to follow your example but I get this error: Index Error: List index out of range
This doesn't make sense to me because we are just increasing the length of the list by 1 or decreasing it by 1. Why would an Index Error possibly occur?
n1 = [0]
n2 = [10]
guessed(count, guess_count, n1, n2)
def guessed(count, guess_count, n1, n2):
count[n1] += 1
guess_count[n2] -=1
And also im trying to call len() on the list so i can get the actual number instead of something like [3]. I called the len() function on a list of 10 however instead of the number 10, i get the number 1. Any idea why this is the case?
This is another snippet
count = [0]
guess_count = [10]
n1 = 0
n2 = 10
print("Welcome. You have {} guesses to guess the number. Guess a number between {} and {}: ".format(len(guess_count), n1, n2))
What gets printed is "You have 1 guesses to......" It should say 10 instead of 1
Here is my full code as of now:
import random
# functions
def guessed(count, guess_count, n1, n2):
count[n1] += 1
guess_count[n2] -=1
def isValid(input):
try:
int(input)
return True
except ValueError:
return False
def winMessage(count, guess_count):
print("You guessed the number! It took you {} tries and you had {} guess left".format(count, guess_count))
def loseMessage():
print("You have used all your guesses. Game over")
def incorrectGuessMessage(guess, secret_num, guess_count):
if guess > secret_num:
print("{} was incorrect. Your guess was too high. You have {} guesses left".format(guess, guess_count))
else:
print("{} was incorrect. Your guess was too low. You have {} guesses left".format(guess, guess_count))
def promptPlayAgain():
response = input("""Would you like to play again? Type 'Y' or 'N':
> """)
if response.upper() == "Y":
main()
# main
def main():
count = [0]
guess_count = [10]
n1 = 0
n2 = 10
print("Welcome. You have {} guesses to guess the number. Guess a number between {} and {}: ".format(len(guess_count), n1, n2))
secret_num = random.randint(n1, n2)
while True:
if guess_count != 0:
guess = input("> ")
if isValid(guess):
guess = int(guess)
guessed(count, guess_count, n1, n2)
if guess == secret_num:
winMessage(len(count), len(guess_count))
break
else:
incorrectGuessMessage(guess, secret_num, len(guess_count))
continue
else:
print("That is not a proper number")
continue
else:
loseMessage()
break
promptPlayAgain()
main()
Chris Freeman
Treehouse Moderator 68,423 PointsThe key is not to confuse the index of a value and the list with the actual value.
count = [0] # list with one item at index 0 with value count[0]
guess_count = [10] # list with one item at index 0 with value guess_count[0]
def guessed(count, guess_count):
# count and guess_count passed as lists
# modify the first item in list count. This is the actual count value
count[0] += 1
# modify the first item in list guess_count. This is the actual guess_count value
guess_count[0] -=1
My example of modifying the lists count
and guess_count
were intended to be examples of technique and not necessarily directly applicable to your code situation. In my example, I was using a 1-item list for count
and guess_count
to illustrate how the results of passing a list and modifying the items of that list within a function can be seen outside of the function.
Overall, I'm not sure how you are using count
vs guess_count
. Are n1
and n2
used as the initial values for the low and high limits?
Kevin Faust
15,353 PointsOh I completely misinterpreted what you were saying. I thought that count = [0] and guess_count = [10] meant that we were creating a list with 0 items and 10 items respectively and therefore the lengths of each are 0 and 10 respectively. I got confused with java where you can specify the initial length of an array. After I realized my mistake, everything made sense instantly.
The program is working perfectly now. thanks for the help
SNEHA VASANTH
4,455 Pointsdef playAgainCheck():
print("Do you want to play again? Y/N ")
while True:
playAgain = input("> ")
if playAgain == "Y":
return True
elif playAgain == "N":
return False
else:
print("Please enter Y or N only")
def checkNumber():
print("Is the number bigger or smaller? B/S ")
while True:
checkGuess = input("> ")
if checkGuess == "S":
return "S"
elif checkGuess == "B":
return "B"
else:
print("Please enter either S or B ")
def guessRandomNumber(count,number1,number2,removeList):
valuesList = []
values = range(number1,number2+1)
#print(values)
for i in values:
if i not in valuesList:
valuesList.append(i)
for i in removeList:
#print(removeList)
if i in valuesList:
#print(valuesList)
valuesList.remove(i)
random.shuffle(valuesList)
return valuesList
import random
# check for int input
# too high
# too low
# play again
count = 0
keepPlaying = True
smallBig = "B"
guess = 0
while keepPlaying:
if count == 0:
guessList = []
removeList = []
number1 = 1
number2 = 10
guess = random.randint(1,10)
removeList.append(guess)
else:
guessList = guessRandomNumber(count,number1,number2,removeList)
#for item in guessList:
#print(item)
guess = guessList.pop()
removeList.append(guess)
#print(removeList)
count += 1
answer = input("Computer says {}, Is this right? Y/N ".format(guess))
if answer == "Y":
print("Computer won!")
count = 0
keepPlaying = playAgainCheck()
elif count == 5:
count = 0
print("Computer lost!")
keepPlaying = playAgainCheck()
else:
smallBig = checkNumber()
if smallBig == "S":
number2 = guess
else:
number1 = guess
Kevin Faust
15,353 PointsKevin Faust
15,353 PointsOk I did this and it worked. However, I read on stackoverflow that we should NOT use global variables but i honestly dont know how to do this without the use of global variables. i did not yet watch kenneth's solution yet. i was wondering if I can have some feedback on this code.