Windows 8.1/10 Crashing on if-statements within while loop - python

I have a simple block of code that works perfectly on Windows 7 machines and Ubuntu machines, but when I try to run it on 8.1/10 it freezes. I'm not sure why. I've tried 3.0/3.6/2.7 interpreters on variations of the code but it still freezes. Does anyone have a solution? The offending code is the if/else-statement at the bottom.
from graphics import *
def main():
lowx = -10.0
highx = +10.0
lowy = -10.0
highy = +10.0
incx = 0.1
points = []
x = lowx
while x <= highx:
# y = EvaluatePostfix(postfix, x)
if x > 0:
y = x * x
else:
y = x * x * x
points.append((x, y))
x += incx
# Graph
win = GraphWin("My Graphing Calculator", 700, 700)
win.setCoords(lowx, lowy, highx, highy)
for i in range(len(points) - 1):
p1 = Point(points[i][0], points[i][1])
p2 = Point(points[i + 1][0], points[i + 1][1])
line = Line(p1, p2)
line.draw(win)
while (True):
user = input("type your answer")
if user == "hello":
print("there")
else:
print("bad")
win.getMouse() # Pause to view result
win.close() # Close window when done
main()

Related

converting code to be able to use Multiprocessing

I have a rather long question I hope I can get help with.
I have a code that runs a simulation by a "while true" loop and after that a "for" loop that saves data from the simulation and restart the sim after given time. This code works fine, but now Im trying to convert this into a multiprocess where I can get 4 simultaneous simulations and for loops. So I tried to put most of the code into a function and then called it but it does not seem to work. Sorry for the long code I appreciate any help!
The first working code without multiprocessing
for z in range(8):
for q in range(100):
time_re = time_re + 3000
tk.after(time_re,appender)
tk.after(time_re,restart)
ava(avaR1)
while True:
time_steps = range(0,iterations+1)
B = Beta.get()
G = Gamma.get()
D = Diff.get()
M = Mor.get()
steps_x_or_y = np.random.rand(n)
steps_x = steps_x_or_y < D/2
steps_y = (steps_x_or_y > D/2) & (steps_x_or_y < D)
nx = (x + np.sign(np.random.randn(n)) * steps_x) % l
ny = (y + np.sign(np.random.randn(n)) * steps_y) % l
for i in np.where( (S==1) & ( np.random.rand(n) < B ))[0]: # loop over infecting agents
S[(x==x[i]) & (y==y[i]) & (S==0)] = 1 # Susceptiples together with infecting agent becomes infected
S[ (S==1) & (np.random.rand(n) < G) ] = 2 # Recovery
S[ (S==1) & (np.random.rand(n) < M) ] = 3 # Death
nrInf1 = sum(S==1)
nrSus.append(sum(S==0))
nrInf.append(sum(S==1))
nrRec.append(sum(S==2))
nrRec1 = sum(S==2)
nrDea = sum(S == 3)
iterations += 1
tk.update()
tk.title('Infected:' + str(np.sum(S==1)))
x = nx # Update x
y = ny # Update y
The second code with me trying to change it to multiprocessing
def main1(i):
# Physical parameters of the system
x = np.floor(np.random.rand(n)*l) # x coordinates
y = np.floor(np.random.rand(n)*l) # y coordinates
S = np.zeros(n) # status array, 0: Susceptiple, 1: Infected, 2: recovered
I = np.argsort((x-l/2)**2 + (y-l/2)**2)
S[I[1:initial_infected]] = 1 # Infect agents that are close to center
nrRec1 = 0
nrDea = []
time_re = 0
particles = []
R = .5 # agent plot radius
nx = x # udpated x
ny = y # updated y
def restart():
global S
I = np.argsort((x-l/2)**2 + (y-l/2)**2)
S = np.zeros(n)
S[I[1:initial_infected]] = 1
rest = Button(tk, text='Restart',command= restart)
rest.place(relx=0.05, rely=.85, relheight= 0.12, relwidth= 0.15 )
def ava(k,o):
global b
k.append(sum(o)/3)
Beta.set(b) # Parameter slider for mortality rate
b += 0.03125
#bSaver.append(b)
def appender(o):
nrDea1.append(nrDea)
o.append(nrRec1)
for j in range(n): # Generate animated particles in Canvas
particles.append( canvas.create_oval( (x[j] )*res/l,
(y[j] )*res/l,
(x[j]+2*R )*res/l,
(y[j]+2*R )*res/l,
outline=ccolor[0], fill=ccolor[0]) )
if i == 1:
b=0
for z in range(3):
for q in range(3):
time_re = time_re + 1000
tk.after(time_re,appender(nrSRec1))
tk.after(time_re,restart)
tk.after(9000,ava(avaR1,nrSRec1))
elif i == 2:
b=0.25
for z in range(3):
for q in range(3):
time_re = time_re + 1000
tk.after(time_re,appender(nrSRec2))
tk.after(time_re,restart)
tk.after(9000,ava(avaR2,nrSRec2))
elif i == 3:
b=.50
for z in range(3):
for q in range(3):
time_re = time_re + 1000
tk.after(time_re,appender(nrSRec3))
tk.after(time_re,restart)
tk.after(9000,ava(avaR3,nrSRec3))
else:
b=.75
for z in range(3):
for q in range(3):
time_re = time_re + 1000
tk.after(time_re,appender(nrSRec4))
tk.after(time_re,restart)
tk.after(9000,ava(avaR4,nrSRec4))
while True:
B = Beta.get()
G = Gamma.get()
D = Diff.get()
steps_x_or_y = np.random.rand(n)
steps_x = steps_x_or_y < D/2
steps_y = (steps_x_or_y > D/2) & (steps_x_or_y < D)
nx = (x + np.sign(np.random.randn(n)) * steps_x) % l
ny = (y + np.sign(np.random.randn(n)) * steps_y) % l
for i in np.where( (S==1) & ( np.random.rand(n) < B ))[0]: # loop over infecting agents
S[(x==x[i]) & (y==y[i]) & (S==0)] = 1 # Susceptiples together with infecting agent becomes infected
S[ (S==1) & (np.random.rand(n) < G) ] = 2 # Recovery
nrDea= sum(S == 3)
nrRec1 = sum(S==2)
tk.update()
tk.title('Infected:' + str(np.sum(S==1)))
x = nx # Update x
y = ny # Update y
if __name__ == '__main__':
p1=mp.Process(target=main1, args=(1,))
p1.start()
p2=mp.Process(target=main1, args=(2,))
p2.start()
p3=mp.Process(target=main1, args=(3,))
p3.start()
p4=mp.Process(target=main1, args=(4,))
p4.start()
joinedList = avaR1+avaR2+avaR3+avaR4
print(joinedList)
Tk.mainloop(canvas)

