Having troubles changing value of global variable - python

I am trying to create a battleships game to practice my coding, however I am having trouble changing the value of a global variable.
turnsover = 0
diff = 0
ship_row = 0
ship_col = 0
def difficulty():
global diff
global turnsover
diff = input("Please select a difficulty\n 1=Easy \n 2=Meduim \n 3=Hard \n 4=VS Machine\n")
if diff.isdigit():
diff = int(diff)
if int(diff) not in range(1,5):
print("Please select a correct difficulty level")
difficulty()
if diff == 1:
turnsover == 20
print("Difficulty level: Easy")
if diff == 2:
turnsover == 15
print("Difficulty level: Meduim")
if diff == 3:
turnsover == 10
print("Difficulty level: Hard")
if diff == 4:
turnsover == randint(1, 26)
print("Difficulty level: Vs Machine")
####REMOVE AFTER PROD####
print(turnsover)
else:
print("Please select a correct difficulty level")
difficulty()
The prod test print of turnsover returns 0 instead of returning the new amount of turnsover (aka lifes remaining)

As #MorganThrapp says, you are checking turnsover equality with code such as turnsover == 10 and not assigning a value to it like so: turnsover = 0. = means assignment and == means equality. This should be obvious as you're assigning values to the global variables at the beginning of your code.

Related

Mastermind Python coding

