How to check if user has been through a method - python

I am making a simple text-based RPG in Python. Currently I have two methods for most rooms, one for when they first enter and one if they return. Is there a way that I can make sure that they haven't been in that room before without another method?
For example, if I had a method named tomb() i create another method called tombAlready() that contains the same code except for the introduction text to the room.
So if I had
slow_type("\n\nTomb\n\n")
slow_type("There is an altar in the middle of the room, with passages leading down and west.")
choice = None
while choice == None:
userInput = input("\n>")
if checkDirection(userInput) == False:
while checkDirection == False:
userInput = input("\n>")
checkDirection(userInput)
userInput = userInput.lower().strip()
if userInput == "d":
catacombs()
elif userInput == "n":
altar()
elif userInput == "w":
throneroom()
else:
slow_type("You cannot perform this action.")
Then tombAlready() would have the same code except for slow_type("There is an altar in the middle of the room, with passages leading down and west.")

What you want is state associated with a function. Use an object with a method:
class Room:
def __init__(self, description):
self._description = description
self._visited = False
def visit(self):
if not self._visited:
print(self._description)
self._visited = True
Then you can have a Room object for each room:
catacombs = Room('There is a low, arched passageway. You have to stoop.')
tomb = Room('There is an altar in the middle of the room, with passages leading down and west.')
throneroom = Room('There is a large chair. It looks inviting.')
You can visit a room twice but it only prints its description once:
>>> catacombs.visit()
There is a low, arched passageway. You have to stoop.
>>> catacombs.visit()

Related

How do I append user inputs to lists within class instance?

I am new to programming and am trying to create a program that will ask the user questions then store them in an instance to be used for matchmaking but I am having trouble being certain that the inputs are being properly stored. This is what I currently have.
ask_name = input("What is your name? ")
print(f"Hello {ask_name}!")
class Member:
"""A place to store member interest info"""
def __init__(self, book_list, movie_list, game_list):
"""Initialize book, movie, and game interest attributes"""
self.book_list = book_list
self.movie_list = movie_list
self.game_list = game_list
member_0 = Member([''],[''],[''])
active = True
while active:
books = input(f"What are your favorite books? Send one at a time. \n\t Send 'movies' when finished. ")
if books == 'movies':
active = False
else:
answer = input(f" Is {books} one of your favorite books?\n\tSend 'yes' if it is. Send 'no' if it is not. ")
if answer == 'yes':
print(f"{books} has been added to favorite books.")
member_0.book_list.append({books})
print(f"{member_0.book_list}")
active = True
while active:
movies = input(f"What are your favorite movies? Send one at a time.\n\tSend 'games' when finished. ")
if movies == 'games':
active = False
else:
answer = input(f" Is {movies} one of your favorite movies?\n\tSend 'yes' if it is. Send 'no' if it is not. ")
if answer == 'yes':
print(f"{movies} has been added to favorite movies.")
member_0.movie_list.append({movies})
print(f"{member_0.movie_list}")
active = True
while active:
games = input(f"What are your favorite video games? Send one at a time.\n\tSend 'done' when finished. ")
if games == 'done':
active = False
else:
answer = input(f" Is {games} one of your favorite games?\n\tSend 'yes' if it is. Send 'no' if it is not. ")
if answer == 'yes':
print(f"{games} has been added to favorite video games.")
member_0.game_list.append({games})
print(f"{member_0.game_list}")
I'd suggest keeping your lists in a dictionary rather than as three different variables, and writing a function that will let you build any given list, so you don't have to copy+paste all of that code for each one:
class Member:
"""A place to store member interest info"""
def __init__(self, name):
self.name = name
self.favorites = {}
def ask_favorites(self, things, done):
if things not in self.favorites:
self.favorites[things] = []
while True:
print(f"What are your favorite {things}? Send one at a time.")
thing = input(f"\tSend '{done}' when finished. ")
if thing == done:
return
print(f" Is {thing} one of your favorite {things}?")
if input("\tSend 'yes' if it is. Send 'no' if it is not. ") != 'yes':
continue
self.favorites[things].append(thing)
print(f"{thing} has been added to favorite {things}.")
print(self.favorites[things])
def print_favorites(self):
print(f"These are a few of {self.name}'s favorite things:")
for things, faves in self.favorites.items():
print(f"Favorite {things}: {', '.join(faves)}")
ask_name = input("What is your name? ")
print(f"Hello {ask_name}!")
member_0 = Member(ask_name)
member_0.ask_favorites("books", "movies")
member_0.ask_favorites("movies", "games")
member_0.ask_favorites("games", "done")
member_0.print_favorites()

