I am trying to use a for loop in a dictionary to represent an unknown about of statements that may need to be in the dictionary (based on the specified amount when stating the class). I was wondering what the syntax for that would be if there is any at all.
Earlier today a friend asked me to make a Choose Your Own Adventure game.
I wanted to have a random page be the death page.
The rest of the pages are story/question pages.
I also wanted to have a dictionary that when I put in a page number
it returned the type of page it was.
I was trying to use a for statement to get a page number that is
called with the class. The pages are random so there is no way for me
to know.
from time import sleep
from random import randint
def ClearSys():
for i in range(0,100):
print("\n")
class Book:
def __init__(self,name,pages):
#self.DeathPage#
RandomPage=randint(2,pages)
self.DeathPage=RandomPage
del RandomPage
#self.pages#
self.pages=["Introduction Page"]
for i in range(2,pages):
if not i==self.DeathPage:
self.pages.append("QuestionPage")
else:
self.pages.append("DeathPage")
####MAIN SECTION I WOULD LIKE TO HIGHLIGHT####
##Page number dictionary##
self.PageNumberToType={
0:"Introduction Page",
for i in range(1,len(self.pages)):
i:self.pages[i]
}
########
I didn't really expect this to work, but I just wrote it out to see if it were possible.
None that I know of; but why does it need to be inside the dictionary literal?
self.PageNumberToType = { 0:"Introduction Page" }
for i in range(1, len(self.pages)):
self.PageNumberToType[i] = self.pages[i]
Because order is of little importance when it comes to dictionaries, you can do a dictionary-comprehension as well:
self.PageNumberToType = {i: self.pages[i]
for i in range(1, len(self.pages[i]))}
self.PageNumberToType.update({0: 'Introduction Page'})
Related
I am very new to python, and am running into an issue I don't fully understand. I am trying to get a random variable to run multiple times, but for some reason it just returns the same random value x times.
I am not entirely certain what to try aside from the code I have already done.
lowTreasureList = "50 gold", "Healing Potion", "10x Magic Arrows", "+1 Magic Weapon"
def ranLowLoot(lowLootGiven):
# This function returns a random string from the passed list of strings.
lootIndex = random.randint(0, len(lowLootGiven) - 1)
return lowLootGiven[lootIndex]
lowLoot = ranLowLoot(lowTreasureList)
treasureSelection = int(input())
if treasureSelection == 1:
numLowTreasure = int(input('How many treasures? '))
for i in range(numLowTreasure):
ranLowLoot(lowTreasureList)
print(lowLoot)
When I do this I get the same random treasure (numLowTreasure) times, but I am trying to get it to select a new random treasure each time.
If you haven't already, it will help to read the documentation on the random module.
There are three alternatives to random.randint that are more suited to your purpose:
random.randrange(start, stop, [step]): step is optional and defaults to one. This will save you the len(...) - 1 you are using to get lootIndex, since stop is an exclusive bound.
random.randrange(stop): uses a default start of zero and default step of 1, which will save you passing 0 as your start index.
random.choice(seq): you can pass your function's parameter lowLootGiven to this as seq, which will save you from using indices and writing your own function entirely.
As for why you're getting the repeated treasure, that's because you aren't updating your variable lowLoot in your for loop. You should write:
for i in range(numLowTreasure):
lowLoot = ranLowLoot(lowTreasureList)
print(lowLoot)
Last thing I want to say is that python is nice for writing simple things quickly. Even if there was some bigger context that you were writing this code in, I might have written it like this:
lowTreasureList = ("50 gold", "Healing Potion", "10x Magic Arrows", "+1 Magic Weapon")
if int(input()) == 1:
for i in range(int(input('How many treasures? '))):
print(random.choice(lowTreasureList))
Using the round parentheses around the tuple declaration like I did isn't necessary in this case, but I like to use it because if you want to make the tuple declaration span multiple lines, it won't work without them.
Reading documentation on standard libraries is something I almost always find helpful. I think Python's documentation is great, and if it's bit too much to digest early on, I found tutorialspoint to be a good place to start.
The problem is that in the main loop you are discarding the result of the call to ranLowLoot(). As a minimal fix, in the main loop assign the result of that function call. Use:
lowLoot = ranLowLoot(lowTreasureList)
rather than simply:
ranLowLoot(lowTreasureList)
As a better fix, ditch your function completely and just use random.choice() (which does what you are trying to do, with much less fuss):
import random
lowTreasureList = ["50 gold", "Healing Potion", "10x Magic Arrows", "+1 Magic Weapon"]
treasureSelection = int(input())
if treasureSelection == 1:
numLowTreasure = int(input('How many treasures? '))
for i in range(numLowTreasure):
lowLoot = random.choice(lowTreasureList)
print(lowLoot)
for an assignment we needed to make a function that flipped a coin and another to flip it 100 times. I was able to make a function that flipped a coin, but got stuck when trying to call it a 100 times with another function. This is what I have right now:
import random
def TC():
face = random.randint(0,1)
if face == 1:
return "head"
else:
return "tail"
print TC()
def ply(flips):
for i in range(flips):
return TC()
print ply(100)
When I run it it just says 'none.' Please tell me where I am going wrong. Thank You!
Just to start, your method naming is very bad. I doubt this is how your professor is teaching you to name methods and variables. It's ugly, against Python standards and hard to read I suggest you take some time and read PEP 8 it's how python was intended to be written.
So instead of TC you should use something like flip_coin and instead of ply use something like play_coin_flip or even simply play.
Next I don't know if I'm stepping outside of what you have learned but instead of using randon.randint you can use randon.choice.
And finally, as others have said, when you return you quit any other execution in a function and return whatever variable you retrun in that statement thus nullifying any other iterations of the loop you're performing. I suggest something like the below as a better program with corrections applied to make it function as intended.
from random import choice
faces = ['head', 'tail']
def flip_coin():
face = choice(faces)
return face
def play_coin_flip(flips = 1):
for i in range(flips):
print(flip_coin)
if __name__ == "__main__":
play_coin_flip(100)
I'm making a subclass for multiple choice questions under a superclass of trivia questions for my Python university course. The multiple choice aspect works, but I want to shuffle the order of the answers for extra credit.
Some of my code:
class ChoiceQuestion(Question) :
def __init__(self) :
super().__init__()
self._choices = []
def addChoice(self, choice, correct) :
self._choices.append(choice)
if correct :
# Convert len(choices) to string.
choiceString = str(len(self._choices))
self.setAnswer(choiceString)
# Override Question.display().
def display(self) :
# Display the question text.
super().display()
# Display the answer choices.
for i in range(len(self._choices)) :
choiceNumber = i + 1
print("%d: %s" % (choiceNumber, self._choices[i]))
The question choices are added in a seperate file I have no control over as a test-file. This is run by the professor after turning in whatever variation of the first code. Here is what he runs it on. Side note: there are of course import statements in the second file, but I have the other stuff solved and it's very long. Didn't want to include stuff that has been worked out.
print('\n')
mcq = ChoiceQuestion()
mcq.setText("In which country was the inventor of Python born?")
mcq.addChoice("Australia", False)
mcq.addChoice("Canada", False)
mcq.addChoice("Netherlands", True)
mcq.addChoice("United States", False)
for i in range(3) :
presentQuestion(mcq)
## Presents a question to the user and checks the response.
# #param q the question
#
def presentQuestion(q) :
q.display() # Uses dynamic method lookup.
response = input("Your answer: ")
if q.checkAnswer(response):
print("Correct")
else:
print("Incorrect") # checkAnswer uses dynamic method lookup.
# Start the program.
With that said, I need to display the options in a random order, while updating the number value tied to that choice slot. I.e. if Netherlands is randomized into slot 1, typing "1" will print "Correct". I also have to make sure I don't allow the same option to appear more than once.
How should I go about it? What are some suggestions? Note: I can only modify the first program
Here are a couple of things to think about:
As kiran.koduru mentioned, look at using the random module for easily shuffling lists.
Currently your code stores the correct answer as it is received. This makes it difficult because when the answers are shuffled the stored answer is no longer correct. An alternative is to store choice and correct together and calculate the correct answer after your choices are shuffled.
Your code does not know in addChoice whether or not there will be more choices added, so shuffling there will result in wasted computation.
I'm coding a text game in python 3.4 and when I though about making a save game came the question:
How can I jump to the place that the player stopped?
I'm making a simple game, me and my friends, so I just wanna jump to a certain part of the code, and I can't do that without having to make around 15 copies of the code, so can I jump to a line?
You can do that using something like python-goto but this is a very bad idea.
In python, you don't have really any reason to do a goto.
A way better way would be to save the structure containing your data with something like pickle and loading it back when the user want to restart the game.
For instance:
import pickle
game_data = {'something': [1, 2, 3 ]}
pickle.dump(game_data, open('file.bin', 'wb')
Then, you can load the data back:
import pickle
game_data = pickle.load(open('file.bin', 'rb'))
There is no goto built into Python. There are ways to effectively 'halt' in a method by using yield and creating a generator, which is effectively how Python coroutines work (see the asyncio module) however this isn't really appropriate for your needs.
For saving game state, saving and serialising the state you need to resume the gameplay in a more general way is a much better idea. You could use pickle For this serialisation.
You need to consider the game-state as something that you can assign a value (or values) to. If this is a very simple text game, then the player will have a location, and that location will presumably be something you can "jump" to via use of a reference.
Let's say your code follows this pseudo-code pattern:
start
player_location = 0
print_start_game_text()
begin loop:
display_text_for_location[player_location]
display_options_for_location[player_location]
player_location = parse_player_response(response_options_for_location[player_location])
if isGameEndCondition(player_location):
break;
print_end_game_text()
end
This pattern would reference some data files that, for each location provided some collection such as 1, "you are in a room, doors are [E]ast and [W]est. You can [S]ave your game, or [L]oad a previously saved one", { "E" : 3, "W" : 2, "S" : "savegame", "L" : "loadgame" }
Then using a function to display some options, collecting the users response and parsing that data, returning a single value; the next location. You then have a new key to reference the next element in the data-file.
IF your game is as simple as this, then your save file need only contain a single reference, the player's location! Simple.
If you have objects that the player can manipulate, then you'll need to figure out a way to keep track of those, their locations, or state-values - it all depends on what your game does, and how it's played.
You should be thinking along these program vs data lines though, as it will make the game much easier to design, and later, extend, since all you'd have to do to create a new adventure, or level, is provide a new datafile.
I'll try to simplify my problem. I'm writing a test program using py.test and appium. Now:
In the application I have 4 media formats: Video, Audio, Image and Document.
I have a control interface with previous, next, play , stop buttons.
Each media formats has a unique ID like
video_playbutton, audio_playbutton, document_playbutton, image_playbutton, video_stopbutton audio_stopbutton ...etc etc.
But the operation I have to do is the same for all of them e.g press on playbutton.
I can address playbutton of each when i give them explicitly like this
find_element_by_id("video_playbutton")
And when i want to press on other playbuttons I've to repeat above line each time. Like this:
find_element_by_id("video_playbutton")
find_element_by_id("audio_playbutton")
find_element_by_id("image_playbutton")
find_element_by_id("document_playbutton")
And because I'm calling this function from another script I would have to distinguish first what string I got e.g:
def play(mediatype):
if mediatype == "video"
el = find_element_by_id("video_playbutton")
el.click()
if mediatype == "audio"
el = find_element_by_id("audio_playbutton")
el.click()
if .....
What is the best way to solve this situation? I want to avoid hundreds of if-statements because there is also stop, next , previous etc buttons.
I'm rather searching for something like this
def play(mediatype)
find_element_by_id(mediatype.playbutton)
You can separate out the selectors and operations in two dictionaries which scales better. Otherwise the mapping eventually gets huge. Here is the example.
dictMedia = {'video':['video_playbutton', 'video_stopbutton','video_nextbutton'], 'audio':['audio_playbutton', 'audio_stopbutton', 'audio_nextbutton']}
dictOperations = {'play':0, 'stop':1, 'next':2}
def get_selector(mediatype, operation):
return dictMedia[mediatype][dictOperations[operation]]
print get_selector('video', 'play')
PS: The above operation doesn't check for key not found errors.
However, I still feel, if the media specific operations grow, then a page object model would be better.