List append MemoryError

So I have this piece of code I'm trying to make generate level layouts for a grid of rooms. The first time through the mainloop it runs perfectly it runs and does exactly what it should but the second time through it pauses just after the first print error and gives me the attached error and I cant figure out what's wrong with it.
(the y/n prompt is only to slow down the program so I can see what's happening)
userInput = ""
roomChance = 0.5
world = [[0,0,0], \
[0,1,0], \
[0,0,0]]
possibleWorld = []
newX = []
def check_neighbours(xy):
possibleWorld.clear()
yLoops = 0
for y in xy:
print(" y:", y)
xLoops = 0
for x in y:
print(" x:", x)
#Check left cell
if(xLoops-1 >= 0):
if(y[xLoops-1] == 1):
possibleWorld.append([xLoops, yLoops])
print("x-1:", y[xLoops-1])
#Check right cell
if(xLoops+1 < len(y)):
if(y[xLoops+1] == 1):
possibleWorld.append([xLoops, yLoops])
print("x+1:", y[xLoops+1])
#Check above cell
if(yLoops-1 >= 0):
if(xy[yLoops-1][xLoops] == 1):
possibleWorld.append([xLoops, yLoops])
print("y-1:", xy[yLoops-1][xLoops])
#Check above cell
if(yLoops+1 < len(xy)):
if(xy[yLoops+1][xLoops] == 1):
possibleWorld.append([xLoops, yLoops])
print("y+1:", xy[yLoops+1][xLoops])
print("\n")
xLoops += 1
yLoops += 1
def assign_neighbours(possible, world, chance):
for i in possible:
if(random.random() < chance):
world[i[1]][i[0]] = 1
possible.clear()
def border_expand(world):
for x in world[0]:
if(x == 1):
for i in world[0]:
newX.append(0)
world.insert(0, newX)
newX.clear
break
def print_world(world):
for y in world:
print(y)
# ==================== Mainloop ====================
while(True):
userInput = input(print("Generate Level? Y/N?"))
check_neighbours(world)
print(possibleWorld)
assign_neighbours(possibleWorld, world, roomChance)
print_world(world)
border_expand(world)
print("\n")
print_world(world)
File "C:\Users\Potato\Desktop\Level gen_query.py", line 96, in <module>
border_expand(world)
File "C:\Users\Potato\Desktop\Level gen_query.py", line 67, in border_expand
newX.append(0)
MemoryError```
You're not calling newX.clear, so it is continually growing. When you run world.insert(0, newX) you are inserting a reference to newX into world[0], even if you did call newX.clear() you would not get the behaviour you want as the first element in world would be empty.
You need to create a new list on every call to border_expand so that it is a new list every time
def border_expand(world):
newX = []
for x in world[0]:
if(x == 1):
for i in world[0]:
newX.append(0)
world.insert(0, newX)
break

Why is my loop still running? (Python Zelle Graphics)

I'm trying to figure out why the while loop in one of my functions is still running even after the points in my graphics are equal, which is when I set it to stop. Is there anything I'm doing wrong? I've tried to switch other things around to get it to work but no luck.
It's for a game--when the character reaches the endbox the loop needs to break, but it isn't doing that after I explicitly coded it to. It's in the second function I have:
from graphics import *
def field():
#creating the window
win = GraphWin('The Field',400,400)
win.setBackground('white')
#drawing the grid
boxlist = []
for i in range(0,400,40):
for j in range(0,400,40):
box = Rectangle(Point(i,j),Point(i+40,j+40))
box.setOutline('light gray')
box.draw(win)
boxlist.append(box)
#creating other boxes
startbox = Rectangle(Point(0,0),Point(40,40))
startbox.setFill('lime')
startbox.setOutline('light gray')
startbox.draw(win)
endbox = Rectangle(Point(360,360),Point(400,400))
endbox.setFill('red')
endbox.setOutline('light gray')
endbox.draw(win)
boxlist.append(startbox)
boxlist.append(endbox)
#creating Pete
pete = Rectangle(Point(2,2),Point(38,38))
pete.setFill('gold')
pete.draw(win)
return win,boxlist,pete
def move(win2,boxlist,pete,endbox):
peteloc = pete.getCenter()
#creating loop to move pete
while peteloc != endbox.getCenter():
click = win2.getMouse()
x = click.getX()
y = click.getY()
peteloc = pete.getCenter()
petex = peteloc.getX()
petey = peteloc.getY()
#moving pete
if x>=petex+20 and y<=petey+20 and y>=petey-20:
pete.move(40,0)
elif x<=petex-20 and y<=petey+20 and y>=petey-20:
pete.move(-40,0)
elif y>=petey+20 and x<=petex+20 and x>=petex-20:
pete.move(0,40)
elif y<=petey-20 and x<=petex+20 and x>=petex-20:
pete.move(0,-40)
peteloc = pete.getCenter()
# The main function
def main():
win2,boxlist,pete = field()
endbox = boxlist[len(boxlist)-1]
move(win2,boxlist,pete,endbox)
main()
I think maybe it is caused by precision of float. I guess pete.getCenter() and endbox.getCenter() are something like [float, float], you should avoid using != between float, such as 1.0000001 is not equal to 1.
So even if the character reaches the endbox, the position will still get a little float bias.
So you can change a != b to abs(a - b) > acceptable_error when the error is acceptable. Sample code is like:
# while peteloc != endbox.getCenter():
while abs(peteloc.getX() - endbox.getCenter().getX()) > 0.01 and abs(peteloc.getY() - endbox.getCenter().getY()) > 0.01:
Hope that will help you.
Zelle graphics Point objects don't appear to ever compare as equal:
>>> from graphics import *
>>> a = Point(100, 100)
>>> b = Point(100, 100)
>>> a == b
False
>>>
We have to extract coordinates and do our own comparison. Although #recnac provides a workable solution (+1), I'm going to suggest a more general one. We'll create a distance() method that's valid for any object that inherits from _BBox, which includes Rectangle, Oval, Circle and Line:
def distance(bbox1, bbox2):
c1 = bbox1.getCenter()
c2 = bbox2.getCenter()
return ((c2.getX() - c1.getX()) ** 2 + (c2.getY() - c1.getY()) ** 2) ** 0.5
We can now measure the distance between objects, horizontally, vertically and diagonally. Since your boxes are moving twenty pixels at a time, we can assume that if they are withing 1 pixel of each other, they are in the same location. Your code rewritten to use the distance() method and other tweaks:
from graphics import *
def field(win):
# drawing the grid
boxlist = []
for i in range(0, 400, 40):
for j in range(0, 400, 40):
box = Rectangle(Point(i, j), Point(i + 40, j + 40))
box.setOutline('light gray')
box.draw(win)
boxlist.append(box)
# creating other boxes
startbox = Rectangle(Point(0, 0), Point(40, 40))
startbox.setFill('lime')
startbox.setOutline('light gray')
startbox.draw(win)
boxlist.append(startbox)
endbox = Rectangle(Point(360, 360), Point(400, 400))
endbox.setFill('red')
endbox.setOutline('light gray')
endbox.draw(win)
boxlist.append(endbox)
# creating Pete
pete = Rectangle(Point(2, 2), Point(38, 38))
pete.setFill('gold')
pete.draw(win)
return boxlist, pete
def distance(bbox1, bbox2):
c1 = bbox1.getCenter()
c2 = bbox2.getCenter()
return ((c2.getX() - c1.getX()) ** 2 + (c2.getY() - c1.getY()) ** 2) ** 0.5
def move(win, pete, endbox):
# creating loop to move pete
while distance(pete, endbox) > 1:
click = win.getMouse()
x, y = click.getX(), click.getY()
peteloc = pete.getCenter()
petex, petey = peteloc.getX(), peteloc.getY()
# moving pete
if x >= petex + 20 and petey - 20 <= y <= petey + 20:
pete.move(40, 0)
elif x <= petex - 20 and petey - 20 <= y <= petey + 20:
pete.move(-40, 0)
elif y >= petey + 20 and petex - 20 <= x <= petex + 20:
pete.move(0, 40)
elif y <= petey - 20 and petex - 20 <= x <= petex + 20:
pete.move(0, -40)
# The main function
def main():
# creating the window
win = GraphWin('The Field', 400, 400)
win.setBackground('white')
boxlist, pete = field(win)
endbox = boxlist[-1]
move(win, pete, endbox)
main()

Python find closest turtle via mouse click

I'm in the process of creating a minesweeper style game using a turtle-based grid setup. I need to find the closest cell within the grid and reveal the icon located under it whether that be a bomb or a number icons. I'm not looking to make it exact, I just need the mouse click to find the nearest cell in the grid even if the click isn't directly on the board. Currently my code only reveals the icon of the last turtle created on the board and then does nothing else with further clicks.
What can I do to make it recognize the real closest click and do it multiple times until the last bomb is found?
import random
import turtle
import cell
class Game:
def __init__(self, size):
registershapes()
self.__boardsize = size
self.__boardlist = []
self.__bombnum = 0
self.__probe = 0
self.__probelist = []
offset = (size-1) * 17
for x in range(size):
for y in range(size):
t = cell.Cell(x,y)
t.up()
t.shape('question.gif')
t.goto(y*34-offset, offset-x*34)
self.__boardlist.append(t)
def hideMines(self, num):
if num > self.__boardsize ** 2:
return False
self.__bombnum = num
self.__rnums = []
i = 0
while i < self.__bombnum:
currentnum = random.randrange(0, (self.__boardsize**2) - 1)
if currentnum not in self.__rnums:
self.__rnums.append(currentnum)
i += 1
return True
def probe(self, x, y):
for t in self.__boardlist:
pos = t.position()
distx = abs(x - pos[0])
disty = abs(y - pos[1])
distfinal = (distx ** 2 + disty ** 2) ** 0.5
curdist = 0
if curdist < distfinal:
curdist = distfinal
closest = t
if closest in self.__probelist:
return (self.__probe, self.__bombnum)
elif closest in self.__rnums:
closest.shape("bomb.gif")
self.__bombnum -= 1
self.__probe += 1
self.__probelist.append(closest)
return (self.__probe, self.__bombnum)
else:
closest.shape("0.gif")
self.__probe += 1
self.__probelist.append(closest)
return (self.__probe, self.__bombnum)
def registershapes():
wn = turtle.Screen()
wn.register_shape('0.gif')
wn.register_shape('1.gif')
wn.register_shape('2.gif')
wn.register_shape('3.gif')
wn.register_shape('4.gif')
wn.register_shape('5.gif')
wn.register_shape('6.gif')
wn.register_shape('7.gif')
wn.register_shape('8.gif')
wn.register_shape('9.gif')
wn.register_shape('bomb.gif')
wn.register_shape('question.gif')
I believe you're approaching this problem the wrong way. You're activating screen.onclick() and trying to map it to a turtle. Instead, activate turtle.onclick() on the individual turtles, deactivating it when a turtle is selected. Then you don't have to search for the turtle in question, and not actively ignore turtles that have already been selected.
Below is my rework of your code from this and your previous question into an example you can run. I had to guess about the definition of the Cell class:
from turtle import Turtle, Screen
import random
class Cell(Turtle):
def __init__(self, number):
super().__init__("question.gif")
self.__number = number
self.penup()
def number(self):
return self.__number
class Game:
def __init__(self, size):
registershapes()
self.__boardsize = size
self.__boardlist = []
self.__bombnum = 0
self.__probe = 0
self.__rnums = None
offset = (size - 1) * 17
for y in range(size):
for x in range(size):
t = Cell(x + y * size)
t.goto(x * 34 - offset, offset - y * 34)
t.onclick(lambda x, y, self=t: closure(self))
self.__boardlist.append(t)
def hideMines(self, num):
if num > self.__boardsize ** 2:
return False
self.__bombnum = num
self.__rnums = []
i = 0
while i < self.__bombnum:
currentnum = random.randrange(0, self.__boardsize ** 2 - 1)
if currentnum not in self.__rnums:
self.__rnums.append(currentnum)
i += 1
return True
def probe(self, closest):
closest.onclick(None)
if closest.number() in self.__rnums:
closest.shape("bomb.gif")
self.__bombnum -= 1
else:
closest.shape("0.gif")
self.__probe += 1
return (self.__probe, self.__bombnum)
def registershapes():
screen.register_shape('0.gif')
# ...
screen.register_shape('bomb.gif')
screen.register_shape('question.gif')
def closure(closest):
_, rem = mine.probe(closest)
if rem == 0:
over = screen.textinput("Text Input", "Would you like to play again? (Y)es or (N)o")
if over.upper() == 'Y':
main()
else:
screen.bye()
def main():
global mine
board = screen.numinput("Numeric Input", "Enter desired board size: ")
mine = Game(int(board))
nummine = screen.numinput("Numeric Input", "Enter desired number of mines: ")
mine.hideMines(int(nummine))
screen = Screen()
mine = None
main()
screen.mainloop()

Python Tkinter - How to make certain code use less memory

I am programming an Othello game in a GUI. I have begun working on the animations that flip certain tiles, which is here. My computer(s) will start choking when the when the amount of tiles on the board becomes larger. I do not know what to do to simplify this code or use less memory. (I can use an automove key I have enabled to finish the game at light speed, without the animations. That works fine.) Here is the definition I am using to flip the tiles.
def animateFlips(self, i):
self._canvas.delete(tkinter.ALL)
column_width = self._canvas.winfo_width()/Othello.COLUMNS
row_height = (self._canvas.winfo_height()-self._scoreBoard)/Othello.ROWS
newBoard = self._game.board
animatedTileCoords = []
color = ''
oppcolor = ''
if self._game.turn == 2:
color = 'black'
oppcolor = 'white'
elif self._game.turn == 1:
color = 'white'
oppcolor = 'black'
for x in range(Othello.COLUMNS):
for y in range(Othello.ROWS):
x1 = x * column_width
y1 = y * row_height
x2 = x1 + column_width
y2 = y1 + row_height
self._canvas.create_rectangle(x1,y1,x2,y2)
if self._game.board[x][y] == 1:
self._canvas.create_oval(x1,y1,x2,y2,fill='black')
elif self._game.board[x][y] == 2:
self._canvas.create_oval(x1,y1,x2,y2,fill='white')
elif self._game.board[x][y] == 3 or self._game.board[x][y] == 4:
animatedTileCoords.append([x,y])
for x, y in animatedTileCoords:
x1 = x * column_width
y1 = y * row_height
x2 = x1 + column_width
y2 = y1 + row_height
if i == 1:
self._canvas.create_oval(x1,y1,x2,y2,fill=oppcolor)
self._canvas.after(50, lambda: self.animateFlips(2))
elif i == 2:
self._canvas.create_oval(x1 + (column_width/4),y1,x1 + (3*column_width/4),y2,fill=oppcolor)
self._canvas.after(50, lambda: self.animateFlips(3))
elif i == 3:
self._canvas.create_oval(x1 + (column_width/2),y1,x1 + (column_width/2),y2,fill=oppcolor)
self._canvas.after(50, lambda: self.animateFlips(4))
elif i == 4:
self._canvas.create_oval(x1 + (column_width/4),y1,x1 + (3*column_width/4),y2,fill=color)
self._canvas.after(50, lambda: self.animateFlips(5))
elif i == 5:
self._canvas.create_oval(x1,y1,x2,y2,fill=color)
newBoard[x][y] = Othello.nextTurn(self._game.turn)
self._game = GameState(board = newBoard, turn = self._game.turn, skipped = 0)
self.displayMoves()
self.displayButtons()
self.displayInfo()
self.displayWinner(self.getWinner())
self._canvas.bind('<Configure>',self.draw_handler)
The simplest solution is to not delete and recreate the game pieces on each iteration. Draw them once, and then use the itemconfig method to alter the appearance of the game pieces.
Even better would be to create a GamePiece class so that each piece is represented by this class. Then, move the animation function inside the class. This will make your main logic much easier to understand.

Categories