Nested while loop, why this loop isnn't looping back to top? - python-3.x

I am trying to create a loop, that will rotate among users and get valid inputs. Inputs are dictionary words checked with external two files one containing allowed words and another restricted. It's a game where users have to say a word that starts with ending letter of their opponents' last word. You get up to 3 passes when you are out of words. When all three passes are takes, you lose the game. I have revised the code many times but it is not looping for some reason:
def game_logic(players_data):
"""takes in players data and initiates the game logic.
:param players_data: contains Player objects with name, word_list and pass_taken as attributes.
:type players_data: list containing dictionaries as items.
"""
# Initialise allowed and prohibited words from external file read.
with open("docs/wordDict.txt", "r") as wordDict:
allowed_words = wordDict.read()
with open("docs/excludeWords.txt", "r") as excludeWords:
prohibited_words = excludeWords.read()
game_switch = True
valid_word = False
player_turn = ""
start_letter = ""
while game_switch:
player_turn = players_data[0].name
if not players_data: # iff empty list
print("Something went wrong. I could not find players! Please restart the game.")
break
elif len(players_data) == 1: # when one person is left
print(f"{players_data[0].name} wins.\nCongratulations!\n°°*°°*°°*°°*°°*°°*° ")
print(f"beat all opponents in: {playtime - datetime.datetime.now()}")
break
else:
print(f"\nIt is {player_turn.upper()}'s turn")
# add a copy of first element to the end
players_data.append(players_data[0])
# remove the first element. so that next turn is next ones'.
players_data.remove(players_data[0])
# start the game
while not valid_word:
if not start_letter:
input_word = input(f"please enter a valid word to begin: ")
if input_word.lower() in allowed_words and input_word.lower() not in prohibited_words:
players_data[-1].word_list.append(input_word)
start_letter = input_word[-1].upper()
print(f"\nStarting letter for next player is: {start_letter}")
valid_word = True
return start_letter
else:
players_data[-1].pass_taken += 1
print(f"FOUL!\nThe word was not recognised as a valid word.\nPenalty: 1 pass({3 - players_data[-1].pass_taken})")
print("Turn goes to your opponent.")
valid_word = False
if players_data[-1].pass_taken >= 3:
print(f"LOST!\n{players_data[-1].name} is out of the game")
players_data.pop()
else:
input_word = input(f"please enter a valid word begining with letter {start_letter}: ")
if input_word.lower() in allowed_words and input_word.lower() not in prohibited_words and input_word[0].upper() == start_letter:
players_data[-1].word_list.append(input_word)
start_letter = input_word[-1].upper()
print(f"\nStarting letter for next player is: {start_letter}")
valid_word = True
return start_letter
else:
players_data[-1].pass_taken += 1
print(f"FOUL!\nThe word was not recognised as a valid word.\nPenalty: 1 pass({3 - players_data[-1].pass_taken})")
print("Turn goes to your opponent.")
valid_word = False
if players_data[-1].pass_taken >= 3:
print(f"LOST!\n{players_data[-1].name} is out of the game")
players_data.pop()
continue
´´´´