Developing a Turn-Based Battle Game [closed]

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 2 years ago.
Improve this question
I am trying to create a turn based rpg game in python. Currently i am using the list method to display and create individual values for each role. For example, the game allows player to setup a team of units for battle (minimum of 1 unit, default is 3). Each unit has a unique name and attributes like health point (HP), attack point (ATK), defence point (DEF), experience point (EXP) and a rank (default is level 1).
A unit can be either a Warrior, a Tanker or a Wizard whom have different strength in ATK and DEF point. In addition, a Wizard has special ability to cast spells that can impact friendly and enemy units (Heal, Poison, Cure, Freeze).
The suggested initial values for each unit’s attribute point are described in requirement details under Part A – Game Setup section.
The game will automatically setup either (1) player vs Artificial Intelligence (AI) or (2) two-player mode, of which both teams are made up of same number of units.
For AI team, the type of units will be assigned randomly or by specific AI algorithm. The name of units will be specified by the player, whereas AI unit names can be defined with prefix + random numbers (eg AI87). For two-player mode, each player will be able to go through the same unit selection process either through console or GUI.
For each turn, player can select an active friendly unit (non-frozen or dead) to perform an action on a target unit. Units which are severely damaged (i.e. HP equals to or less than 0) will be considered killed (or flagged as “dead”).
How do I use Object Oriented Programming method to create the 3 characters with input name for each team (can display the name keyed and the information of each character), instead of use list method.
#Menu page
print('Welcome to PSB Battle Game! \n(N)ew game\n(S)ave game\n(Q)uit')
def main():
selection = input('Choose your option then hit <ENTER> ==> ')
if selection.upper() == 'N':
new_game()
elif selection.upper() == 'S':
print('Loading save game...')
pass
elif selection.upper() == 'Q':
print('Exit game...')
pass
else:
print("I don't understand what are you typing.")
return main()
def new_game():
print('\nSetting up Player 1 team...\n')
name_list = []
for unit_name in range(1,4):
print(f'Enter a unique name for unit #{unit_name}-> ', end='')
name = input('')
repeated = False
while repeated:
if name == "":
continue
repeated = True
if name in name_list:
print('\nUnit name must be unique.\n')
return new_game()
if not name.strip():
print('\nUnit name could not be blank.\n')
return new_game()
else:
print('Name looks good!')
name_list.append(name)
print(f'Select unit #{unit_name}, type: (W)arrior, (T)anker, or Wi(Z)ard ==> ', end='')
role = input('')
if role.upper() == 'W':
print('Added ' + str(name_list))
warrior()
elif role.upper() == 'T':
print('Added ' + str(name_list))
tanker()
elif role.upper() == 'Z':
print('Added ' + str(name_list))
wizard()
else:
print("I don't understand what are you typing.")
return role()
def warrior ():
charac = [1,50,8,3,0,'True','False','False']
print ('\nWarrior Level 1: ','HP =',charac[1],',''ATK =',charac[2],',''DEF =',charac[3],',''EXP =',charac[4],',''ALIVE =',charac[5],',''POISONED =',charac[6],',''FROZEN =',charac[7])
print ()
def tanker ():
charac = [1,60,5,5,0,'True','False','False']
print ('\nTanker Level 1: ','HP =',charac[1],',''ATK =',charac[2],',''DEF =',charac[3],',''EXP =',charac[4],',''ALIVE =',charac[5],',''POISONED =',charac[6],',''FROZEN =',charac[7])
print ()
def wizard ():
charac = [1,40,3,2,0,'True','False','False']
print ('\nWizard Level 1: ','HP =',charac[1],',''ATK =',charac[2],',''DEF =',charac[3],',''EXP =',charac[4],',''ALIVE =',charac[5],',''POISONED =',charac[6],',''FROZEN =',charac[7])
print ()
main()
Your game is far from functional. I took the liberty of setting up a small sketch of a game after your design with battle functionality and character classes. From this code you can work forward to include other functionalities, such as chance, moving, changing skill points, and other stuff.
class Char:
def __init__(self, name = '', cclass = "Warrior", stats = [1,50,5,5,0,'True','False','False']):
self.c = cclass
self.name = name
self.stats = {'LVL':stats[0],
'HP':stats[1],
'ATK':stats[2],
'DEF':stats[3],
'EXP':stats[4],
'ALIVE':stats[5],
'POISONED':stats[6],
'FROZEN':stats[7]}
self.calc_level()
def __repr__(self):
outs = ''
outs+="Character Name: {0} of class {1}:\n---------------".format(self.name,self.c)
for k,v in self.stats.items():
outs+='\n {0}: {1}'.format(k,v)
return outs
def calc_level(self):
self.stats['LVL'] = int(self.stats['EXP']**.5)+1
def attack(self,other):
print("\n{0} furiously attacks {1} with {2} attack. {1} has {3} defense.".format(self.name,other.name,self.stats['ATK'],other.stats['DEF']))
if self.stats['ATK']>=other.stats['DEF']:
other.stats['HP'] -= self.stats['ATK']
print("\nThat was a hit! The HP of {0} is now {1}".format(other.name,other.stats['HP']))
else:
print("\nYou missed and only made him angrier!")
def new_char(existing):
cc = ''
accept = False
while not accept:
n = input("\nPlease input a new name: ")
accept = True
for c in existing:
if n == c.name:
accept = False
print("This name is taken, already")
while not cc in ['w','t','z']:
cc = input("\nPlease input a class, noble {0}. (W)arrior, (T)ank, Wi(z)ard: ".format(n)).lower()
cclasses = {'w':'Warrior','t':'Tank','z':'Wizard'}
newc = Char(n,cclasses[cc])
print('\nCharacter successfully created:')
print(newc)
return newc
def play(chars):
print("May the games begin. The following characters are present:\n")
for c in chars:
print(c)
print('')
game_over = False
turn = 0
while not game_over:
print("It's the turn of noble {0} {1}. Please select a player to attack:".format(chars[turn].c,chars[turn].name))
possible = []
for i in range(len(chars)):
if not i==turn:
possible.append(i)
print(" - ({0}): {1} named {2}".format(i,chars[i].c,chars[i].name))
sel = -1
while not sel in possible:
s = input('Selection: ')
try:
sel = int(s)
except:
print("That's not a valid choice")
chars[turn].attack(chars[sel])
if chars[sel].stats['HP']<=0:
game_over=True
print("That was it! {0} has died and the game is over.".format(chars[sel].name))
turn +=1
if turn==len(chars):turn=0
def main():
chars = []
entry = ''
print("Welcome to PSB Battle Game!")
while not entry.lower() in ['q','p']:
entry = input('\n(N)ew character\n(P)lay game\n(Q)uit\nSelection: ').lower()
if entry == 'p' and len(chars)<2:
print("\nYou can't play with only one character. Create characters first")
entry = '' ## You can't play with only one char
elif entry == 'n':
chars.append(new_char(chars))
entry = ''
elif entry == 'p':
play(chars)
elif entry == 'q':
print("\nOK, good bye")
main()

