how to make functions cooperate - python

So I was going to make an arithmetic operator:
import random
solution = 0
summation = False
multiplication_table = False
subtraction = False
the_exercise = False
def arithmetic_operation(arithmetic_type):
stopper = []
exercise = input(
f"This is the {arithmetic_type} generator. Subjects: summation, multiplication table, subtraction.\nWhich of the subjects is "
"the student to practice? Please choose one of these 3 specifically")
if exercise == 'summation':
summation = True
elif exercise == 'multiplication table':
multiplication_table = True
elif exercise == 'subtraction':
subtraction = True
while summation == True:
ten_exercises = 0
if ten_exercises == 2:
summation == False
a = random.randint(0, 50)
b = random.randint(0, 50)
solution = a + b
print(f"What is {a} + {b}?")
the_exercise = True
return solution
while multiplication_table == True:
ten_exercises = 0
if ten_exercises == 2:
summation == False
a = random.randint(0, 10)
b = random.randint(0, 10)
solution = a * b
print(f"What is {a} * {b}?")
the_exercise = True
return solution
while subtraction == True:
ten_exercises = 0
if ten_exercises == 2:
summation == False
a = random.randint(21, 100)
b = random.randint(0, 20)
solution = a - b
print(f"What is {a} - {b}?")
the_exercise = True
return solution
arithmetic_operation("artithmetic exercise")
def main():
while the_exercise == True:
ans = input()
if int(ans) == solution:
print("Correct!")
stopper.append("STOP!")
if stopper.count("STOP!") == 10:
print("That's the end. Until next time!")
summation == False
else:
break
else:
print("Wrong! Try again")
ten_exercises += 1
if __name__ == '__main__':
main()
The problem is that my two functions aren't cooperating. According to the exercise, 'arithmetic_operation' is supposed to have a parameter.
What is it that I fail to understand? I have tried multiple solutions and replacing blocks of code to the main, but it doesn't work...

Related

function unable to work with user inputs?

