How can i create a "run-loop" function that detects key-presses using Python? - python-3.x

I'm new to python3 and I've been practicing by doing some basic programs but now I'm stuck with a little snake type game I wrote. The code I wrote so far have the following parts in order:
Imported modules
Classes to get a key from the user without the need to press "enter"
A function that is called by the module threading (named move_alt()).
t = threading.Thread(target=move_alt) # this is immediately after the portion of code
described in point 3)
4)A move_forward() function to create the map using a list of characters and to move a "position character" starting at the center of the map to the right till it crashes into a "wall caracter". This function is named move_forward().
t.setDaemon(True)
t.start()
move_forward()
The idea is to start a thread to run simultaneously with move_forward function, which targets the function described in 2) to take a key from the user and depending on what key was pressed make some action over move_forward function, for example (and to be more specific) move_up or move_down, etc.
I don't know how to use the threading module correctly so I'm not getting my code to work as expected. Instead what is happening is the program would run the thread without running simultaneously the move_forward function and until I don't press a key (which is what it's done inside the thread) it doesn't do anything. Actually, at the beginning when i just run the program it tries to draw the map (list of characters) but only draws some characters and then gets stuck.
Sorry if my explanation wasn't efficient but English is not my first language and I tend to write too much.
P.S= I didn't put the code above because it is too long due to comments and stuff I made to learn (and not forget)