How to fix my IF statement so I cant remove and append items from a list

I'm currently writing up a simple program to manage a car yard for a rental company, i've gotten to the end with no real issues until now. To illustrate what I mean i'll posted my code and then my issue.
# class for Car_Yard
class CarYard():
def __init__(self, listOfCars):
self.availableCars = listOfCars
def carYardCarsAvailable(self):
print("Available Cars: ")
for car in self.availableCars:
print(car)
def carYardRentCar(self, rentCar):
if rentCar in self.availableCars:
print("Congratulations on renting your new car, here\'s the keys")
self.availableCars.remove(rentCar)
else:
print("We currently don't have that car in our yard")
def carYardReturnCar(self, rentCarReturn):
self.availableCars.append(rentCarReturn)
print("You have returned the car. Thank You!")
# class for Buyer and his/hers actions
class Buyer():
def buyerRentCar(self):
print("Which car would you like to rent out?" )
self.car = input()
return self.car
def buyerReturnCar(self):
print("Which car would you like to return? ")
self.car = input()
return self.car
# create objects from class and pass a list of cars to the car yard
carYard = CarYard (['Mazda','Holden','Ford','Porsche','Honda','VW','Toyota','Kia'])
buyer = Buyer
# infinite loop
while True:
print()
print("Enter 1 to see our wide range of cars")
print("Enter 2 to rent a car")
print("Enter 3 to return a car")
print("Enter 4 to leave the rental yard")
print()
userInput = int(input())
if userInput is 1:
carYard.carYardCarsAvailable()
elif userInput is 2:
rentCar = buyer.buyerReturnCar
carYard.carYardRentCar(rentCar)
elif userInput is 3:
rentCarReturn = buyer.buyerReturnCar
carYard.carYardReturnCar(rentCarReturn)
elif userInput is 4:
quit()
The issue that i'm having is when I run my code and enter 2 it automatically skips to the line "we currently don't have that car in our yard" and when I enter 3 is says "You have returned the car. Thank you!".
I'm trying to figure out why my code is not called the Buyer class to request for the input. Any suggestions on what I might be missing?
You shouldn't use is like that. The is operator tests whether 2 objects are the same, which is not the same as testing whether their values are equal. What you actually want is an equality test (e.g. userInput == 1).
Anyway, the source of your problem is that you're passing around methods instead of the values that are returned by those methods. For instance this may work better:
buyer = Buyer()
...
elif userInput == 2:
rentCar = buyer.buyerReturnCar()
carYard.carYardRentCar(rentCar)
By passing buyer.buyerRentCar you're passing a method to carYardRentCar, and naturally it's not able to match that method against anything in the list of cars. What you want is to pass a string that is returned by carYardRentCar(). This will cause that method to get invoked, asking the user for input, and then the result of that will get passed along, which is what you want