I have the following code, which is a code for a connect 4 game, the problem is that the functions seem to break in the user input part of the code. I don't know if I accidentally edited something to break it but I'm almost certain that it isn't as typing the adding this to the code:
addcounter(1,1)
addcounter(1,1)
addcounter(1,1)
addcounter(1,1)
addcounter(2,1)
addcounter(2,1)
addcounter(2,1)
addcounter(3,1)
addcounter(3,1)
addcounter(4,1)
checkdiagonal(4,1,1)
The output of this does return true as expected.
The code is as follows:
# -*- coding: utf-8 -*-
"""
Created on Sun Dec 22 17:24:35 2019
#author: Norbert
"""
import numpy as np
h = 8
w = 9
x = 0
y = 0
playspace = np.zeros((h,w))
playspace[:, [0,-1]] = 8
def addcounter(column,team):
placed = False
while not placed:
for i in range(h-1,0,-1):
if playspace[i,column] > 0:
continue
else:
if team == 1:
playspace[i,column] = 1
if team == 2:
playspace[i,column] = 2
if team != 1 and team != 2:
print("error, invalid team")
placed = True
break
def height(column):
for i in range(h-1,0,-1):
if playspace[i,column] > 0:
continue
else:
return i
def checkhorizontal(y,x,team):
a1 = 0
a2 = 0
a3 = 0
a4 = 0
for i in range(4):
try:
if playspace[h-y,x+i] == team:
a1 += 1
if playspace[h-y,x+i-1] == team:
a2 += 1
if playspace[h-y,x+i-2] ==team:
a3 += 1
if playspace[h-y,x+i-3] ==team:
a4 += 1
except:
pass
if (a1 == 4) or (a2 == 4) or (a3 == 4) or (a4 == 4):
return True
def checkvertical(y,x,team):
a1 = 0
a2 = 0
a3 = 0
a4 = 0
checking = playspace[:,x]
for i in range(4):
try:
if checking[h-(y+i)] == team:
a1 += 1
if checking[h-(y+i-1)] == team:
a2 += 1
if checking[h-(y+i-2)] ==team:
a3 += 1
if checking[h-(y+i-3)] == team:
a4 += 1
except:
pass
if (a1 == 4) or (a2 == 4) or (a3 == 4) or (a4 == 4):
return True
def checkdiagonal(y,x,team):
diag1 = 0
diag2 = 0
if playspace[h-y,x] == team:
diag1 += 1
diag2 += 1
for i in range(1,4):
broken1 = False
try:
if playspace[h-y+i,x+i] == team and not broken1:
diag1 += 1
if playspace[h-y+i,x+i] != team:
broken1 = True
except:
pass
for i in range(1,4):
broken2 = False
try:
if playspace[h-y-i,x-i] == team and not broken2:
diag1 += 1
if playspace[h-y-i,x-i] != team:
broken2 = True
except:
pass
for i in range(1,4):
broken3 = False
try:
if playspace[h-y+i,x-i] == team and not broken3:
diag2 += 1
if playspace[h-y+i,x-i] != team:
broken3 = True
except:
pass
for i in range(1,4):
broken4 = False
try:
if playspace[h-y-i,x+i] == team and not broken4:
diag2 += 1
if playspace[h-y-i,x+i] != team:
broken4 = False
except:
pass
if (diag1 >= 4) or (diag2 >= 4):
return True
finished = False
turn = 0
team_turn = 1
print(playspace)
while not finished:
valid = False
print("turn: {}".format(turn))
print("It is player {}'s turn".format(team_turn))
while not valid:
player_input = int(input("Where would you like to drop a counter?"))
if playspace[0,player_input] != 0:
print("That isn't a valid column")
else:
valid = True
if team_turn == 1:
addcounter(player_input,team_turn)
if checkhorizontal(height(player_input),player_input,team_turn) == True or checkvertical(height(player_input),player_input,team_turn) == True or checkdiagonal(height(player_input),player_input,team_turn) == True:
print("Player {} wins".format(team_turn))
finished = True
if team_turn == 2:
addcounter(player_input,team_turn)
if checkhorizontal(height(player_input),player_input,team_turn) == True or checkvertical(height(player_input),player_input,team_turn) == True or checkdiagonal(height(player_input),player_input,team_turn) == True:
print("Player {} wins".format(team_turn))
finished = True
turn += 1
turn_changed = False
while not turn_changed:
if team_turn == 1:
team_turn = 2
turn_changed = True
break
if team_turn == 2:
team_turn = 1
turn_changed = True
break
print(playspace)
any help in trying to solve the bugs in the code would be grately appreciated. The connect 4 game uses simple 2-d arrays to display and store the game board. I have plans to use this array to create a pygame later on.
EDIT:
To clarify, the checks don't run to execute a victory message and end the game. despite the if statements being True. Only the vertical win seems to end the game.
I managed to correct the horizontal part, the code correction is as follows:
if (checkhorizontal(height(player_input)+1,player_input,team_turn) == True) or (checkvertical(height(player_input),player_input,team_turn) == True) or (checkdiagonal(height(player_input),player_input,team_turn) == True):
and in the horizontalcheck function:
def checkhorizontal(y,x,team):
a1 = 0
a2 = 0
a3 = 0
a4 = 0
checking = playspace[y,:]
print(checking)
for i in range(4):
try:
if checking[x+i] == team:
a1 += 1
if checking[x+i-1] == team:
a2 += 1
if checking[x+i-2] ==team:
a3 += 1
if checking[x+i-3] ==team:
a4 += 1
except:
pass
print(a1,a2,a3,a4)
if (a1 == 4) or (a2 == 4) or (a3 == 4) or (a4 == 4):
return True
Ignore the prints, they're for debugging. But I basically removed one dimension and flipped the h-y value to become the y value.

Python keyboard module not working properly inside loop