After a lot of thinking I was finally able to make the program work as expected. First of all, the threading module wasn't the best option but for some reason I was confusing threading (which is used for concurrency purposes) with whatever I was trying to do. So after a little while I stopped using this idea.
The way I managed to make it work was actually using another module called "keyboard" (for linux users you have to use the module as root for some reason). Here is a little bit of a code to use that module:
def onkeypressw(event): this function is used as a condition in the "while loop" for the move_up condition
global stopw
if event.name == 's' or event.name == "a" or event.name == "d":
stopw = True
keyboard.on_press(onkeypressw)
def onkeypressw1(event): # this function is used as condition in the if sentence in the main function to call move_up() function
global runw1
if event.name == "w":
runw1 = True
else:
runw1 = False
keyboard.on_press(onkeypressw1)
Then in the main function i have a while True loop running, where i have some if sentences that run one of four possibles move function: move_up, move_down, move_left, move_right depending of which key i pressed (w-s-d-a). Inside these "move functions" there are while loops to draw the map and move the character position(let's say the snake head) using a list of characters, until I press another button. So for example if in the main function I pressed "w" the program is going to run move_up function and move the character position until either it crashes against "the wall character" or I press "s, d or a". The conditions I put for the "while loop" are: 1)one for the wall character and 2)"not stopw" so it draws the list until I crash against the wall or stopw = True.
I know you can make this code using others modules and get the same result with less work but i wanted to use as much basic code as possible to learn python3 faster because I had previous experience programming with C.
P.S: Here is one of the moves function, just in case someone is curious:
def move_up():
global c, f
global map1
global stopw
while f> 0 and not stopw:
map1[f, c] = " o " # f represents the rows and c the columns, I replaced the initial position character "_" for "o"
f = f - 1 # up one row
map1[f, c] = " _ " # I put the position character "_" at the new position
cls() # clear the screen
time.sleep(0.4) # add a little delay just to modify the snake speed
stopw = False # reset the boolean

Related

Defining a function to find the unique palindromes in a given string

I'm kinda new to python.I'm trying to define a function when asked would give an output of only unique words which are palindromes in a string.
I used casefold() to make it case-insensitive and set() to print only uniques.
Here's my code:
def uniquePalindromes(string):
x=string.split()
for i in x:
k=[]
rev= ''.join(reversed(i))
if i.casefold() == rev.casefold():
k.append(i.casefold())
print(set(k))
else:
return
I've tried to run this line
print( uniquePalindromes('Hanah asked Sarah but Sarah refused') )
The expected output should be ['hanah','sarah'] but its returning only {'hanah'} as the output. Please help.
Your logic is sound, and your function is mostly doing what you want it to. Part of the issue is how you're returning things - all you're doing is printing the set of each individual word. For example, when I take your existing code and do this:
>>> print(uniquePalindromes('Hannah Hannah Alomomola Girafarig Yes Nah, Chansey Goldeen Need log'))
{'hannah'}
{'alomomola'}
{'girafarig'}
None
hannah, alomomola, and girafarig are the palindromes I would expect to see, but they're not given in the format I expect. For one, they're being printed, instead of returned, and for two, that's happening one-by-one.
And the function is returning None, and you're trying to print that. This is not what we want.
Here's a fixed version of your function:
def uniquePalindromes(string):
x=string.split()
k = [] # note how we put it *outside* the loop, so it persists across each iteration without being reset
for i in x:
rev= ''.join(reversed(i))
if i.casefold() == rev.casefold():
k.append(i.casefold())
# the print statement isn't what we want
# no need for an else statement - the loop will continue anyway
# now, once all elements have been visited, return the set of unique elements from k
return set(k)
now it returns roughly what you'd expect - a single set with multiple words, instead of printing multiple sets with one word each. Then, we can print that set.
>>> print(uniquePalindromes("Hannah asked Sarah but Sarah refused"))
{'hannah'}
>>> print(uniquePalindromes("Hannah and her friend Anna caught a Girafarig and named it hannaH"))
{'anna', 'hannah', 'girafarig', 'a'}
they are not gonna like me on here if I give you some tips. But try to divide the amount of characters (that aren't whitespace) into 2. If the amount on each side is not equivalent then you must be dealing with an odd amount of letters. That means that you should be able to traverse the palindrome going downwards from the middle and upwards from the middle, comparing those letters together and using the middle point as a "jump off" point. Hope this helps

Do multiple logical statement work in a single while loop?

I'm trying to design a game of tic-tac-toe on python. I was just trying it out step by step before arranging the whole program. But I am stuck with the conditioning part of it. Specifically the while loop. Previously, I've only used a single logical/boolean expression. Here I need to use multiple ones.
I have tried it for just the horizontal conditioning as of now, but still it doesn't work.
finaltic=[1,2,3,4,5,6,7,8,9]
def tic_board():
print(finaltic[0],'|',finaltic[1],'|',finaltic[2])
print(finaltic[3],'|',finaltic[4],'|',finaltic[5])
print(finaltic[6],'|',finaltic[7],'|',finaltic[8])
tic_board()
def replace_tic():
a=int(input('Enter your number: '))
z=a-1
finaltic[z]='X'
tic_board()
b=int(input('Enter your number: '))
x=b-1
finaltic[x]='O'
tic_board()
def conditional_tic():
con1=finaltic[0]!=finaltic[1] or finaltic[1]!=finaltic[2]
con2=finaltic[3]!=finaltic[4] or finaltic[4]!=finaltic[5]
con3=finaltic[6]!=finaltic[7] or finaltic[7]!=finaltic[8]
while con1 and con2 and con3:
replace_tic()
conditional_tic()
As soon as anyone of the variables i.e. con1 or con2 or con3 become False, the while loop should break. But it goes in infinite loop.
For your loop to work, you'll need to recompute the conditions inside of it. Currently, con1, con2 and con3 are only computed once, and then their values are tested repeatedly. That's probably not very useful, since they'll always have the same values (even if finaltic changes).
You could fix this by copying the whole set of the computations to the bottom of loop:
con1=finaltic[0]!=finaltic[1] or finaltic[1]!=finaltic[2]
con2=finaltic[3]!=finaltic[4] or finaltic[4]!=finaltic[5]
con3=finaltic[6]!=finaltic[7] or finaltic[7]!=finaltic[8]
while con1 and con2 and con3:
replace_tic()
con1=finaltic[0]!=finaltic[1] or finaltic[1]!=finaltic[2]
con2=finaltic[3]!=finaltic[4] or finaltic[4]!=finaltic[5]
con3=finaltic[6]!=finaltic[7] or finaltic[7]!=finaltic[8]
But copying and pasting code like that is usually a bad idea (both because it can copy bugs, but also because you might want to update the condition later and after a copy/paste you'd need to update two places consistently).
A better solution might be to avoid the extra variables and just do the or tests directly in the while condition. Alas this does require extra parentheses, since the condition is quite long:
while ( # these outer parentheses are only needed to let us split over multiple lines
(finaltic[0] != finaltic[1] or finaltic[1] != finaltic[2]) and
(finaltic[3] != finaltic[4] or finaltic[4] != finaltic[5]) and
(finaltic[6] != finaltic[7] or finaltic[7] != finaltic[8])
):
replace_tic()
You might also consider writing a function to do the condition testing, and call it from the loop condition. That's only a definite win if you might need that condition elsewhere.

How do I replace and update a string multiple times in Python?

I'm working on a quiz program and need some help. I'm trying to replace words one at a time, but Python isn't saving the previously replaced string. Here is a mini example of what I mean:
replacedQuiz=""
easyQuiz = """
You can change a string variable to an integer by typing (__1__)
in front of the variable. It also works vice versa, you can change an
integer
variable to a string by typing (__2__). This is important to remember before
you __3__ strings together, or else a TypeError will occur. While adding an
integer to a string, it is important to separate it using a __4__ (use the
symbol). \n"""
def replaceWord(replaced, quiz, numCount):
if numCount == 1:
replaced = quiz.replace("__1__", "int")
if numCount == 2:
replaced = replaced.replace("__2__", "str")
if numCount == 3:
replaced= replaced.replace("__3__", "concatenate")
if numCount == 4:
replaced= replaced.replace("__4__", ",")
print replaced
def easy():
QCount=1
print easyQuiz
while QCount < 5:
replaceWord(replacedQuiz, easyQuiz, QCount)
QCount += 1
print easy()
I thought that by making a String called replacedQuiz, it would save the first replacement and then I could continue replacing the words inside the quiz and updating it. Please help! I don't know where I'm going wrong
You seem to have made a slight mistake in the scope of your variable replacedQuiz (it'd certainly suggest that you check out some explanation of this topic). Basically, you are replacing replacedQuiz by its new value only within your current function. Your other functions only have access to the global value you defined earlier. There are several ways to fix this (e.g. the global keyword) but the standard way would be to return the new replacedQuiz from your function.
To do so, add the following line to the end of your replaceWord function:
return replacedQuiz
This tells Python to use this value at the line it was called at. You can then define a new value for replacedQuiz within easy by just defining it as the returned value:
replacedQuiz = replaceWord(replacedQuiz, easyQuiz, QCount)

Selecting an element of a list inside a list (python)

Im attempting to write a turn based, pokemon-esque, game to test my python skills & learn new things.
I'm having trouble selecting an element from a list inside of another list.
Punch = ["Punch!", 20]
Kick = ["Kick!", 40]
Moves = [Punch, Kick]
Player = ["Jamie", 100, Moves]
print ("Do you want to punch, or kick?")
attack = input(" ")
if attack == "punch":
atk = 0
if attack == "kick":
atk = 1
damage = Player[2[atk[1]]]
print (Player[0]," uses ", Player[2[atk[0]]])
but this results in error:
TypeError: 'int' object is not subscriptable
I understand why this error happens. But I'm wondering is there is another way to call up an element of a list inside of a list.
Thanks
What you want is probably something like this :
damage = Player[2][atk][1]
But beware because you only define atk in if statements so atk could potentially not be defined after those ifs.
Moreover you place either 1 or 2 in atk but you only have two moves which makes me think you want to put either 0 or 1 in it.
Note: You should not capitalise the name of your variables as it would imply they are classes instead of variables
from the way i understand
damage=Player[2][atk][1]
As has already been mentioned . The thing to understand is what is happening when you do this.
player[2] refers to Moves and when you further subscript it, it subscripts to the Moves, so player[2][atk] simply becomes Moves[atk].
A thing to keep in mind is that it is truly just a reference, if you were to change the list Moves, the value in player[2] will also change.
For example:
code:
Moves[1][2]=1000
print(player[2][1][2])
Will give output
1000

Program ignores all the numbers after the 1st one

Why the program takes just the first number in the list and ignores others, making an empty list.
This happens in every function with for loop.
cars=[23.11,1531,'volvo','BMW']
def price(CAR):
num=[]
strings=[]
for i in CAR:
if isinstance(i,float)or isinstance(i,int):
num.append(i)
elif isinstance(i,str):
strings.append(i)
else:
pass
return num,strings
print(price(cars))
([23.11], [])
The only reason I can think of is, your return statement is aligned with your for loop, so it exists after the first iteration. (Though it looks aligned correctly right now, maybe the editor corrected it instinctively.)

Resources