My display menu repeats multiple times when an input is entered

I'm practice classes and inheritance in a program idea that I came up with myself. Basically Im making an arcade game menu simulator that can play two modes, single player and multiplayer. Every time I enter a choice, either 1 or 2, the menu displays a couple times and then it proceeds to accept the input, I only want the menu to be displayed once. Heres my code:
# Suppose you are at an arcade and you and your friend want to play a multiplayer game that requires UI.
# Make the game ask for the users name and age to see if they can play, make the program so that it can add a friend.
# If any of the players are under the age of 18, they are not allowed to play, otherwise proceed.
# **EXTRA CREDIT** --> Add a functionality which adds the players to a list until the list reaches 4 players, then stop adding to the list.
# arcade_game.py
import sys
# give the user a greeting
import self as self
lst = []
class menu:
def __init__(self, ready):
self.ready = ready
#display menu
#classmethod
def display_menu(self):
print("Pick from one of the choices below, type in the corressponding number")
print("1. single player \n"
"2. Multiplayer")
choice = int(input("Enter your choice here: "))
return choice
# ready or not function to see if the user is ready to play
def ready_or_not(self):
# see if user types 1 or 2 with try & except
try:
# ask user if they are ready
self.ready = int(input("Are you ready to play? Type 1 for yes, 2 for no"))
self.display_menu()
except ValueError:
print("You did not type 1 or 2, please try again!")
# add players class
class player(menu):
# add a default player to __init__(), **(since there has to be at least one player)**
def __init__(self, ready, player1):
super().__init__(ready)
self.player1 = player1
# single player method
def set_name(self):
self.player1 = input("Enter your name for single player mode")
print("Lets play! ", self.player1)
# multiplayer method
def set_names(self):
try:
self.player1 = input("Enter your name to begin")
lst.append(self.player1)
# add another player to continue
while len(lst) <= 4:
add = input("Add player here: ")
lst.append(add)
if len(lst) == 4:
print("Player limit reached!")
break;
except ValueError:
print("You didnt enter valid input, please try again")
# get the names of the players only if 1 is picked from display_menu() above, including player1
def check_choice(self):
if self.display_menu() == 1:
self.set_name()
elif self.display_menu() == 2:
self.set_names()
else:
print("Exiting....")
print("Goodbye!")
sys.exit(0)
m = menu("yes")
m.ready_or_not()
p = player("yes", "test")
p.check_choice()
ready_or_not calls self.display_menu():
def ready_or_not(self):
# see if user types 1 or 2 with try & except
try:
# ask user if they are ready
self.ready = int(input("Are you ready to play? Type 1 for yes, 2 for no"))
self.display_menu()
except ValueError:
print("You did not type 1 or 2, please try again!")
check_choice also calls self.display_menu() at least once, and twice if you type anything other than 1 the first time:
def check_choice(self):
if self.display_menu() == 1:
self.set_name()
elif self.display_menu() == 2:
self.set_names()
else:
print("Exiting....")
print("Goodbye!")
sys.exit(0)
Your top-level code calls ready_or_not() on one menu instance:
m = menu("yes")
m.ready_or_not()
… and check_choice() on another:
p = player("yes", "test")
p.check_choice()
So, your program displays the menu twice, and then a third time if you type anything but 1.
If you don't want the menu displayed two or three times, don't call the method two or three times.
If you want to display the menu only once and remember the choice, instead of displaying it two or three times, you need to use that self.ready attribute that you create in ready_or_not, instead of calling the method again.
However, that still isn't going to work as-is, because your class design is weird. You've made two separate instances, m and p, each of which has its own independent attributes. I'm not sure why player inherits from menu in the first place (or why display_menu is a #classmethod, or why it calls its parameter self rather than cls if it is one, and various other things), but, given that a player is a menu in your design, you probably just want a single player instance, like this:
p = player("yes", "test")
p.ready_or_not()
p.check_choice()
And then, you can change check_choice like this:
def check_choice(self):
if self.choice == 1:
self.set_name()
elif self.choice == 2:
self.set_names()
else:
print("Exiting....")
print("Goodbye!")
sys.exit(0)
Took me a while to figure out, but it seems like when you are done with display_menu() your calling ready_or_not() so you need to remove display_menu() from ready or not like this
# ready or not function to see if the user is ready to play
def ready_or_not(self):
# see if user types 1 or 2 with try & except
try:
# ask user if they are ready
self.ready = int(input("Are you ready to play? Type 1 for yes, 2 for no"))
# self.display_menu()
except ValueError:
print("You did not type 1 or 2, please try again!")
EDIT
looks like im late to the party