I'm trying to create a simple game that creates math problems and the users task is to decide if they are true or false. (eg. 2 + 2 = 6, True or False?)
I am using the keyboard module and I want to have the user press the left arrow key if he thinks that the problem is true, and the right one if he thinks that it's false.
import random
import keyboard
def addition_easy():
x = random.randint(1, 6)
y = random.randint(1, 6)
z = x + y
answer_correct = random.choice([True, False])
if answer_correct == False:
answer = (random.randint(2, 12))
else:
answer = z
if answer == z:
answer_correct = True
print(f"{x} + {y} = {answer}")
print("True or False?")
while True:
if keyboard.is_pressed('left'):
user_answer = True
break
elif keyboard.is_pressed('right'):
user_answer = False
break
if user_answer == answer_correct:
return True
else:
return False
The thing is, after I paste this function into a loop, I can only press left or right once. After that the rest of the code is executed without waiting for my keypress.
from problems import addition_easy
exercise_amount = int(input("How many exercises would you like to solve?"))
for exercise in range(1, exercise_amount + 1):
addition_easy()
This returns (for input of 5):
How many exercises would you like to solve? 5
6 + 1 = 9
True or False? //(Here it waits for me to press "left" or "right")
3 + 3 = 8
True or False? //(From here it doesn't stop to wait for a keypress)
4 + 3 = 7
True or False? //(Same here and so on...)
2 + 3 = 3
True or False?
1 + 2 = 3
True or False?
How can I make it wait for a keypress every time it prints out a math problem?
If the user holds down "left" for half a second, and addition_easy executes a hundred times in that half second, then keyboard.is_pressed('left') will evaluate to True for every one of them, even though the user only pressed "left" once.
You can verify that is_pressed doesn't permanently consider "left" to be pressed by telling your program to do 1000 problems. Pressing left will only answer about 20 of them.
One possible solution is to alter your loop so it waits until the key is subsequently released before continuing.
while True:
if keyboard.is_pressed('left'):
user_answer = True
while keyboard.is_pressed("left"):
pass
break
elif keyboard.is_pressed('right'):
user_answer = False
while keyboard.is_pressed("right"):
pass
break
Another possible design is to use keyboard.on_press_key, which should only fire when the key changes state from "not pressed" to "pressed" (or when the auto repeat time elapses, which probably won't happen unless the user is doing it intentionally). You can abstract this out to a function to keep your addition_easy function clean:
import random
import keyboard
import time
def wait_for_keys(keys):
key_pressed = None
def key_press_event(key):
nonlocal key_pressed
key_pressed = key.name
for key in keys:
keyboard.on_press_key(key, key_press_event)
while key_pressed is None:
time.sleep(0.01)
return key_pressed
def addition_easy():
x = random.randint(1, 6)
y = random.randint(1, 6)
z = x + y
answer_correct = random.choice([True, False])
if answer_correct == False:
answer = (random.randint(2, 12))
else:
answer = z
if answer == z:
answer_correct = True
print(f"{x} + {y} = {answer}")
print("True or False?")
key = wait_for_keys(["left", "right"])
user_answer = (key == "left")
if user_answer == answer_correct:
return True
else:
return False
exercise_amount = 1000
for exercise in range(1, exercise_amount + 1):
addition_easy()
Not sure if you indented your function correctly. Try:
import random
import keyboard
def addition_easy():
x = random.randint(1, 6)
y = random.randint(1, 6)
z = x + y
answer_correct = random.choice([True, False])
if answer_correct == False:
answer = (random.randint(2, 12))
else:
answer = z
if answer == z:
answer_correct = True
print(f"{x} + {y} = {answer}")
print("True or False?")
while True:
if keyboard.is_pressed('left'):
user_answer = True
break
elif keyboard.is_pressed('right'):
user_answer = False
break
if user_answer == answer_correct:
return True
else:
return False
exercise_amount = int(input("How many exercises would you like to solve?"))
for exercise in range(1, exercise_amount + 1):
addition_easy()

Connect 4 implemented with python AI alpha-beta-pruning (Recursion/MemoryError)?

I'm trying to create a game called Connect Four with AI which uses the alpha-beta pruning algorithm in python. Here is the code I have managed to write:
# -*- coding: utf-8 -*-
import sys
class ConnectFour:
def __init__(self):
self.board = [[],[],[],[],[],[]]
for i in range(7):
for j in range(6):
self.board[j].append(" ")
self.moves = 0
self.colstack = [0,0,0,0,0,0,0]
self.node = 0
self.move = 0
def PrintGameBoard(self):
print(' 0 1 2 3 4 5 6')
for i in range(5, -1, -1):
print('|---|---|---|---|---|---|---|')
print("| ",end="")
for j in range(7):
print(self.board[i][j],end="")
if j != 6:
print(" | ",end="")
else:
print(" |")
print('`---------------------------ยด')
def CanPlay(self, col):
return self.colstack[col] < 6
def Play(self, col, board):
board[self.colstack[col]][col] = 2
self.colstack[col] += 1
self.moves += 1
return board
def IsWinning(self, currentplayer):
for i in range(6):
for j in range(4):
if self.board[i][j] == currentplayer and self.board[i][j+1] == currentplayer and self.board[i][j+2] == currentplayer and self.board[i][j+3] == currentplayer:
return True
for i in range(3):
for j in range(7):
if self.board[i][j] == currentplayer and self.board[i+1][j] == currentplayer and self.board[i+2][j] == currentplayer and self.board[i+3][j] == currentplayer:
return True
for i in range(3):
for j in range(4):
if self.board[i][j] == currentplayer and self.board[i+1][j+1] == currentplayer and self.board[i+2][j+2] == currentplayer and self.board[i+3][j+3] == currentplayer:
return True
for i in range(3,6):
for j in range(4):
if self.board[i][j] == currentplayer and self.board[i-1][j+1] == currentplayer and self.board[i-2][j+2] == currentplayer and self.board[i-3][j+3] == currentplayer:
return True
return False
def AlphaBeta(self, alpha, beta):
self.node += 1
if self.moves == 42:
return 0
for col in range(7):
if self.CanPlay(col) and self.IsWinning(2):
return (43 - self.moves)/2
max = (41 - self.moves)/2
if beta > max:
beta = max
if alpha >= beta:
return beta
for col in range(7):
if self.CanPlay(col):
self.board[self.colstack[col]][col] = 2
self.move = col
score = -self.AlphaBeta(-alpha, -beta)
if score >= beta:
return score
elif score > alpha:
alpha = score
self.board[self.colstack[col]][col] = " "
def Solve(self, table, week=False):
self.node = 0
self.board = table
if week:
self.AlphaBeta(-1, 1)
self.board = self.Play(self.move, table)
return self.board
else:
self.AlphaBeta(-21, 21)
self.board = self.Play(self.move, table)
return self.board
def PlayerMove(self, table):
self.board = table
try:
allowedmove = False
while not allowedmove:
print("Choose a column where you want to make your move (0-6): ",end="")
col =input()
if self.CanPlay(int(col)):
self.board[self.colstack[int(col)]][int(col)] = 1
self.moves += 1
self.colstack[int(col)] += 1
allowedmove = True
else:
print("This column is full")
except (NameError, ValueError, IndexError, TypeError, SyntaxError) as e:
print("Give a number as an integer between 0-6!")
else:
return self.board
def PlayerMark():
print("Player 1 starts the game")
mark = ''
while not (mark == "1" or mark == "2"):
print('Do you want to be 1 or 2: ',end="")
mark = input()
if mark == "1":
return 1
else:
return 2
def PlayAgain():
print('Do you want to play again? (yes or no) :',end="")
return input().lower().startswith('y')
def main():
sys.setrecursionlimit(2000)
print("Connect4")
while True:
mark = PlayerMark()
connectfour = ConnectFour()
if mark==1:
print("You are going to start the game\r\n\r\n")
else:
print("Computer (negamax) starts the game")
gameisgoing = True
table = [[],[],[],[],[],[]]
for i in range(7):
for j in range(6):
table[j].append(" ")
while gameisgoing:
connectfour.PrintGameBoard()
if mark == 1:
table = connectfour.PlayerMove(table)
if connectfour.IsWinning(1):
connectfour.PrintGameBoard()
print('You won the game!')
gameisgoing = False
else:
if connectfour.moves==42:
connectfour.PrintGameBoard()
print('Game is tie')
break
else:
mark = 2
else:
move = connectfour.Solve(table)
if connectfour.IsWinning(2):
connectfour.PrintGameBoard()
print('Computer won the game')
gameisgoing = False
else:
if connectfour.moves==42:
connectfour.PrintGameBoard()
print('Game is tie')
break
else:
mark = 1
if not PlayAgain():
print("Game ended")
break
if __name__ == '__main__':
main()
I'm not sure if the algorithm is working properly, but the problem is that I get RecursionError: maximum recursion depth exceeded in comparison. If I increase recursionlimit I get in around 10000 MemoryError: Stack Overflow. I think that the problem is that there is too many states to handle for my computer. That's why I changed the negamax algorithm to alpha-beta pruning, but there seem to be still to many states. Is there a effective technique that does algorithmic search, for example max depth 10 and still the computer is almost invincible? I'm waiting your solutions.

Anything wrong with my python Monty hall simulation?

Did I go wrong somewhere? I keep getting 50% wins even after switching.
import random
def monty_hall():
#-----setup ----#
prizes = ["Car" , "Goat" , "Goat"]
random.shuffle(prizes)
#----person chooses at random----#
choose_index = random.randint(0,2)
##-------host reveals a goat------#
while True:
goat_gate = random.randint(0, 2)
if prizes[goat_gate] == "Goat":
break
##------person switches -------##
while True:
switch_choice = random.randint(0, 2)
if (switch_choice!= choose_index) & (switch_choice!= goat_gate):
break
## -- check if won---#
if prizes[switch_choice] == "Car":
return True
win = 0
games = 100000
for times in range(games):
if monty_hall() == True:
win += 1
print(win/games)
Yes, you didn't include the fact that the host will not reveal what's behind the chosen door.
while True :
goat_gate = random.randint(0, 2)
if prizes[goat_gate] == "Goat" :
break
should be
while True :
goat_gate = random.randint(0, 2)
if prizes[goat_gate] == "Goat" and goat_gate != choose_index:
break

List index out of range when coding a valid move for board game

Hey everyone im new here and im trying to make a game called HiQ now i got the board drawn and everything and i can click on one of the pieces, but when i do the piece does change color and i get an error in the shell as well (listed below) im not sure why im getting this and i was hoping you guys could give me better insight. Ill provide my code below as well and it is coded in python 3, thank you
builtins.IndexError: list index out of range
boardcirc =[[0,0,0,1,1,1,0,0,0],
[0,0,0,1,1,1,0,0,0],
[0,0,0,1,1,1,0,0,0],
[1,1,1,1,1,1,1,1,1],
[1,1,1,1,2,1,1,1,1],
[1,1,1,1,1,1,1,1,1],
[0,0,0,1,1,1,0,0,0],
[0,0,0,1,1,1,0,0,0],
[0,0,0,1,1,1,0,0,0]]
def HiQ():
splash_screen()
make_board()
def make_board():
make_sqr()
make_circ()
get_click()
def get_click():
global count, boardcirc
while 1!=0:
count = count - 1
displaymessage("Pieces: " + str(count))
where = win.getMouse()
col = where.x//90
row = where.y//90
valid_move(row,col)
make_move(row,col)
def valid_move(row,col):
if boardcirc[row][col] == 0:
return False
if boardcirc[row-1][col] == 1 and boardcirc[row-2][col] == 1:
return True
if boardcirc[row+1][col] == 1 and boardcirc[row+2][col] == 1:
return True
if boardcirc[row][col-1] == 1 and boardcirc[row][col-2] == 1:
return True
if boardcirc[row][col+1] == 1 and boardcirc[row][col+2] == 1:
return True
def make_move(row,col):
while valid_move(row,col) == True:
col = (col*85)+42
row = (row*85)+42
circ = Circle(Point(col,row),35)
circ.setFill("white")
circ.draw(win)
thats everything that applies to the error
For your valid_move(row,col), you can't have all those if statements.
Instead of doing this, use elif's after the initial if statement, and don't forget to write an else statement
if boardcirc[row][col] == 0:
return False
if boardcirc[row-1][col] == 1 and boardcirc[row-2][col] == 1:
return True
elif boardcirc[row+1][col] == 1 and boardcirc[row+2][col] == 1:
return True
elif boardcirc[row][col-1] == 1 and boardcirc[row][col-2] == 1:
return True
elif boardcirc[row][col+1] == 1 and boardcirc[row][col+2] == 1:
return True
else:
return False

Categories