Inconsistent Python outcomes - python

So I'm having this problem in which my code is inconsistently failing at random times, this has been answered before:(Python 3.7.3 Inconsistent code for song guessing code, stops working at random times now I have had to add a leaderboard to this song guessing game I am doing. I randomly choose a number of which is used to find the artist and song. If right, it will remove the song and artist to prevent dupes and carry on. Here is the code:
loop = 10
attempts = 0
ArtCount = len(artist)
for x in range (ArtCount):
print(ArtCount)
randNum = int(random.randint(0, ArtCount - 1))
randArt = artist[randNum]
ArtInd = artist.index(randArt)# catches element position
songSel = songs[randNum]
print (randNum)
print ("The artist is " + randArt)
time.sleep(0.5)
songie = songSel
print( "The songs first letter be " + songSel[0])
time.sleep(0.5)
print("")
question = input("What song do you believe it to be? ")
if question == (songSel):
songs.remove(songSel)
artist.remove(randArt)
print ("Correct")
print ("Next Question")
if attempts ==0:
points = points + 5
print("+5 Points")
print("")
if question != (songSel):
loop = loop + 1
attempts = attempts + 1
print("")
print("Wrong,", attempts, "questions wrong, careful!")
print("")
time.sleep(0.5)
if attempts == 5:
break
print("GAME OVER")
Pardon my mess, I'm just starting off in making large code, will clean up when finished. I've had the additional problem of having the count controlled loop as 10 (the amount of questions) then having to go pas the loop when you get a question wrong, I've tried having it loop by the amount of songs in the list and I've also tried making a variable that +1 when you get it wrong so you have space to answer but that doesn't work either. After implementing the leaderboard it now doesn't remove any songs (I was messing with the indentation to make the leaderboard print every time.) The error I randomly get is;
randArt = artist[randNum]
IndexError: list index out of range
I'm never sure why this is the code that is the problem, I'm not even sure if it's necessary.

Please, don't use
randNum = int(random.randint(0, ArtCount - 1))
You may easily get a random artist by using:
randArt = random.choice(artist)

The problem is your code had modify the artist array length when you remove item on true answer. You need to get the right artist count after you change.
for x in range (ArtCount):
print(ArtCount)
count = len(artist) # get the new length here
randNum = int(random.randint(0, count - 1)) # use the new length here instead of your old ArtCount

Related

My code freezes and stops, what's wrong with it?

I'm new to python so don't be surprised it if is something really basic, but i've been trying to write this code that asks math questions and then saves the scores in order to show them again at the start of the loop, but it doesn't save the scores. what should i change?
this is the code
scores = []
names = []
while True:
f = open("highscore.txt", "r")
for line in f:
line = line.strip("\n")
line = line.split(" ")
names.append(line[0])
scores.append(int(line[1]))
print(f.read())
for pos in range(len(names)) :
print(pos + 1, names[pos], scores[pos])
f.close()
score = 0
print("hello, welcome to maths game")
print("\nQuestion 1: what is 2 x 2 x 2?")
answer = int(input("your answer >"))
if answer == 8:
print("correct")
score = score + 1
print("your score is ", score)
else:
print("incorrect")
print("the score is ", score)
print("\nQuestion 2: what is 34 x 2?")
answer = int(input("your answer >"))
if answer == 68:
print("correct")
score = score + 1
print("your score is", score)
else:
print("incorrect")
print("the score is", score)
name = input("what is your name?")
position = 0
for compare_score in scores :
if score < compare_score:
position = position + 1
scores.insert(position, score)
names.insert(position, name)
scores = scores[:5]
names = names[:5]
f = open("highscore.txt", "w")
for pos in range (len(names)):
f.write(names[pos] + " " + scores[pos])
it doesn't give any kind of error message, just loops back and doesn't save the names, neither the scores
You have a for-loop on scores that adds a new item to the scores list at each iteration. The for-loop will never reach the end of the list because there is always 'one more'.
Alain T.'s answer has already stated the root cause that you experienced. The loop never stops which appears to you as "freezing" since there are no outputs or indicators that you (as a user/developer) see that the loop still runs. So actually nothing freezes here .. it just runs forever.
For that reason I wanted to add a short note how to drill down the problem your own the next times..
Keyword here is clearly: debugging.
Debugging means: "finding out what your code does while being executed"
A very simple but (at least for small programs) quite effective approach is using one or more print() statements. These can be used to display the value of variables, the property of an object or just some statement like print("I am before the loop") to know where execution runs/stops..
A possible would be: (look at the print statements)
while True:
print("in while") #<-- this one
...
print("before loop") #<-- this one
for compare_score in scores :
print("in loop") #<-- this one repeats....
if score < compare_score:
position = position + 1
scores.insert(position, score)
names.insert(position, name)
scores = scores[:5]
names = names[:5]
print("After loop") #<-- never see this one
f = open("highscore.txt", "w")
for pos in range (len(names)):
f.write(names[pos] + " " + scores[pos])
Running your program again should print out:
in while
before loop
in loop
in loop
in loop
in loop
in loop
in loop
in loop
...
and so on... So what you know now is:
Everything before the loop at least executed
The loop runs forever .
So now it would be time to dig a little deeper inside the loop.
Most interesting would be to examine the variable on which the loop exit
depends.
In your case that is the length of the scores list:
for compare_score in scores:
So the loop runs until there are no more scores to compare left in the scores list.
So it might be a good idea to print() the length of the list to check if and how it decreases until there are no more scores to compare.
So add something like this:
Check the two print() statements containing len(scores)
for compare_score in scores:
print("in loop")
if score < compare_score:
position = position + 1
scores.insert(position, score)
names.insert(position, name)
scores = scores[:5]
names = names[:5]
print(len(scores)) #<--- this one
# or a bit nicer as f-string:
print(f"len score: {len(scores)}") #<--- this one
print("After loop")
Both are displaying the length of the scores list.
The former one just does it a little nicer.
There is a lot more to debugging. Many tools like VSCode, Pycharm, etc. support a lot more sophisticated methodologies to step through code, set breakpoints, inspect objects and variables ..
But for small ans simple projects and when the focus is on learning, instant feedback and repeating. At least to my mind. Print() debugging gives you a lot of insight in a very easy and simple manner.
Oh, and if you read until here:
"Welcome to the community" Just jokin', welcome !! ;)"