How to modify my code so that it'll get the right diagnosis with the minimal number of questions asked?

Below is my complete code with comments describing what each section should operate. In the picture,I have provided it shows how each condition would be verified with depending on the users inputting 'y' for yes and 'n' for no concerning symptoms.
The problem, I'm having is that I should be only asking the minimal question, in order to get the diagnosis of the exact condition without having to answer any other questions.
Ex. Don't have a fever and don't have a stuffy nose: Hypochondriac.
It should print: You are Hypochondriac, just by inputting no for Fever and no for a Stuffy Nose.
I have to go through the entire questionnaire to display the diagnosis but that shouldn't be.
How can i modify my code to only ask the minimal questions required?
![#Description: Creata a medical diagnosis program
#that asks the user whether they have a fever, a rash,
#a stuffy nose and if their ear hurts.
#Get user inputs on whether they have specific conditions
userFever = input("Do you have a fever (y/n): ")
userRash = input("Do you have a rash (y/n): ")
userEar = input("Does your ear hurt (y/n): ")
userNose = input("Do you have a stuffy nose (y/n): ")
#Conditional statements that determine the diagnosis of the user
if userFever == 'n' and userNose == 'n':
print("Diagnosis: You are Hypchondriac")
elif userFever == 'n' and userNose == 'y':
print("Diagnosis: You have a Head Cold")
elif userFever == 'y' and userRash == 'n' and userEar == 'y':
print("Diagnosis: You have an ear infection")
elif userFever == 'y' and userRash == 'n' and userEar == 'n':
print("Diagnosis: You have the flu")
elif userFever == 'y' and userRash == 'y':
print("Diagnosis: You have the measles")][1]
Just construct a hierarchy of questions depending on which one discriminates most. In your case is very easy because the symptoms are totally disjoint. The fever would be the top question: if you don't have fever, you're only interested in knowing if there's stuffy nose or no. If there is, you want to know if there's a rash before asking for the ear. So, I'd start like this:
userFever = input("Do you have a fever (y/n): ")
if userFever == 'n':
userNose = input("Do you have a stuffy nose (y/n): ")
if userNose == 'n':
...
else:
...
else:
# The other questions
Given that this looks like homework, I leave the rest to you :P
Well especially if you want to extend this program I would recommend using something like this:
from itertools import islice
class Diagnosis:
diagnoses = ("You are Hypchondriac", "You have a Head Cold",
"You have an ear infection", "You have the flu", "You have the measles"
)
def __init__(self):
self.diagnosis = 0 # Consider using an enum for this
self.queue = (self.check_fever, self.check_nose, self.check_rash,
self.check_ear)
def ask(self, question):
answer = input(question + " [y/N] ").lower()
return answer != "" and answer[0] == "y"
def make(self):
queue_iter = iter(self.queue)
for func in queue_iter:
skip = func()
# return -1 if you want to break the queue
if skip == -1:
break
if skip > 0:
next(islice(queue_iter, skip, skip + 1))
def check_fever(self):
return 1 if self.ask("Do you have a fever?") else 0
def check_nose(self):
if self.ask("Do you have a stuffy nose?"):
self.diagnosis = 1
return -1
def check_rash(self):
if self.ask("Do you have a rash?"):
self.diagnosis = 4
return -1
return 0
def check_ear(self):
if self.ask("Does your ear hurt?"):
self.diagnosis = 2
else:
self.diagnosis = 3
return -1
def get_result(self):
return self.diagnoses[self.diagnosis]
if __name__ == "__main__":
diagnosis = Diagnosis()
diagnosis.make()
print("Diagnosis: " + diagnosis.get_result())
Basically put all functions you need in the queue and return the number of functions you want to skip or return -1 if you're finished.
This is the old 'Guess who' game - otherwise known as a binary decision tree.
Rather than do your homework here is a different example
male?
/ \
N Y
blonde? beard?
/ \ / \
N Y N Y
Sam Jane hat? Andy
/ \
N Y
Bob Fred
In terms of solving these then an OO approach is almost always best as it is easily understandable and adding extra items easy. Use a recursive method to get the answer...
class Question(object):
no = None
yes = None
def __init__(self, question):
self.question = question
def answer(self):
r = raw_input("%s (y/N): " % self.question).lower()
next = self.yes if r == 'y' else self.no
# check if we need to descend to the next question
if hasattr(next, 'answer'):
return next.answer()
# otherwise just return the answer
return next
# create a bunch of questions
male = Question("Are you male?")
blonde = Question("Are you blonde?")
beard = Question("Do you have a beard?")
hat = Question("Are you wearing a hat?")
# hook up all the questions according to your diagram
male.no = blonde
male.yes = beard
blonde.no = "Sam"
blonde.yes = "Jane"
beard.no = hat
beard.yes = "Andy"
hat.no = "Bob"
hat.yes = "Fred"
# start the whole thing rolling
print "You are %s." % male.answer()

Categories

Resources