list index out of range.split on input? - python-3.x

i'm running into "out of range" while hitting enter and imputing single words. I understand why they are out of range, i just can't find how to fix the issue. this is my code:
commands = {
'help': help,
'exit': exit,
'look': look,
'stats': thePlayer.printStats,
's':thePlayer.move_South}
def runCmd(cmd, args, player):
commands[cmd](args, player)
def help(args):
print(commands)
def play():
main1()
World.loadTiles()
#These lines load the starting room and display the text
room = World.tileExists(player.locationX, player.locationY)
print(room.introText())
while player.isAlive():
room = World.tileExists(player.locationX, player.locationY)
room.modifyPlayer(player)
# Check again since the room could have changed the player's state
if player.isAlive():
print("\nHp:%d\%d Mp:%d\%d\n"%(player.hp,player.maxHp,player.mp,player.maxMp))
print(room.printEnemy())
availableActions = room.availableActions()
for action in availableActions:
print(action)
actionInput = input('Action: ')
action = actionInput.lower()
action = action.split()
print(action)
if action[0] in commands:
runCmd(action[0],action[1], player)
i realize i'm not passing an "action[1]" and that just hitting enter isn't in "commands" causing my error. i'm new to coding so creating a game is how i'm teaching myself.
i'm trying to get to where i can type: enter, single word (help, stats), double words (look rat), other things with more words ( buy big sword) and so on. any help on how i can code this correctly?

How about testing
len(action)
before calling runCmd? Thus, you can know if there are one word, two words, or more than two words.
If there is only one word, you can call:
runCmd(action[0], None, player)
If there are two words, you can call your current function. If there are more than two words, it's a bit tricky. You can pass the whole action variable. Then, the called function has to know how many parameters it needs.

Related

How To Print Strings From Python App to a Browser Text-Field within a Flash Game

