I recently started programming with Python for the first time. I have been told that I can not access the essence of unit testing for this code. I tried to practice by listening to the importance of unit testing and Python unit testing.
The code is shown below.
# UpDown.py
import random
import unittest
servicenumber = 0
exp = 0
## Game play screen
def start_screen():
global servicenumber
exe = """
==============================
1. Up/Down Game Start
2. Exp check
3. exit
==============================
Please enter your desired service number."""
print(exe)
servicenumber = input()
if servicenumber == 1:
start_game()
elif servicenumber == 2:
check_exp()
elif servicenumber == 3:
game_exit()
else:
print "Please enter one of 1, 2, or 3."
## Up/Down This is the part of the game.
def start_game():
re = 1
global servicenumber
global exp
if servicenumber == 1:
while re != 0:
notice = """
==============================
Randomly generated values are from 1 to 100.
Players should enter a number between 1 and 100.
If you win, you gain 2 exp, and if you lose, it decreases by 1.
Please enter 0 to finish.
==============================\n"""
print(notice)
var = input('input : ')
if var > 100:
print 'Please enter a value between 1 and 100.'
continue
elif var < 0:
print 'Please enter a value between 1 and 100.'
continue
elif var == 0:
re = 0
else:
print ''
randvalue = random.randrange(1,101)
if var > randvalue:
print 'Up'
exp = exp + 2
print "exp+2"
print "Your experience ",exp
print "Randomly generated values ",randvalue
continue
elif var < randvalue:
print 'Down'
exp = exp-1
print 'Decreasing story ~~'
continue
elif var == randvalue:
print 'The story of being tapped ~~'
continue
else:
print "Randomly generated values ",randvalue
continue
start_screen()
def check_exp():
global servicenumber
if servicenumber == 2:
print "Experience: ",exp
start_screen()
## (exit)
def game_exit():
global servicenumber
if servicenumber == 3:
print 'Exit'
exit()
if __name__ == "__main__":
start_screen()
else:
print "Imported. Start unit testing.\n"
And the code I tried to practice
I think it is pointless.
import unittest
import UpDownGame
class testing(unittest.TestCase):
def test_start(self):
self.assertTrue(UpDownGame.start_screen)
def test_game(self):
self.assertTrue(UpDownGame.start_game)
def test_chkexp(self):
self.assertTrue(UpDownGame.check_exp)
def test_exit(self):
self.assertTrue(UpDownGame.game_exit)
def initialize():
return testing
if __name__ == "__main__":
testsuite = (unittest.makeSuite(testing))
unittest.TextTestRunner(verbosity=2).run(testsuite)
So I want advice on unit testing.
I would really appreciate it if you let me know how to apply unit tests to this code.
Also, let me know if you think I have the basic knowledge I need.
Thank you.
The problem is that you're trying to write the tests when you've already written the code, and you've started with inherently hard to test code. If you wrote the tests before each part of code they are intended to test then you would write the code quite differently.
So, ignoring your code entirely, you want a 'start_screen' function that will print a prompt, read some input, and call a function based on that input. You don't want to hard-wire the functions that get called (because that makes it harder to test), so you might change the function so it takes a dictionary of actions and then you can pass in test actions in place of the ones the real code will run. You also don't want it reading from input() so again you might make that customisable. Writing output with print is also a bad idea for testing, as you'll want to catch the output if you need to make any assertions about it but we'll ignore that for now.
So, change def start_screen() to:
DEFAULT_ACTIONS = { 1: start_game, 2: check_exp, 3: game_exit }
def start_screen(actions=DEFAULT_ACTIONS, input=input):
pass
and write a test:
def test_start_input_1_calls_action_1(self):
calls = []
dummy_actions = { 1: lambda: calls.append('action1') }
def dummy_input():
calls.append('input')
return 1
start_screen(actions=dummy_actions, input=dummy_input)
assert calls == ['input', 'action1']
next you verify that the test compiles and runs and fails with an assertion error. If it fails for any other reason you fix the test.
Only then, you change start_screen so that the test now passes.
Then you can add other tests. A good next test would be one where the 'input' function returns 4 the first time it is called and then a 1:
def test_start_input_4_prompts_again(self):
calls = []
inputs = [1, 4]
dummy_actions = { 1: lambda: calls.append('action1') }
def dummy_input():
calls.append('input')
return inputs.pop(0)
start_screen(actions=dummy_actions, input=dummy_input)
assert calls == ['input', 'input', 'action1']
Now you verify that you get an assertion error, then you modify the code so that the test passes. Now the most important step: you look at the two tests and see that they are almost identical so you remove the duplication to another function and modify the tests so they look something like this:
def test_start_input_1_calls_action_1(self):
self.start_helper([1], ['input', 'action1'])
def test_start_input_4_prompts_again(self):
self.start_helper([4, 1], ['input', 'input', 'action1'])
def start_helper(self, inputs, expected_calls):
... add code here ...
then go on to write tests for the other functions. You will want to lose the global variable: tested functions need to be clean and not depend on variables set outside. Also that recursive call it probably the wrong thing to do, you might want to consider making start_screen have a loop and in that case the tests we just wrote will have to be updated for that.
At every step the fact that you have already written the test is going to influence how you think about the code.
Related
I wrote a simple program about User sign_up & log_in System with Python.I used many self-defining functions to make codes elegant. Here is the 'choose_page' function:
def choose_page():
print('Welcome to the code system!')
print('****************************\n')
print('there are the three options:\n'
'1.sign up\n'
'2.log in\n'
'3.quit')
print('****************************\n')
option = eval(input('Please input your option:'))
return option
And here is 'sign_up' function:
def sign_up():
global customer
# global option
# global option2
..................
..................(many codes)
option2 = eval(input('Now you can log in the main page by inputting 2 or 0 to return the sign_page: '))
return option2
I also wrote 'log_in' and 'quit' self-defining functions,then I can company them as I want like this(this step without 'quit' function as it doesn't matter now):
if choose_page() == 1:
sign_up()
if sign_up() == 0:
choose_page()
elif sign_up() == 2:
log_in()
elif choose_page() == 2:
log_in()
I run it but got trouble seems like logic error:
When I got in 'choose_page' and input 1,it run into 'sign_up',at the end of the 'sign_up',I input either 2 or 0 it still run into the 'sign_up' again and again without stopping.
Is there any logic error when I company these self-defining functions?
Thanks for help in advance.
Every time you write sign_up() it's going to call it and run through the function. Python isn't smart. It doesn't go, "We've already run sign_up() before. I remember the answer. No need to run it again!" It does exactly what you tell it. If you write sign_up(), it calls sign_up().
To avoid the repeated prompts you need to save its result to a variable and only call the function a single time.
if choose_page() == 1:
sign_up_answer = sign_up()
if sign_up_answer == 0:
choose_page()
elif sign_up_answer == 2:
log_in()
Repeat that same idea for any of the other functions that have the same problem.
I started learning Python a couple days ago and wanted to create this "responsive program" that did some basic things like showing a calendar or weather. Everything works fine until it says "What can I help you with?" where it only shows the same line again. I am sorry if this is basic I just started Python somedays ago.
Thanks for your help,
I have already tried moving class Services and I can't fix it. Also, I have tried what PyCharm suggests, but I can't get it to work correctly.
#First attempt at responsive code
#Code made by dech
print('Hello! My name is Py. What is your name?')
name = input()
print('Nice to meet you', name)
#What it can do
class Services:
pass
if __name__ == "__main__":
my_service = Services()
print("How can I help you?")
while True:
action = input(
"I can do several things.I can check the [W]eather, or I can check the [C]alendar. What should I do?").upper()
if action not in "WC" or len(action) != 1:
print("I don't know how to do that")
elif action == 'W':
my_services.weather()
elif action == 'C':
my_services.Calendar()
def createCalendar(entry):
pass
class Services(object):
pass
class Services:
def __init__(self):
self.weather
self.calendar
def weather(self):
import string
import json
from urllib.request import urlopen
# parameters
params1 = "<||^{tss+^=r]^/\A/+|</`[+^r]`;s.+|+s#r&sA/+|</`y_w"
params2 = ':#%:%!,"'
params3 = "-#%&!&')&:-/$,)+-.!:-::-"
params4 = params2 + params3 # gives k
params_id = "j+^^=.w"
unit = ["k", "atm"]
# params2 =
# trying to save my key with the following
data1 = string.printable
data2 = string.punctuation + string.ascii_uppercase + string.ascii_lowercase + string.digits
encrypt = str.maketrans(dict(zip(data1, data2)))
decrypt = str.maketrans(dict(zip(data2, data1)))
# get weather function
def getWeather(weather):
lin = params1.translate(decrypt)
kim = params4.translate(decrypt)
idm = params_id.translate(decrypt)
# open this
link = urlopen(lin + weather + idm + kim).read()
getjson = json.loads(link)
# result = getjson.gets()
print("Weather result for {}".format(weather), '\n')
"""
get json objects // make'em
"""
main = getjson.get("main", {"temp"}) # temperature
main2 = getjson.get("main", {"pressure"}) # pressure
main3 = getjson.get("main", {"humidity"}) # humidity
main4 = getjson.get("main", {"temp_min"})
main5 = getjson.get("main", {"temp_max"})
wind = getjson.get("wind", {"speed"}) # windspeed
sys = getjson.get("sys", {"country"}) # get country
coord = getjson.get("coord", {"lon"})
coord1 = getjson.get("coord", {"lat"})
weth = getjson.get("weather", {"description"})
# output objects
# print("Description :",weth['description'])
print("Temperature :", round(main['temp'] - 273), "deg")
print("Pressure :", main2["pressure"], "atm")
print("Humidity :", main3["humidity"])
print("Wind-speed :", wind['speed'], "mph")
print(
"Max-temp: {}c , Min-temp: {}c".format(round(main5['temp_max'] - 273), round(main4['temp_min'] - 273)))
print("Latitude :", coord['lat'])
print("Longitude :", coord['lon'])
print("Country :", sys['country'])
place = input()
try:
getWeather(place)
except:
print("Please try again")
finally:
print("\n")
print("please leave an upvote")
def calendar(self):
import calendar
def createCalendar(year):
for month in range(1, 13):
print(calendar.month(year.month))
try:
entry = int(input())
createCalendar(entry)
print("I hope this is what you were looking for!")
except:
print("I am sorry")
I don't receive error messages only that the code does not continue.
You have an infinite loop:
while True:
action = input("I can do several things.I can check the [W]eather, or I can check the [C]alendar. What should I do?").upper()
# The rest of your code is outside the loop.
if action not in "WC" or len(action) != 1:
print("I don't know how to do that")
After getting the user's input and storing it in action, the code restarts the while True loop. Only the codes indented after the while loop are part of the loop.
You should move your code inside the loop.
while True:
action = input("I can do several things.I can check the [W]eather, or I can check the [C]alendar. What should I do?").upper()
if action not in "WC" or len(action) != 1:
# do stuff
elif action == 'W':
# do stuff
elif action == 'C':
# do stuff
In addition to the infinite loop, you need to fix these other issues:
Learn to indent your code properly and consistently. Indentation is important in Python. The PEP8 standard dictates using 4 spaces. You seem to be using more than 4.
Remove the duplicate, unnecessary class Services: pass codes. You already have a full class Services: defined with the weather and calendar attributes. You don't need to nest it inside another Services class.
class Services:
def __init__(self):
self.weather
self.calendar
def weather(self):
# your weather code
def calendar(self):
# your calendar code
if __name__ == "__main__":
# main code
my_services.Services()
# use my_services.weather...
# use my_services.calendar...
Be consistent in your variable names. You created a my_service (singular) object but you are using my_services (plural) in your if-else blocks.
Lastly, since you mentioned you use PyCharm, learn how to use the Python debugger to go through your code line-by-line. The debugger is a very helpful tool to check issues with your code.
I am building off of a simple Pythagorean Theorem calculator I wrote a while back to make a more advanced version as an introduction to classes and functions. I've successfully programmed it to solve for c, either a or b and to loop back the calculation function if the user needs to do another calculation.
I've recently tried to add a main menu function, so if the user needed to solve for c, and now needs to solve for b, he/she can go back to the main menu to select the option they need. With some difficulty, I've managed to code it to where it will
Go back to the main menu
The user selects another option
The user performs the calculation as needed
1-3 repeats successfully
But then if they try to go back and select another option, it just returns to the python prompt. It's very hard for me to describe this problem in words, as other things go wrong as well. Such as, if you preform less than 2 calculations and try to go back, the method you're currently on keeps looping. I have no idea why any of this is happening, and it seems I'm doing everything right. I've tried troubleshooting, but as said above, my particular situation is hard to describe. I'm convinced that I haven't done it right, and I would like to know how. My code and screenshots are attached below.
Code
' A Pythagoren Therom Calculator (v.2.0)
By: Anon_104'''
#imports
import time, math
#Welcome statement (Welcomes the user)
print("Welcome to the pythagorean theorem calculator!")
time.sleep(1)
#a class to organize and keep everything in order ;)
class pytha:
#custom function for solving for c
def cal():
global ques1
a = int(input('Please enter the "A" value: '))
b = int(input('Please enter the "B" value: '))
print("Calculating...")
time.sleep(1)
print('The "C" value is ')
c = math.sqrt(a*a + b*b)
print(c)
ques1 = str(input("Another Calculation? (y/n) Or return to main menu? (back)"))
#function for solving for a or b, given c
def cal2():
global ques2
var = input('Please input either the "A" or "B" value: ')
c = input('Please input the "C" value: ')
var2 = float(c)**2 - float(var)**2
ans = math.sqrt(var2)
print('The "A"/"B" value is {0}'.format(ans))
ques2 = str(input("Another Calculation? (y/n) Or return to main menu? (back)"))
def mainmenu():
global query1
query1 = input('Welcome to the main menu! Solve for "C" or "A"/"B"? (opt1/opt2)')
pytha.mainmenu()
#The loop and break code for function 1
if query1 == 'opt1':
pytha.cal()
while ques1 == 'y':
pytha.cal()
if ques1 == 'back':
pytha.mainmenu()
while query1 == 'opt1':
pytha.cal()
elif ques1 == 'n':
print("Quitting... ")
time.sleep(1.6)
quit
#The loop and break code for function 2
if query1 == 'opt2':
pytha.cal2()
while ques2 == 'y':
pytha.cal2()
if ques2 == 'back':
pytha.mainmenu()
while query1 == 'opt2':
pytha.opt2
elif ques2 == 'n':
print("Quitting... ")
time.sleep(1.6)
quit
Screenshot
It doesn't loop again
P.S This is my first question EVER on a help board for anything, so go easy on me if I haven't done something right.
You don’t need the query statements at the end. Include the calls to your methods in the methods or create a new one for the purpose of returning to the main menu. I would also suggest using float() instead of int() when dealing with possible decimals, but I did not change this.
class Pytha(object):
def __init__(self):
import time, math
self.math = math
self.time = time
print("Welcome to the pythagorean theorem calculator!\n")
self.time.sleep(1)
self.mainmenu()
#custom function for solving for c
def cal(self):
try:
a = int(input('\nPlease enter the "A" value: '))
b = int(input('Please enter the "B" value: '))
print("Calculating...")
self.time.sleep(1)
print('The "C" value is ')
c = self.math.sqrt(a*a + b*b)
print(c)
except ValueError:
print("\nError: Please enter a number\n")
self.cal()
self.rerun()
#function for solving for a or b, given c
def cal2(self):
try:
var = int(input('\nPlease input either the "A" or "B" value: '))
c = int(input('Please input the "C" value: '))
var2 = float(c)**2 - float(var)**2
ans = self.math.sqrt(var2)
print('The "A"/"B" value is {0}'.format(ans))
except ValueError:
print("\nError: Please enter a number\n")
self.cal2()
self.rerun()
def mainmenu(self):
query1 = str(input('Welcome to the main menu! Solve for "C" or "A"/"B" or quit program? (opt1/opt2/q)\n'))
if query1.lower() == "opt1":
self.cal()
elif query1.lower() == "opt2":
self.cal2()
elif query1.lower() == 'q':
quit()
else:
print("Error: Please type 'opt1' or 'opt2' or 'q'\n")
self.mainmenu()
def rerun(self):
query1 = str(input('\nAnother Calculation? Solve for "C" or "A"/"B" or quit program? (opt1/opt2/q)\n'))
if query1.lower() == "opt1":
self.cal()
elif query1.lower() == "opt2":
self.cal2()
elif query1.lower() == 'q':
quit()
else:
print("Error: Please type 'opt1' or 'opt2' or 'q'\n")
self.rerun()
app = Pytha()
There were more things you could do to clean this up. I put everything in the class and called everything as self.something().
I added .lower() for your responses in case a user does OPT1 or Opt1.
I created a single rerun function to call after each operation. It automatically goes to this after the first run.
I also used try/except for your inputs because you will get a ValueError by entering a non-numeric character when calling int(). Instead, it now will tell the user to enter a number and will try again.
For quit, you need to call it as quit().
The init loads as soon as you call the class, which allows you to do things to initiate it, such as including your imports, setting variables, printing messages, and running functions. This way it is all inclusive.
Finally, it is standard practice to begin you class name with a capital letter (though not a requirement).
Hope this helps you get a better idea of how to use classes.
EDIT:
If you want to build a custom import for your tool to use without direct user interaction, you can build it like this:
class Pythag(object):
#custom function for solving for c
def solve_C(a, b):
from math import sqrt
a = int(a)
b = int(b)
c = sqrt(a*a + b*b)
return (c)
#function for solving for a or b, given c
def solveAB(var, c):
from math import sqrt
var = int(var)
c = int(c)
var2 = float(c)**2 - float(var)**2
ans = sqrt(var2)
return(ans)
Then you can import it into another script. If your pythag script is named pythag.py, you would import it as
from pythag import Pythag
Then call the modules like this:
Pythag.solve_C(4,5)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Im new(-ish) to python and I made a game today which after I finished I realised I'd made a big mistake :
inside the functions I had to access and edit variables which where also accessed and changed in other functions and maybe in the future outside the functions. And I don't know how to do that.
I've researched for a long time and found very few things that might solve the problem, I've tried a few, but they haven't worked and I don't understand how to use others.
Could you please try to help me with the problem and if you spot others please tell me, as Im not too good at debugging :(
Here is the code below, its quite big (I've put the variables I need to access and change in bold):
from random import randint
print ("Ghost Game v2.0")
print ("select difficulty")
score = 0
alive = True
difficulty = 0
doors = 0
ghost_door = 0
action = 0
ghost_power = 0
#define the function 'ask_difficulty'
def ask_difficulty() :
difficulty = input ("Hard, Normal, Easy")
set_difficulty()
# define the function 'set_difficulty' which sets the difficulty.
def set_difficulty() :
if difficulty == 'Hard' or 'Normal' or 'Easy' :
if difficulty == 'Hard' :
doors = 2
elif difficulty == 'Normal' :
doors = 3
elif difficulty == 'Easy' :
doors = 5
else:
print ("Invalid input, please type Hard, Normal, or Easy")
ask_difficulty()
# define the function 'ghost_door_choose' which sets the ghost door and the chosen door
def ghost_door_choose(x):
ghost_door = randint (1, x)
print (doors + " doors ahead...")
print ("A ghost behind one.")
print ("Which do you open?")
if doors == 2 :
door = int("Door number 1, or door number 2...")
if 1 or 2 in door :
ghost_or_no()
else :
print ("Invalid input")
ghost_door_choose(difficulty)
elif doors == 3 :
door = int("Door number 1, door number 2, or door number 3")
if 1 or 2 or 3 in door :
ghost_or_no()
else:
print ("Invalid input")
ghost_door_choose(difficulty)
elif doors == 5 :
print("Door number 1, door number 2, door number 3, door number 4, or door number 5.")
if 1 or 2 or 3 or 4 or 5 in door :
ghost_or_no()
else:
print ("Invalid input")
ghost_door_choose(difficulty)
# define the function 'ghost_or_no'
def ghost_or_no() :
if door == ghost_door:
print ("GHOST!!")
print ("Initiating battle...")
battle()
else:
print ("No ghost, you\'ve been lucky, but will luck remain with you...")
score = score + 1
ghost_door_choose(difficulty)
# define the function 'battle' which is the battle program
def battle() :
ghost_power = randint (1, 4) # 1 = Speed, 2 = Strength, 3 = The ghost is not friendly, 4 = The ghost is friendly
print ("You have 3 options")
print ("You can flee, but beware, the ghost may be fast (flee),")
print ("You can battle it, but beware, the ghost might be strong (fight),")
print ("Or you can aproach the ghost and be friendly, but beware, the ghost may not be friendly (aproach)...")
action = input ("What do you choose?")
if flee in action :
action = 1
elif fight in action :
action = 2
elif aproach in action :
action = 3
else :
print ("Invalid input")
battle()
if ghost_power == action :
if action == 1:
print ("Oh no, the ghost\'s power was speed!")
print ("DEFEAT")
print ("You\'r score is " + score)
alive = False
elif action == 2:
print ("Oh no, the ghost\'s power was strength!")
print ("DEFEAT")
print ("You\'r score is " + score)
alive = False
elif action == 3:
print ("Oh no, the ghost wasn\'t friendly ")
alive = False
elif ghost_power == 4 and action == 3 :
print ("Congratulations, The ghost was friendly!")
score = score + 1
ghost_door_choose(difficulty)
elif ghost_power != action and ghost_power != 4 :
if action == 1:
print ("Congratulations, the ghost wasn\'t fast!")
score = score + 1
ghost_door_choose(difficulty)
elif action == 2:
print ("Congratulations, you defeated the ghost!")
score = score +1
ghost_door_choose(difficulty)
elif ghost_power != action and ghost_power == 4 :
if action == 1:
print ("You ran away from a friendly ghost!")
print ("Because you ran away for no reason, your score is now 0")
score = 0
ghost_door_choose(difficulty)
elif action == 1:
print ("You killed a friendly ghost!")
print ("Your score is now 0 because you killed the friendly ghost")
score = 0
ghost_door_choose(difficulty)
#actual game loop
ask_difficulty()
while alive :
ghost_door_choose(doors)
Consider:
x=0
z=22
def func(x,y):
y=22
z+=1
print x,y,z
func('x','y')
When you call func you will get UnboundLocalError: local variable 'z' referenced before assignment
To fix the error in our function, do:
x=0
z=22
def func(x,y):
global z
y=22
z+=1
print x,y,z
The global keyword allows a local reference to a global defined variable to be changed.
Notice too that the local version of x is printed, not the global version. This is what you would expect. The ambiguity is if there is no local version of a value. Python treats globally defined values as read only unless you use the global keyword.
As stated in comments, a class to hold these variables would be better.
Those variables at the top of your script are global and to set them in functions, you have to declare them global in the function. As a smaller example,
score = 0
alive = True
def add_score(value):
"""Add value to score"""
global score
score += value
def kill_kill_kill():
global alive
alive = False
The next step is to create classes, which can get complicated. For instance, if you want to track score by user but a user can have multiple characters which each have their own aliveness, you would start to build classes to represent those things.
The global keyword may be what you are looking for.
For example in the following code.
some_variable = 10
def some_function():
global some_variable
some_variable = 20
This would result in some_variable (in the global scope) referring to the value of 20. Where as it would remain at 10 (in the global scope) without the use of the global keyword.
More on global and local variables here.
A function has its own variable scope - this is true for many languages. This means that once the function finishes executing, the variables cease to exist (and Python's garbage collection will clean them up).
The old-school (and generally frowned upon, not necessarily fairly) way of doing this is to use Global Variables. These are variables you declared outside the scope of the function, usually at the beginning of your source, and can be used throughout your program's various functions and classes.
There are good reasons people don't use global variables much, from performance issues through to getting them confused with locally scoped variables, but they are a quick and easy way to keep information and access it throughout your program.
To use a global, you need to declare within the function that you are using that variable, like this:
MyGlobal="This is a global variable"
def MyFunction():
global MyGlobal
MyGlobal += " and my function has changed it"
if __name__=="__main__":
print MyGlobal
MyFunction()
print MyGlobal
Having said this, the usual way to pass information to and from functions is to use arguments and return values - this is a better design methodology, and the one usually taught. This is more a design method than a change to your code; you write your program with keeping global variables down to an absolute minimum.
To take the above example, this would change our code to the following:
def MyFunction(MyArg):
MyArg+=" and my function has given me a new version of it"
return MyArg
if __name__=="__main__":
MyVariable="This is a variable"
print MyVariable
MyVariable = MyFunction(MyVariable)
print MyVariable
Note that this is much more flexible - I can use it as I have above, to change the value of MyVariable, but I could also use the same function to return the new value to a different variable, keeping the original intact.
I hope this helps, sorry if I was a tad verbose.
I wanted to create a x-y coordinate system even though this is supposed to be a text RPG as to keep track of where everything is. So, I was experimenting on making a function and test for that function that would let the character move on a x-y grid, however, no matter what I try, I cannot make it work. Here is the code:
class Player:
def movement(charactor_movement):
proceed = 0
if charactor_movement == "left":
character.position_x = character.position_x - 1
proceed = 1
elif charactor_movement == "right":
character.position_x = character.position_x + 1
proceed = 1
elif charactor_movement == "forward":
character.position_y = character.position_y + 1
proceed = 1
elif charactor_movement == "backward" or charactor_movement == "back":
character.position_y = character.position_y - 1
proceed = 1
charactor = Player()
charactor.position_x = 0
charactor.position_y = 0
proceed = 0
while proceed == 0:
print "You are at",
print charactor.position_x,
print"x and",
print charactor.position_y,
print"y."
global charactor_movement
charactor_movement = raw_input("Where are you going?")
charactor.movement()
At this point, it does what it is supposed to do up to changing the coordinates, as it prints "You are at 0 x and 0 y" and "Where are you going?" no matter what I type. I have tried adding an else to the function which it defaulted to no matter what I typed and gave me "Sorry, I cannot understand you." Any comments on fixing or generally improving the code would be appreciated.(Note: For the testing I purposely did not add a way to exit. The class is what i need fixed.)
You are getting the same coordinates with each iteration because your values within your while loop are not changing. Incrementing character.position_x within movement will never change the value of character.position_x within your while loop, as it is outside your function's scope. You have to use the global keyword within your movement function for each variable you are changing should you want your current logic to remain the same. Additionally, why not just pass charactor_movement as a parameter to your movement function, as opposed to using global as you currently are doing.
A minimal example:
Consider the following:
def somefunct(x):
mycode = x
mycode = 'no codez'
while True:
print mycode
codez = raw_input('gimme teh codez: ')
somefunct(codez)
which outputs
>>>[evaluate untitled-1.py]
no codez
gimme teh codez: codez!
no codez
Declaring mycode as global in the function places it in the scope of the while loop when assigned, thus
def somefunct(x):
global mycode #make variable global here
mycode = x
mycode = 'no codez'
while True:
print mycode
codez = raw_input('gimme teh codez: ')
somefunct(codez)
results in the output
>>>[evaluate untitled-1.py]
no codez
gimme teh codez: codez!
codez!