Is there a way to not give a point if they get it wrong the first time, quiz, python

I am new to python and am doing a basic quiz. I'm running into a problem for scoring.
trials = 3
for i in range(trials):
ans_2 = ansTwo()
results.append(ans_2)
if ans_2 in ('c','C'):
print("Good Job",name)
score+=1
break
else:
remaining = trials-i-1
s = '' if remaining == 1 else 's'
print("Oops Try Again? [{0} Chance{1} Remaining]".format(remaining, s))
This is my code and I'm trying to make it that if they do not get the answer the first time they do not get any points, but if they get the answer the first time they get a point.
Just add an if statement before score += 1 that checks if the loop is running for the first time. In your case:
if i == 0:
score += 1

How to get python to go back to start of loop and not use random?

I'm a bit new to python and was giving myself a task, I wanted a number guessing game that gets you to guess four numbers and the program will keep telling you how many numbers you guess right till you guess the full list of numbers.
running = True
import random
def compareLists(a, b):
return list(set(a) & set(b))
def start():
rNums = random.sample(range(10), 4)
gNums = []
print("Get ready to guess 4 numbers!")
for i in range(0, 4):
x = int(input("Guess: "))
gNums.append(x)
print("You guessed: ", gNums)
comparison = len(compareLists(rNums, gNums))
while gNums and rNums:
if gNums != rNums:
print("You guessed " + str(comparison) + " numbers right, keep guessing!")
break
elif gNums == rNums:
print("What amazing luck!")
while running:
start()
The problem is that when I use a break a new list of 4 numbers is created, I want python to just go back to the start of the loop and not make a whole new list!
You want to use continue. Try it with a toy example:
i = 0;
while i < 10:
i += 1
if i % 2 == 0:
continue
print i
Output:
1
3
5
7
9
You can put the
rNums = random.sample(range(10), 4)
outside the loop and pass rNums to start. This way you will have the same four numbers in the list. Hope this helps
For the sake of minimizing the amount of loops going on in your code, I would probably first pop your random numbers in a dictionary.
Something like this (probably more efficient way of doing this...but it's the first thing that popped in my head):
from collections import Counter
d = Counter(random.sample(range(10), 4))
Start your while loop, and keep asking the user to guess. Every time they make a right guess, just perform this operation:
d.pop(correctly_guessed_num)
Once your dictionary is empty, you are done and you break the loop.
EDIT adding my quick stab at the implementation. Not fully thought through, might be some edge cases that break this...but this is the overall idea. Hope it helps.
from collections import Counter
import random
d = Counter(random.sample(range(1, 10), 4))
size = len(d) - 1
while True:
x = int(input("Guess: "))
if size == 0:
print("you guessed them all, way to go")
break
if x not in d:
print("keep going buddy")
continue
else:
d.pop(x)
size -= 1
print("A right guess")

Using classes in a python program and incrementing points

I need to create a final project for a Beginning Python class and I decided to create a riddle program and want to simplify the following code, but am unsure how to do it. I would like to use a class to do this, but I'm having trouble figuring out how to change my main program to use the information from Class The program runs fine without using Class, but I have to use it for the final project. I am unsure how to do this, I've tried a few things like doing a points system (5 points increment for each win) and thought it would be nice to make the riddles/answers etc. into a class. The problem I'm having is how to code the self instances in the program itself. I know to import the class, but I'm struggling with how/what to change in the program without screwing everything up.. I've looked all over Stack Overflow and a variety of other internet resources, and believe I have a decent understanding of classes, importing and inheritance, but I can't seem to find any examples similar to what I'm trying to do.. Any help is greatly appreciated.
import riddle_class
banner = "~Riddle Me This~"
print(banner)
print('')
print('Instructions: You have 10 chances to answer each of the following 5 riddles.\
You will receive 5 points for each riddle you answer – up to 25 points.')
points = {'win': 0}
riddle_one = 'What\'s round, but not always around. It is light sometimes and is dark sometimes. Everyone wants to walk all over me. What am I?'
riddle_two = 'What has roots as nobody sees, Is taller than trees, Up, up it goes, And yet never grows?'
riddle_three = 'Voiceless it cries, Wingless flutters, Toothless bites, Mouthless mutters. What am I?'
riddle_four = 'Tear one off and scratch my head; what was once red is black instead.'
riddle_five = 'We\'re five little items of an everyday sort; you\'ll find us all in a tennis court'
riddle_one_answer = 'moon'
riddle_two_answer = 'mountain'
riddle_three_answer = 'wind'
riddle_four_answer = 'match'
riddle_five_answer = 'vowels'
hidden_one = '-' * len(riddle_one_answer)
hidden_two = '-' * len(riddle_two_answer)
hidden_three = '-' * len(riddle_three_answer)
hidden_four = '-' * len(riddle_four_answer)
hidden_five = '-' * len(riddle_five_answer)
guess_one = 0
guess_two = 0
guess_three = 0
guess_four = 0
guess_five = 0
points = 0
score = {'win':0}
print('')
#Riddle One
print('~Riddle Number One!~')
print(riddle_one)
print('')
while guess_one < 11:
print(hidden_one)
user_input = input('Enter one letter at a time (guess #%d): ' % guess_one)
if len(user_input) != 1:
continue
# Count the number of times the character occurs in the word
num_occurrences = riddle_one_answer.count(user_input)
# Replace the appropriate position(s) in hidden_word with the actual character.
position = -1
for occurrence in range(num_occurrences):
position = riddle_one_answer.find(user_input, position+1) # Find the position of the next occurrence
hidden_one = hidden_one[:position] + user_input + hidden_one[position+1:] # Rebuild the hidden word string
if not '-' in hidden_one:
print('')
print('Nice Job!', end=' ')
results = 'win'
break
guess_one += 1
else:
print('Loser!', end=' ')
print('The word was %s' % riddle_one_answer,'\.')
print('______________________________________')
print('')
#Riddle Two
print('')
print('~Riddle Number Two!~')
print(riddle_two)
print('')
while guess_two < 11:
print(hidden_two)
user_input = input('Enter one letter at a time (guess #%d): ' % guess_two)
if len(user_input) != 1:
continue
# Count the number of times the character occurs in the word
num_occurrences = riddle_two_answer.count(user_input)
# Replace the hidden_word with the character.
position = -1
for occurrence in range(num_occurrences):
position = riddle_two_answer.find(user_input, position+1) # Find the position of the next occurrence
hidden_two = hidden_two[:position] + user_input + hidden_two[position+1:] # Rebuild the hidden word string
if not '-' in hidden_two:
print('')
print('WINNER!', end=' ')
results = 'win'
break
guess_two += 1
else:
print('Loser!', end=' ')
print('The word was: %s' % riddle_two_answer,'\.')
print('______________________________________')
print('')
#Riddle Three
print('')
print('~Riddle Number Three!~')
print(riddle_three)
print('')
while guess_three < 11:
print(hidden_three)
user_input = input('Enter one letter at a time (guess #%d): ' % guess_three)
if len(user_input) != 1:
continue
# Count the number of times the character occurs in the word
num_occurrences = riddle_three_answer.count(user_input)
# Replace the appropriate position(s) in hidden_word with the actual character.
position = -1
for occurrence in range(num_occurrences):
position = riddle_three_answer.find(user_input, position+1) # Find the position of the next occurrence
hidden_three = hidden_three[:position] + user_input + hidden_three[position+1:] # Rebuild the hidden word string
if not '-' in hidden_three:
print('')
print('WINNER!', end=' ')
results = 'win'
break
guess_three += 1
else:
print('Loser!', end=' ')
print('The word was %s' % riddle_three_answer,'/.')
print('______________________________________')
print('')
#Riddle Four
print('')
print('~Riddle Number Four!~')
print(riddle_four)
print('')
while guess_four < 11:
print(hidden_four)
user_input = input('Enter one letter at a time (guess #%d): ' % guess_four)
if len(user_input) != 1:
continue
# Count the number of times the character occurs in the word
num_occurrences = riddle_four_answer.count(user_input)
# Replace the appropriate position(s) in hidden_word with the actual character.
position = -1
for occurrence in range(num_occurrences):
position = riddle_four_answer.find(user_input, position+1) # Find the position of the next occurrence
hidden_four = hidden_four[:position] + user_input + hidden_four[position+1:] # Rebuild the hidden word string
if not '-' in hidden_four:
print('')
print('WINNER!', end=' ')
results = 'win'
break
guess_four += 1
else:
print('Loser!', end=' ')
print('The word was %s' % riddle_four_answer,'/.')
print('______________________________________')
print('')
#Riddle Five
print('')
print('~Riddle Number Five!~')
print(riddle_five)
print('')
while guess_five < 11:
print(hidden_five)
user_input = input('Enter one letter at a time (guess #%d): ' % guess_five)
if len(user_input) != 1:
continue
# Count the number of times the character occurs in the word
num_occurrences = riddle_five_answer.count(user_input)
# Replace the appropriate position(s) in hidden_word with the actual character.
position = -1
for occurrence in range(num_occurrences):
position = riddle_five_answer.find(user_input, position+1) # Find the position of the next occurrence
hidden_five = hidden_five[:position] + user_input + hidden_five[position+1:] # Rebuild the hidden word string
if not '-' in hidden_five:
print('')
print('WINNER!', end=' ')
results = 'win'
break
guess_five += 1
else:
print('Loser!', end=' ')
print('The word was %s' % riddle_five_answer,'/.')
print('______________________________________')
print('')
if results == 'win':
score['win'] += 1
total_wins = (score['win'])
points += 5 * total_wins
print('Total points: %d' % points) *#This is only recognizing 1 'win'*
Class
class riddle_me:
def __init__(self, turns, guess):
self.turns = 5
guess = 0
score = {'wins': 0}
def __init__(self):
guess_one = 0
guess_two = 0
guess_three = 0
guess_four = 0
guess_five = 0
UPDATE
Thank you all for your help and questions. Even the questions got me thinking more about my project. I still haven't completed the program yet, but I know it could work. I just need to practice more. I've been studying nonstop, but for some reason I'm struggling to learn this language no matter how many tutorials I search.
I'm assuming you understand what a class is, right? So your question really is, "how should I use classes in this program?"
Usually the best way to figure out what classes (and objects) you need in a program is to sit down and write out a description of what your program is trying to do, and then pick out words from that. For example:
This riddle game will ask the user a series of questions, and each time compare the user's guess with the correct answer. When the user guesses correctly, the user's points will increase. If the user does not guess correctly after 10 guesses, we will move to the next question. After all the questions have been asked, the game will display the user's points.
OK, so this is still pretty straightforward. I've highlighted some of the words that occur more than once. Each of these words represents an idea that might be usefully made into a class: the game itself, each question, the user's guess.
Some of these things don't need to be their own objects, but can be properties of other objects. For example, notice how we kept referring to "the user's points". Clearly the points number is an attribute of the user object. And the correct answer to a question should be an attribute of that question.
OK, so now we have some "things" we're going to use in our program, and some idea of what we want to know about each of them:
User:
has points (a number)
Question:
has question text (a string)
has correct answer (a string)
Guess:
has the text of the guess, what the user entered (a string)
is either right or wrong (a boolean)
Game:
has 5 questions
OK, these are starting to look like classes! We can translate these into classes pretty directly:
class User:
def __init__(self):
self.points = 0 # user starts out with zero points
class Question:
def __init__(self, question_text, correct_answer):
self.question_text = question_text
self.correct_answer = correct_answer
class Guess:
def __init__(self, text, is_correct):
self.text = text
self.is_correct = is_correct
class Game:
def __init__(self, questions):
self.questions = questions
Now we have some objects, but we can't do anything useful with them. Now we need to decide what methods to add. There's more than one right way to do this (and a lot of subtle tradeoffs, depending on which things you care more or less about).
Let's start, though, by identifying things we want to be able to do:
ask a Question, that is, print out its question_text
read in a Guess from the user
determine whether a Guess matches a Question's correct_answer text
add points to a User
find the next Question in a Game, or determine when there are no more questions
Each of these things we want to do should be a method! Now you're breaking down your program into smaller and smaller pieces. Keep doing it until it becomes obvious what each piece should do -- and then translate each piece into code. That's it!
Some of these things could potentially live in multiple places. Some things to think about:
Should reading in a Guess from the user be a method on Guess or on User? Either one is OK. Or it could even be a separate function (not a method of a class).
Where should the function that determines whether a Guess is correct or not live? Right now I have it as an attribute of the Guess class, but maybe it should be a method on Guess like is_correct_answer_to(question) that takes the question and returns True or False.
Where should we keep track of the number of guesses so far for a particular question? It could either be on the Question object, or on the User object. Or it could just be a local variable in a function like ask_question(question) which could live either on Question or maybe on Game, or maybe not as a member of a class.
These are the decisions you need to make. But hopefully this will help you get started!
I think there are two possible places to put a class into your code. One is urgently needed, the other not so much (but it could come in handy if you want to add new features to the program).
The obvious place to use a class is to encapsulate all the data and logic related to a single riddle. Each instance of the class would have attributes for the question, the answer, and perhaps other things that would be modified as the player tries to solve the riddle (the masked solution shown to the player and a list of the guesses so far, perhaps).
Something like this:
class Riddle(object):
def __init__(self, question, answer):
self.question = question
self.answer = answer
self.guesses = []
self.update_mask()
def update_mask(self):
self.masked_answer = "".join(c if c in self.guesses else "-"
for c in self.answer)
def guess(self, letter):
# perhaps do some sanity checking here, for invalid or duplicated letters
self.guesses.append(letter)
self.update_mask()
# return number of letters just matched, number yet to be guessed
return self.answer.count(letter), self.masked_answer.count("-")
The other place you might use a class is to encapsulate the game logic (e.g. how many guesses the user gets to make, how they score points) and state (e.g. the player's score and the list of Riddles to ask). This would let you adapt your program in various ways, like letting the player play again after they complete the first run.
However, I don't think that using a class for this is nearly as important as it was for the riddles. Most of the benefits would simply come from gathering the game logic into functions, rather than repeating it over and over. Make an ask_riddle function to handle a single riddle and return the score the player earned and your code will get a whole lot cleaner. If you want to make it a method of the Game class, and update the instance with the score instead, that works too. Python doesn't require you to write object oriented code (though it does make it easy to do so), so you don't need to wedge classes in where they're not needed.

Need help using the random.randint command making a word guessing game

I have been set some homework to make a word guessing game, I have got it to work for the most part but at this point I am using random.choice and that command allows the same string to repeat more than once. I need to know how to use random.randint in this instance.
""" This is a guessing game which allows the person operating the program to
guess what i want for christmas"""
import random
sw = ("Trainers")
print ("In this game you will have 10 chances to guess what I want for christmas, you start with 10 points, each time you guess incorrectly you will be deducted one point. Each time you guess incorrectly you will be given another clue.")
clue_list = ["They are an item of clothing", "The item comes in pairs", "The Item is worn whilst playing sport", "The item is an inanimate object", "The item can be made of leather","They come in differant sizes", "They have laces", "can be all differant colours", "the item has soles", "Im getting it for christmas ;)"]
def guessing_game(sw, clue_list):
x = 10
while x<=10 and x > 0:
answer = input("What do I want for christmas?")
if sw.lower() == answer and answer.isalpha():
print ("Good Guess thats what I want for christmas")
print ("You scored %s points" % (x))
break
else:
print ("incorrect, " + random.choice(clue_list))
x -=1
if x == 0:
print ("You lost, try again")
guessing_game(sw, clue_list)
for your implementation I think you want:
clueint = random.randint(0, len(clue_list))
print("incorrect, " + clue_list[clueint])
to ensure the same clues are not displayed twice declare an empty list to store guess in OUTSIDE the function definition:
clues_shown = []
and then add each int to the list:
def showClue():
clueint = random.randint(0, len(clue_list))
if clueint in clues_shown:
showClue()
else:
clues_shown.append(clueint)
print("incorrect, " + clue_list[clueint])

Categories

Resources