Ok I have a feeling that this is a simple simple issue but I have been staring at this code for about 10 hours now.
The issue I am having is in mastermind is that once I get it to recognize that I have the correct colors in the right spot I can get it to display the right spots with X and the wrong spots with O. I need to be able to convert that so instead of X and O I need it to tell the user that he/she has 2 blacks and one white
For example: The secret code is RGYB The user enters RGOY so then Python relays "You have 2 blacks(The R and G spots) and one 1 White (The Y because it's the right color just in the wrong index) As of right now I got it to display X for the right color in the right spot and anything else it is an O
I will post what I have been working with now but today I am at my wit's end
https://pastebin.com/HKK0T7bQ
if correctColor != "XXXX":
for i in range(4):
if guess[i] == tempCode[i]:
correctColor += "X"
if guess[i] != tempCode[i] in tempCode:
correctColor += "O"
print (correctColor + "\n")
if correctColor == "XXXX":
if attempts == 1:
print ("You think you are sweet because you got it right on the first try? Play me again!")
else:
print ("Well done... You needed " + str(attempts) + " attempts to guess.")
game = False
A few comments
X and O
you use X and 0 to denote the success, it will be easier and faster to use a list or tuple or booleans for this, that way you can use sum() to count how many colors and locations were correct. Then whether you represent that with X and O or red and white pins is a matter for later
compartmentalization
Your game logic (guess input, input validation, do you want to continue, etc) is mixed with the comparison logic, so it would be best to separate the different functions of your program into different methods.
This is an fineexample to introduce object oriented programming, but is so simple it doesn't need OO, but it can help. What you need is a method which takes a series of colours and compares it to another series of colours
Standard library
Python has a very extended standard library, so a lot of stuff you want to do probably already exists
Correct colours
to count the number of letters which occur in 2 strings, you can use collections.Counter
guess = "RGOY "
solution = "RGYB"
a = collections.Counter(guess)
b = collections.Counter(solution)
a & b
Counter({'G': 1, 'R': 1, 'Y': 1})
correct_colours = sum((a & b).values())
3
So the user guessed 3 colours correctly
Correct locations
can be solved with an easy list comprehension
[g == s for g, s in zip(guess, solution)]
[True, True, False, False]
sum(g == s for g, s in zip(guess, solution))
2
so the used put 2 colours on the correct location
This is a MasterMind I made in Python. Hope you like it and it helped you! :)
import random
import time
from tkinter import *
def select_level():
global level
level = level_selector.get()
root.destroy()
root = Tk()
level_selector = Scale(root, from_=1, to=3, tickinterval=1)
level_selector.set(0)
level_selector.pack()
Button(root, text="Select a difficulty level", command=select_level).pack()
mainloop()
cpc_1_digit = 0
cpc_2_digit = 0
cpc_3_digit = 0
cpc_4_digit = 0
p_1_digit = 0
p_2_digit = 0
p_3_digit = 0
p_4_digit = 0
correct_correct = 0
correct_wrong = 0
chances = 0
if level == 1:
chances = 15
elif level == 2:
chances = 10
else:
chances = 7
cpc_1_digit = random.randint(0, 9)
while cpc_2_digit == cpc_1_digit or cpc_2_digit == cpc_3_digit or cpc_2_digit ==
cpc_4_digit:
cpc_2_digit = random.randint(0, 9)
while cpc_3_digit == cpc_1_digit or cpc_3_digit == cpc_2_digit or cpc_3_digit ==
cpc_4_digit:
cpc_3_digit = random.randint(0, 9)
while cpc_4_digit == cpc_1_digit or cpc_4_digit == cpc_2_digit or cpc_4_digit ==
cpc_3_digit:
cpc_4_digit = random.randint(0, 9)
while chances > 0:
correct_correct = 0
correct_wrong = 0
answer = input("Enter a four-digit number with different digits (e.g 1476): ")
p_1_digit = int(answer[0])
p_2_digit = int(answer[1])
p_3_digit = int(answer[2])
p_4_digit = int(answer[3])
if p_1_digit == cpc_1_digit:
correct_correct = int(correct_correct) + 1
elif p_1_digit == cpc_2_digit or p_1_digit == cpc_3_digit or p_1_digit ==
cpc_4_digit:
correct_wrong = int(correct_wrong) + 1
else:
pass
if p_2_digit == cpc_2_digit:
correct_correct = correct_correct + 1
elif p_2_digit == cpc_1_digit or p_2_digit == cpc_3_digit or p_2_digit ==
cpc_4_digit:
correct_wrong = int(correct_wrong) + 1
else:
pass
if p_3_digit == cpc_3_digit:
correct_correct = int(correct_correct) + 1
elif p_3_digit == cpc_1_digit or p_3_digit == cpc_2_digit or p_3_digit ==
cpc_4_digit:
correct_wrong = int(correct_wrong) + 1
else:
pass
if p_4_digit == cpc_4_digit:
correct_correct = int(correct_correct) + 1
elif p_4_digit == cpc_1_digit or p_4_digit == cpc_3_digit or p_4_digit ==
cpc_2_digit:
correct_wrong = int(correct_wrong) + 1
else:
pass
print("")
if int(correct_correct) == 4:
print("Congratsulations! You found the computer's number!")
break
elif int(correct_wrong) > 0 or int(correct_correct) >= 1 and int(correct_correct)
< 4:
print("You got " + str(correct_correct) + " correct digit(s) in the correct
place, and " + str(correct_wrong) + " correct digit(s) but in wrong place.")
elif int(correct_correct) == 0 and int(correct_wrong) == 0:
print("You didn't guess any number, try again!")
else:
raise Exception("CheckError: line 69, something went wrong with the
comparings.")
exit()
print("")
chances = chances - 1
if chances == 0:
print("You lost... The secret number was " + str(cpc_1_digit) + str(cpc_2_digit)
+ str(cpc_3_digit) + str(cpc_4_digit) + ". Try again by rerunning the program.")
time.sleep(4)

Python splitting code into functions [duplicate]

This question already has answers here:
Using global variables in a function
(25 answers)
Parameter vs Argument Python [duplicate]
(4 answers)
Closed 5 years ago.
Sorry about the length of this but I figured more info is better than not enough!!
I'm trying to split the (working) piece of Python code into functions to make it clearer / easier to use but am coming unstuck as soon as i move stuff into functions. It's basically a password generator which tries to only output a password to the user once the password qualifies as having a character from all 4 categories in it. (Lowercase, uppercase, numbers and symbols).
import random
import string
lowerasciis = string.ascii_letters[0:26]
upperasciis = string.ascii_letters[26:]
numberedstrings = str(1234567809)
symbols = "!#$%^&*()[]"
password_length = int(raw_input("Please enter a password length: "))
while True:
lowerasscii_score = 0
upperascii_score = 0
numberedstring_score = 0
symbol_score = 0
password_as_list = []
while len(password_as_list) < password_length:
char = random.choice(lowerasciis+upperasciis+numberedstrings+symbols)
password_as_list.append(char)
for x in password_as_list:
if x in lowerasciis:
lowerasscii_score +=1
elif x in upperasciis:
upperascii_score +=1
elif x in numberedstrings:
numberedstring_score +=1
elif x in symbols:
symbol_score +=1
# a check for the screen. Each cycle of the loop should display a new score:
print lowerasscii_score, upperascii_score, numberedstring_score, symbol_score
if lowerasscii_score >= 1 and upperascii_score >= 1 and numberedstring_score >= 1 and symbol_score >=1:
password = "".join(password_as_list)
print password
break
And here is my attempt at splitting it. When i try to run the below it complains of "UnboundLocalError: local variable 'upperascii_score' referenced before assignment" in the scorepassword_as_a_list() function
import random
import string
lowerasciis = string.ascii_letters[0:26]
upperasciis = string.ascii_letters[26:]
numberedstrings = str(1234567809)
symbols = "!#$%^&*()[]"
password_length = int(raw_input("Please enter a password length: "))
lowerasscii_score = 0
upperascii_score = 0
numberedstring_score = 0
symbol_score = 0
password_as_list = []
def genpassword_as_a_list():
while len(password_as_list) < password_length:
char = random.choice(lowerasciis+upperasciis+numberedstrings+symbols)
password_as_list.append(char)
def scorepassword_as_a_list():
for x in password_as_list:
if x in lowerasciis:
lowerasscii_score +=1
elif x in upperasciis:
upperascii_score +=1
elif x in numberedstrings:
numberedstring_score +=1
elif x in symbols:
symbol_score +=1
# give user feedback about password's score in 4 categories
print lowerasscii_score, upperascii_score, numberedstring_score, symbol_score
def checkscore():
if lowerasscii_score >= 1 and upperascii_score >= 1 and numberedstring_score >= 1 and symbol_score >=1:
return 1
else:
return 0
def join_and_printpassword():
password = "".join(password_as_list)
print password
while True:
genpassword_as_a_list()
scorepassword_as_a_list()
if checkscore() == 1:
join_and_printpassword()
break
The primary issue here is that you need to keep track of the scope of the various variables that you're using. In general, one of the advantages of splitting your code into functions (if done properly) is that you can reuse code without worrying about whether any initial states have been modified somewhere else. To be concrete, in your particular example, even if you got things working right (using global variables), every time you called one of your functions, you'd have to worry that e.g. lowerassci_score was not getting reset to 0.
Instead, you should accept anything that your function needs to run as parameters and output some return value, without manipulating global variables. In general, this idea is known as "avoiding side-effects." Here is your example re-written with this in mind:
import random
import string
lowerasciis = string.ascii_letters[0:26]
upperasciis = string.ascii_letters[26:]
numberedstrings = str(1234567809)
symbols = "!#$%^&*()[]"
def genpassword_as_a_list(password_length):
password_as_list = []
while len(password_as_list) < password_length:
char = random.choice(lowerasciis+upperasciis+numberedstrings+symbols)
password_as_list.append(char)
return password_as_list
def scorepassword_as_a_list(password_as_list):
lowerasscii_score = 0
upperascii_score = 0
numberedstring_score = 0
symbol_score = 0
for x in password_as_list:
if x in lowerasciis:
lowerasscii_score +=1
elif x in upperasciis:
upperascii_score +=1
elif x in numberedstrings:
numberedstring_score +=1
elif x in symbols:
symbol_score +=1
# give user feedback about password's score in 4 categories
return (
lowerasscii_score, upperascii_score, numberedstring_score,
symbol_score
)
def checkscore(
lowerasscii_score, upperascii_score, numberedstring_score,
symbol_score):
if lowerasscii_score >= 1 and upperascii_score >= 1 and numberedstring_score >= 1 and symbol_score >=1:
return 1
else:
return 0
def join_and_printpassword(password_as_list):
password = "".join(password_as_list)
print password
password_length = int(raw_input("Please enter a password length: "))
while True:
password_list = genpassword_as_a_list(password_length)
current_score = scorepassword_as_a_list(password_list)
if checkscore(*current_score) == 1:
join_and_printpassword(password_list)
break
A few notes on this:
Notice that the "score" variables are introduced inside the scorepassword_as_list function and (based on the scoping rules) are local to that function. We get them out of the function by passing them out as a return value.
I've used just a bit of magic near the end with *current_score. Here, the asterisk is used as the "splat" or "unpack" operator. I could just as easily have written checkscore(current_score[0], current_score[1], current_score[2], current_score[3]); they mean the same thing.
It would probably be useful to read up a bit more on variable scoping and namespaces in Python. Here's one guide, but there may be better ones out there.

Beginner in Python, can't get this for loop to stop

Bit_128 = 0
Bit_64 = 0
Bit_32 = 0
Bit_64 = 0
Bit_32 = 0
Bit_16 = 0
Bit_8 = 0
Bit_4 = 0
Bit_2 = 0
Bit_1 = 0
Number = int(input("Enter number to be converted: "))
for power in range(7,0,-1):
if (2**power) <= Number:
place_value = 2**power
if place_value == 128:
Bit_128 = 1
elif place_value == 64:
Bit_64 = 1
elif place_value == 32:
Bit_32 = 1
elif place_value == 16:
Bit_16 = 1
elif place_value == 8:
Bit_8 = 1
elif place_value == 4:
Bit_4 = 1
elif place_value == 2:
Bit_2 = 1
elif place_value ==1:
Bit_1 = 1
Number = Number - (place_value)
if Number == 0:
print ("Binary form of"),Number,("is"),Bit_128,Bit_64,Bit_32,Bit_16,Bit_8,Bit_4,Bit_2,Bit_1
I want this loop to move to the next 'power' value when it fails the first if condition, but when I run it in an interpreter, the program keeps on running despite the first condition not being true. I only want it to move on the next conditions if the first condition turns out to be true.
How can I do this? This is my first "big" program in python, and I'm having a hard time figuring this out. Any tips would be appreciated. Btw, the program is meant to convert any number from 1-255 to binary form.
If you want a loop to go to the next value, all you need to do is use the continue keyword:
...
for power in range(7,0,-1):
if (2**power) <= Number:
place_value = 2**power
continue
...
Just using "break" statement , to break the current loop when the condition is satisfied.

Using a while loop to add and subtract a current location

def main():
global currentX,currentY
currentX = 0
currentY = 0
currentlocation = currentX,currentY
print("Starting Location is", currentX,currentY)
print()
#Main menu dialouge
print("Please select direction:")
print("1, North;")
print("2, East;")
print("3, South;")
print("4, West;")
print("5, End this program")
#Loop = to 1 so while loop will go on indefitly until option 5 is pressed.
loop = 1
#try: handles all errors along with except:
try:
while loop == 1:
direction = input("--> ")
print()
direction = int(direction)
if direction == 1:
moveN = currentY + 1
print("Moved North.",currentlocation)
elif direction == 2:
currentX + 1
print("Moved East.",currentlocation)
elif direction == 3:
currentY - 1
print("Moved South.",currentlocation)
elif direction == 4:
currentX - 1
print("Moved West.",currentlocation)
elif direction == 5:
loop = 0
print("Final location is", currentlocation)
else:
print("ERROR:", choice, "is an invalid input.\n"
"Enter a number from 1 to 5.")
except: ValueError
print("Please enter a whole number between 1-5")
main()
I can't figure out why the loop doesn't add to the currentlocation.
I get an output like
Starting Location is 0 0
Please select direction:
1, North;
2, East;
3, South;
4, West;
5, End this program
--> 3
Moved South. (0, 0)
--> 4
Moved West. (0, 0)
You aren't actually changing currentX and currentY, you're merely evaluating the values you want them to have. To change them, you need to assign to them:
currentX = currentX + 1
or, more concisely:
currentX += 1
Your direction 1 case also looks off. For some reason you're assigning to moveN. I have no idea what that's supposed to do.
Edit: You also need to update currentlocation to reflect the changes in position.
When you say
currentlocation = currentX,currentY
You're not actually creating a tuple with references to currentX and currentY, you're creating a tuple with whatever values were in currentX and currentY at the time it was declared. So every time you change those, it's not updated.
One way to fix this is turn currentlocation into a function.
def currentlocation():
return currentX,currentY
Then, instead of
print(currentlocation)
Just put
print(currentlocation())

Do while loops have local variables in Python?

I am trying to use a while statement like so:
o = 0
while o == 0:
try:
n = int(raw_input("Which number do you want to begin with?"))
o = 1
except:
o = 0
print "Please use a valid number."
However, when I try to use variable n later, it gives me the "local variable 'n' referenced before assignment' UnboundLocalError. That means that n cannot be recognized as a variable in the def I am using, because it only exists in the while statement? Is this possible?
The whole code:
import time
from sys import argv
import os
os.system("cls")
print "Welcome to Number counter 2.0!"
a = True
def program():
global a
if a == False:
os.system("cls")
o = 0
while o == 0:
try:
n = int(raw_input("Which number do you want to begin with?"))
o = 1
except:
o = 0
print "Please use a valid number."
if n == "/historyKeep false":
if a == False:
print "Command historyKeep is already set to false."
else:
a = False
print "Command set successfully."
elif n == "/historyKeep true":
if a == True:
print "Command historyKeep is already set to true."
else:
a = True
print "Command set successfully."
if n == "/historyKeep false":
n = raw_input("Which number do you want to begin with?")
elif n == "/historyKeep true":
n = raw_input("Which number do you want to begin with?")
d = raw_input("How many seconds between each number?")
d = int(d)
total_s = n * d
while n > 0:
print n
time.sleep(d)
n = n - 1
print "Done in", total_s, "seconds in total!"
end_q = raw_input("Exit or retry? (e/r)")
if end_q == "e":
os.system("cls")
print "Exiting."
time.sleep(0.5)
os.system("cls")
print "Exiting.."
time.sleep(0.5)
os.system("cls")
print "Exiting..."
time.sleep(0.5)
os.system("cls")
exit(0)
elif end_q == "r":
program()
program()
You set a = True at the beginning. You then test if a == False and only set n if it is. But then you test n == "/history.... n has not been set at this point.
You need to make sure n is assigned before you use it. It is not enough to just mention it in a branch that is not taken.
n is not defined in the scope that you are trying to use it to fix this define it outside of the while loop and the if statement the while loop is in:
global a
n = 0
Then when you ask the user for what number to start with, that value will replace 0, and you should be good to go. Also instead of declaring global a, why not just make a an input argument for the program() function?
Just to make sure, declare n outside of the loop first:
n = None
while True:
try:
n = int(raw_input("Text..."))
break
except:
print("Please enter a valid number!")
Note: Usually, you would use break to exit a loop. This is because your method requires an extra variable, which uses more memory (not much, but if you keep doing it, it will stack up).

Categories

Resources