I want this small python program to be able to output strings into a text-field within a flash game on Google Chrome. The key press emulations work, however the print function obviously only returns the printed code to console.
I tried a few workarounds using a for loop to push the string values into a .press and .release functions, but (not only is this not optimal code) it (as far as I could tell) can't be done.
def click():
username=textentry.get()
time.sleep(2)
for i in range(1000):
print(username)
keyboard.press(Key.tab)
keyboard.release(Key.tab)
print(f'{i:03}')
keyboard.press(Key.enter)
keyboard.release(Key.enter)
keyboard.press(Key.shift)
keyboard.press(Key.tab)
keyboard.release(Key.tab)
keyboard.release(Key.shift)
Prints fine to console, and the key presses and releases are working. Only issue is that text doesn't get sent to anything outside the console.
My ideal situation is that you can simply start the program and then click into the text-fields (one for username, the other for the 3-code integer) and it will do the rest for you, running through username-associated 000 ints until it gets the friend code.
This program IS not (and couldn't) guess somebody's password. It's for a harmless flash game called stick empires.
The question seems unsolvable (I could be wrong, but after researching for hours and hours the reoccurring answer is that it can't be done.) But here's a semi-work around:
If you use pynputs .type("") function, you can essentially queue up key presses in your operating system as though you yourself were typing a string out. To do this as I requested above, with the first textfield needing a username to be entered, and the second textfield needing a 3 digit integer (iterating up from 000 to 999 for all possibilities) I had to use two for-loops and call a bunch of functions. It looks pretty ugly but it is functional.
#Click function to run inputs
def click():
t = 0; j = 0
lst = []
keyboard = Controller()
username = textentry.get()
a = len(username)
time.sleep(2)
for i in range(1000):
for j in range(a):
keyboard.press(username[j])
keyboard.release(username[j])
j += 1
keyboard.press(Key.tab)
keyboard.release(Key.tab)
lst.append(f'{i:03}')
keyboard.type(lst[i])
keyboard.press(Key.enter)
keyboard.release(Key.enter)
keyboard.press(Key.shift)
keyboard.press(Key.tab)
time.sleep(0.02)
keyboard.release(Key.tab)
keyboard.release(Key.shift)
i += 1
j = 0

How to get Python 3 to register a random word from a external file as a variable

I'm a computer science student at secondary school currently struggling with a certain aspect of my NEA, we are permitted to get help with the code. The aim of the NEA is to create a game which can choose a random song and artist from an external file and then get the user to guess which song it is. The issue I have run into is when I run the program the random aspect of the code (The Song name and artist chosen from the external file) does not seem to be registered by the if statement. I cannot think of a better way to explain my issue, but if you run the code I believe you will see the issue I'm having. I have taken out most of the excess code that is not part of the problem to make it easier to understand because like I said before I am still a novice at this. I have looked around for a while now and cannot seem to find an answer. Any sort of help would be very much appreciated.
username = 'Player1'
password = 'Password'
userInput = input("What is your username? (Case Sensitive)\n")
if userInput == username:
userInput = input("What Is Your Password? (Case Sensitive)\n")
if userInput == password:
print(
"Welcome! In this game you need to guess each songs name after being given its first letter and its artist. Good luck!"
)
else:
print("That is the wrong password. Goodbye ;)")
exit()
else:
print("That is the wrong username. Goodbye ;)")
exit()
startgame = 'Start' 'start'
userInput1 = input("Click Any Button And Click Enter To Begin Game:")
if userInput1 == startgame: 'Start'
print("Welcome To The Game")
import random
Song = [line.strip() for line in open("Songnames.txt")] #Currently in the external file I have removed all of the other songs apart from H______ By Ed Sherran.
print(random.choice(Song))
userguess = input("Whats Your Answer?\n")
if userguess == ("Happier") and (random.choice(Song)) == "H______ By Ed Sherran": #The program will continue to return 'Incorrect'.
print("Nice One")
else:
print ("Incorrect")
Any sort of help would be very much appreciated , I have looked for a while on this site and others for an answer however if it seems I have missed an obvious answer I do apologise.
When I run the code it seems to work. (My Songnames.txt contains one line, H______ By Ed Sherran.)
Is it possible that your Songnames.txt contains at least one empty line? If so, filtering the empty lines might fix the problem:
Song = [line.strip() for line in open("Songnames.txt") if line.strip()]
A few other suggestions for your code:
startgame = 'Start' 'start'
userInput1 = input("Click Any Button And Click Enter To Begin Game:")
if userInput1 == startgame: 'Start'
print("Welcome To The Game")
This doesn't make sense. Besides the misleading prompt about buttons and clicks, the if userInput1 == startgame: 'Start' doesn't do anything, not even print start. And the game starts regardless of what the user enters.
The actual game has a few issues as well, most importantly for when you actually have multiple songs is the fact that you choose a random song twice. Given enough songs, these will almost always be two different songs, so the print will be utterly misleading. Better choose one song and assign it to a variable:
import random
songs = [line.strip() for line in open("Songnames.txt") if line.strip()]
computer_choice = random.choice(songs)
print(computer_choice)
userguess = input("Whats Your Answer?\n")
if userguess.lower() == computer_choice.lower():
print("Nice One")
else:
print("Incorrect")
I took the liberty to make the comparison case insensitive by comparing the lowercase versions of the user guess and the computer's choice.

I am having trouble understanding the flow of programming

I am new to programming and one of the problems I have run across is structuring. I am learning Python (3) and am practicing by making a few practical programs. An issue I am running in to is how to get the right flow to the program. I find that as I write a function, I realize that I need it to lead to another function, so I end up calling the next function at the end of the function I'm writing. Then I realize that Python will read the code line-by-line, so I have to have the function I will be calling above the one I am actively writing. The effect is that I end up writing the program in reverse. For example:
#Replaces letters in chosen word with X's
def display_word():
selected_word = list(selected_word)
for x in selected_word:
x = "X"
print (x)
#Function that will display the welcome message when program launches
def start_screen():
user_input = input("Hello and welcome to Hang Man! If you would like to
start a game, please enter 'YES' now!")
user_input = user_input.upper()
if user_input == "YES":
display_word()
else:
print ("You're no fun!")
start_screen()
This is a little tid-bit that I have written in a hang-man program I am practicing with. I started out writing the start_screen function, then realized that I will need to call the display_word function within the start_screen function, but to do that, I will have to define the function before it is called, so I have to write the display_word function above the start_screen function, which effectively has me moving in reverse. My question is whether this is the way things go or if there is a better way to do things. It seems like writing the code in reverse is inefficient, but I am unsure if that is just my inexperience talking.
All functions in Python must be defined before they are used. That does not mean that the function has to be listed above the one it is called from.
The functions can be defined in any order. You just have to make sure the executable portions that start your program, like start_screen(), are called below where the function is defined.
In the case of your hangman program, you are perfectly safe to switch the order of the two functions.
In general, if you have all of your executable code following all of your function definitions, you are good to go to keep them in any order you choose!
Example:
This is perfectly ok. You can even switch them!
def fn1():
print('I am function 1')
fn2()
def fn2():
print ('I am function 2')
fn1()
This is bad!
fn1() #not defined yet!
def fn1():
print('I am function 1')
def fn2():
print ('I am function 2')
This is also bad!
def fn1():
print('I am function 1')
fn2() #not defined yet!
fn1()
def fn2():
print ('I am function 2')

How to save the input in a list on python 3

I code this into my python 3 and everytime that im going to run it. Of course it performs it function but not the things i wanted it to run. It will ask you to put some course that your want to add into the list which is the "courses_list" but my problem was everytime i type another input (courses) it just only replace whats inside the courses_list. It didn't save it like what i want.
def courses():
courses_list = []
coursesInput = input("Insert the course you want")
courses_list.insert(0, coursesInput)
print (courses_list)
courses()
courses()
Result : Example i type (CompScie and Physics)
CompSci
['CompScie']
Physics
['Physics']
so how can i save the result of the courses_list so everytime that it ask me again to give another courses it will insert it to the courses_list.
What i want to happen :
CompScie
['CompScie']
Physics
['Physics', 'CompScie']
This happens because you have made the list inside the function. So everytime the function gets called, it creates a new list and appends the input. What you need to do is create a list outside the scope of function and modify it using argument.
def courses(c_list):
coursesInput = input("Insert the course you want")
c_list.insert(0, coursesInput)
print (c_list)
courses(c_list)
courses_list = []
courses(course_list)

Creating a list of Class objects from a file with no duplicates in attributes of the objects

I am currently taking some computer science courses in school and have come to a dead end and need a little help. Like the title says, I need of create a list of Class objects from a file with objects that have a duplicate not added to the list, I was able to successfully do this with a python set() but apparently that isn't allowed for this particular assignment, I have tried various other ways but can't seem to get it working without using a set. I believe the point of this assignment is comparing data structures in python and using the slowest method possible as it also has to be timed. my code using the set() will be provided.
import time
class Students:
def __init__(self, LName, FName, ssn, email, age):
self.LName = LName
self.FName = FName
self.ssn = ssn
self.email = email
self.age = age
def getssn(self):
return self.ssn
def main():
t1 = time.time()
f = open('InsertNames.txt', 'r')
studentlist = []
seen = set()
for line in f:
parsed = line.split(' ')
parsed = [i.strip() for i in parsed]
if parsed[2] not in seen:
studentlist.append(Students(parsed[0], parsed[1], parsed[2], parsed[3], parsed[4]))
seen.add(parsed[2])
else:
print(parsed[2], 'already in list, not added')
f.close()
print('final list length: ', len(studentlist))
t2 = time.time()
print('time = ', t2-t1)
main()
A note, that the only duplicates to be checked for are those of the .ssn attribute and the duplicate should not be added to the list. Is there a way to check what is already in the list by that specific attribute before adding it?
edit: Forgot to mention only 1 list allowed in memory.
You can write
if not any(s.ssn==parsed[2] for s in studentlist):
without committing to this comparison as the meaning of ==. At this level of work, you probably are expected to write out the loop and set a flag yourself rather than use a generator expression.
Since you already took the time to write a class representing a student and since ssn is a unique identifier for the instances, consider writing an __eq__ method for that class.
def __eq__(self, other):
return self.ssn == other.ssn
This will make your life easier when you want to compare two students, and in your case make a list (specifically not a set) of students.
Then your code would look something like:
with open('InsertNames.txt') as f:
for line in f:
student = Student(*line.strip().split())
if student not in student_list:
student_list.append(student)
Explanation
Opening a file with with statement makes your code more clean and
gives it the ability to handle errors and do cleanups correctly. And
since 'r' is a default for open it doesn't need to be there.
You should strip the line before splitting it just to handle some
edge cases but this is not obligatory.
split's default argument is ' ' so again it isn't necessary.
Just to clarify the meaning of this item is that the absence of a parameter make the split use whitespaces. It does not mean that a single space character is the default.
Creating the student before adding it to the list sounds like too
much overhead for this simple use but since there is only one
__init__ method called it is not that bad. The plus side of this
is that it makes the code more readable with the not in statement.
The in statement (and also not in of course) checks if the
object is in that list with the __eq__ method of that object.
Since you implemented that method it can check the in statement
for your Student class instances.
Only if the student doesn't exist in the list, it will be added.
One final thing, there is no creation of a list here other than the return value of split and the student_list you created.

Resources