As Nico238 said in the comments, you break your loop with return statements inside every if/else statement. As this game relies on a logical progression (Whether a player has entered the correct first letter, and if it's in the dictionary) you need to handle loops carefully, preferably making them as flat (not nested) as possible, and of course not breaking out of them if you need to stay in the game loop.
My suggestion would be to remove those return start_letter statements as you already set it to be something other than empty, and this should continue your loop.

Related

Word "None" on line below input [duplicate]

This question already has answers here:
Why does my input always display none in python? [closed]
(2 answers)
Closed 23 days ago.
I wrote a simple program to track household items and output to a text file, with a while loop to have it keep running till "exit" is entered. I get the word "None" on the line below the input line when I haven't written it to do so. Here is my code.
HouseHoldItems = open('C:\\_PythonClass\\Assignment03\\HouseHoldItemsAndValue.txt', mode='a')
Items = ''
Value = ''
# while loop to keep program running until user enters "Exit"
while(True):
# Items is the primary variable, determines if user is entering new household item or wants to end the program
Items = input(print("Enter an Item (Or type 'Exit' to quit) : "))
# If statement to determine if user wants to end program
if(Items.lower() == "exit"):
break
# Else statement to write household items to the file, followed by value of items
else:
HouseHoldItems.write(Items + ', ')
Value = input(print("Enter an estimated Value: "))
HouseHoldItems.write(Value + '\n')
HouseHoldItems.close()
Here is a snip of the way the code looks as I input data items. (https://i.stack.imgur.com/CHOWk.png)
Is it part of the while(true) piece that is making it do this? Thanks for the help in advance.
You do not need to use the print function when using the input function.
Use:
Items = input("Enter an Item (Or type 'Exit' to quit) : ")
and:
Value = input("Enter an estimated Value: ")
While we're at it, in test conditions for while and if statements while your code works as is, it is not considered 'pythonic'. The pythonic way is to not use parentheses. ie
While True:
and:
if Items.lower() == "exit":

Adding and checking values within a list of tuples

So i am trying to make a menu that will present the user with a function based on their choice, the purpose of the one below is to add words and the description of that word in a list of tuples (criteria of schoolwork) but i feel like i have hit a wall with what i currently have.
##Lägger in nya ord i ordboken
def menu2_val1(lista):
lista_ord = input("Input word ")
##Looping trough the list to look for duplicate words
for dup in lista[0]:
if dup in lista_ord:
print("The word already exists")
return menu2()
else:
lista_definition = input("Input definition ")
lista_ord = (lista_ord, lista_definition)
ny_lista = list(lista)
ny_lista.append(lista_ord)
lista = tuple(ny_lista)
If the word already exists in the list it should inform the user and go back to the menu
def menu2():
programm = 1
lista = [("word", "description")]
while programm > 0:
print("""
1.Insert
2.Lookup
3.Delete Word
4.Exit program
""")
menu2=input("(Tupel Meny)What would you like to do? ")
## Calls on functions based on input
if menu2=="1":
menu2_val1(lista)
elif menu2=="2":
menu2_val2(lista)
elif menu2=="3":
menu2_val3(lista)
Your code has the line for dup in lista[0]:, which will only loop through the first element of lista instead of the whole list.
Try out for dup in lista: instead and see if that helps.
Just for closure i did manage to solve it in the end with the following code
def menu2_val1(lista):
lista_ord = input("Input Word ")
dup = [x[0] for x in lista]
## Storing the first value of each in tuple in dup
if lista_ord in dup:
## Looks for the new word in dup
print("The word already exists")
return
else:
lista_definition = input("Input definition ")
nytt_ord = lista_ord, lista_definition
lista.append (nytt_ord)
Potato's suggestion would end up comparing string values to tuple values which wouldn't work

How to loop through csv and be able to go back a step or proceed line by line?

I'm trying to look up a time for a user. Let's say they input 13(minutes), my code scrolls through the csv and finds each row that has 13 in the time column. It then prints out the row one at a time. I don't know how to allow a user to have the option of revisiting a previous step? My code currently just reverses the order of the csv, starts from the bottom, even if the rows are not the 13 minute- selected rows.
I'm a total newbie so please try to explain as simple as possible.. Thanks
Please see code:
def time():
while True:
find = input("Please enter a time in minutes(rounded)\n"
"> ")
if len(find) < 1:
continue
else:
break
print("Matches will appear below\n"
"If no matches were made\n"
"You will return back to the previous menu.\n"
"")
count = -1
with open("work_log1.csv", 'r') as fp:
reader = csv.DictReader(fp, delimiter=',')
for row in reader:
count+=1
if find == row["time"]:
for key, value in row.items(): # This part iterates through csv dict with no problems
print(key,':',value)
changee = input("make change? ")
if changee == "back": # ISSUE HERE******
for row in reversed(list(reader)): # I'm trying to use this to reverse the order of whats been printed
for key, value in row.items(): # Unfortunately it doesnt start from the last item, it starts from
print(key,':',value) # The bottom of the csv. Once I find out how to iterate through it
# Properly, then I can apply my changes
make_change = input("make change? or go back")
if make_change == 'y':
new_change = input("input new data: ")
fp = pd.read_csv("work_log1.csv")
fp.set_value(count, "time", new_change) # This part makes the changes to the row i'm currently on
fp.to_csv("work_log1.csv", index=False)
print("")
you can always have list that keep last n lines so you can go back using this list, after reading new line just history.pop(0) and 'history.append(last_line)'
or alternatively you can wrap this logic using stream.seek function

Why is my program refrenceing the readline command multiple times and how do I stop it

Okay. So I am trying to make a code which is basically a guess the word game. since it is for a school assignment there are certain required parts such as the used of 4 functions and those functions doing certain things. the program need to pull information off of an words sheet which is stored on an external .txt file. When I try to use a line from said using the readline command it will move to the next line every time I reference the function which leaves me in a pickle.
Here is the code
import random
#Variables
file = open('words.txt','r')
Number_of_lines = 0
Correct = 'Place holder'
Score = 0
#Retrieve the next word through readline command
def get_a_Word():
Basic_Word = file.readline()
Word = Basic_Word
Word = Word
return Word
#Turn the word into a guess word
def guess_Word():
Word = get_a_Word()
Edited_Word = '*' + Word[1:]
return Edited_Word
def check_Word(Word):
if Word == get_a_Word():
return True
else:
return False
#Put that shit together
def Main():
Line = 0
while Line < 10:
Edited_Word = guess_Word()
Score = 0
Line = Line + 1
Word = input('Given {} What is the word? '.format(Edited_Word))
Word = Word.upper()
if check_Word(Word) == True:
print('That is correct!')
Score = Score + 10
elif check_Word(Word) == False:
print('That is incorrect. the word was {}.'.format(get_a_Word()))
else:
print('you broke it')
Correct = Score/10
print('You have successfully guessed {} out of 10 words. Your final score is {}.' .format(Correct, Score))
Main()
file.close()
The .txt File contains these word in this order
Store
Apple
Bicycle
Water
Mercedes
Classroom
Architect
Elevator
Measurement
Godzilla
Any help would be appreciated!
I don't know exactly how the functions you're supposed to have are specified, but the obvious solution to not getting multiple different words is simply not to call get_a_Word more than once per cycle of the main loop. Some of the other functions may need to be changed to take the previously fetched word as an argument.
The loop would look something like this (pseudocode, I may be skipping some things):
while line < 10:
word = get_a_Word()
edited_word = guess_Word(word)
guess = input('Given {} What is the word? '.format(edited_word))
if check_Word(word, guess):
print('That is correct!')
score += 10
else:
print('That is incorrect. The word was {}.'.format(word))
A note on naming, unrelated to your issue: Python convention for naming variables and functions is to use lowercase_names_with_underscores for everything, unless the code is mimicking an existing API that uses a different convention. Use CapitalizedNames for classes, and ALL_CAPS for constants.
The most important thing though, is to to be consistent. Your current code seems to have a mix of underscores, capitalization and other styles without any logic to it. Pick one style (even if it's not the one I described in the previous paragraph) and stick to it. (This can be hard to do if your instructor is inconsistent in naming style. Alas there may not be much you can do about that.)

Expected str instance, int found. How do I change an int to str to make this code work?

I'm trying to write code that analyses a sentence that contains multiple words and no punctuation. I need it to identify individual words in the sentence that is entered and store them in a list. My example sentence is 'ask not what your country can do for you ask what you can do for your country. I then need the original position of the word to be written to a text file. This is my current code with parts taken from other questions I've found but I just can't get it to work
myFile = open("cat2numbers.txt", "wt")
list = [] # An empty list
sentence = "" # Sentence is equal to the sentence that will be entered
print("Writing to the file: ", myFile) # Telling the user what file they will be writing to
sentence = input("Please enter a sentence without punctuation ") # Asking the user to enter a sentenc
sentence = sentence.lower() # Turns everything entered into lower case
words = sentence.split() # Splitting the sentence into single words
positions = [words.index(word) + 1 for word in words]
for i in range(1,9):
s = repr(i)
print("The positions are being written to the file")
d = ', '.join(positions)
myFile.write(positions) # write the places to myFile
myFile.write("\n")
myFile.close() # closes myFile
print("The positions are now in the file")
The error I've been getting is TypeError: sequence item 0: expected str instance, int found. Could someone please help me, it would be much appreciated
The error stems from .join due to the fact you're joining ints on strings.
So the simple fix would be using:
d = ", ".join(map(str, positions))
which maps the str function on all the elements of the positions list and turns them to strings before joining.
That won't solve all your problems, though. You have used a for loop for some reason, in which you .close the file after writing. In consequent iterations you'll get an error for attempting to write to a file that has been closed.
There's other things, list = [] is unnecessary and, using the name list should be avoided; the initialization of sentence is unnecessary too, you don't need to initialize like that. Additionally, if you want to ask for 8 sentences (the for loop), put your loop before doing your work.
All in all, try something like this:
with open("cat2numbers.txt", "wt") as f:
print("Writing to the file: ", myFile) # Telling the user what file they will be writing to
for i in range(9):
sentence = input("Please enter a sentence without punctuation ").lower() # Asking the user to enter a sentenc
words = sentence.split() # Splitting the sentence into single words
positions = [words.index(word) + 1 for word in words]
f.write(", ".join(map(str, positions))) # write the places to myFile
myFile.write("\n")
print("The positions are now in the file")
this uses the with statement which handles closing the file for you, behind the scenes.
As I see it, in the for loop, you try to write into file, than close it, and than WRITE TO THE CLOSED FILE again. Couldn't this be the problem?

Resources