Python - Change made to class in array not saved - python

I've been working all day on a bit of code for a maze generation algorithm. In this snippet:
if nextCoords[2] == '<':
cells[x][y].l = False
x, y = nextCoords[0], nextCoords[1]
cells[x][y].r = False
The first line of the if statement, cells[x][y].l = False executes as expected, but for some reason cells[x][y].r = False does not keep the change made.
Here's the full code (with some prints from hopeless debugging):
import random
class Cell():
def __init__(self, x, y):
self.x = x
self.y = y
self.visited = False
self.isStart = False
self.isEnd = False
self.isNormal = True
self.u = True
self.d = True
self.l = True
self.r = True
def __str__(self):
# For console applications
return "{0}{1}{2}{3}{4}{5}{6}".format(
'^' if not self.u else ' ',
'v' if not self.d else ' ',
'<' if not self.l else ' ',
'>' if not self.r else ' ',
'+' if self.isStart else '',
'#' if self.isEnd else '',
' ' if self.isNormal else ''
)
def __repr__(self):
return self.__str__()
def mazegen(w=3, h=3, printOut=False):
x = 0
y = 0
cells = [[Cell(x, y) for x in range(w)] for y in range(h)]
stack = []
cells[x][y].isStart = True
cells[x][y].isNormal = False
while True:
allVisited = True
for i in cells:
for j in i:
if not j.visited:
allVisited = False
if allVisited:
finalCell = cells[ stack[-1][0] ][ stack[-1][1] ]
finalCell.isNormal = False
finalCell.isEnd = True
break
cells[x][y].visited = True
choices = []
if x > 0:
choices.append((x-1, y, '<'))
if x < w-1:
choices.append((x+1, y, '>'))
if y > 0:
choices.append((x, y-1, '^'))
if y < h-1:
choices.append((x, y+1, 'v'))
betterChoices = []
for c in choices:
if not cells[ c[0] ][ c[1] ].visited:
betterChoices.append(c)
if betterChoices != []:
nextCoords = random.choice(betterChoices)
else:
popped = stack.pop()
x, y = popped[0], popped[1]
continue
stack.append((x, y))
print(nextCoords[2])
if nextCoords[2] == '^':
cells[x][y].u = False
print("This cell is now {}.".format(cells[x][y]))
x, y = nextCoords[0], nextCoords[1]
cells[x][y].d = False
print("The next cell is {}.".format(cells[x][y]))
if nextCoords[2] == 'v':
cells[x][y].d = False
print("Old: ({0}, {1})".format(x, y))
print(cells[x][y])
x, y = nextCoords[0], nextCoords[1]
print("New: ({0}, {1})".format(x, y))
print(cells[x][y])
cells[x][y].u = False
print(cells[x][y])
if nextCoords[2] == '<':
cells[x][y].l = False
x, y = nextCoords[0], nextCoords[1]
cells[x][y].r = False
if nextCoords[2] == '>':
cells[x][y].r = False
x, y = nextCoords[0], nextCoords[1]
cells[x][y].l = False
print("Moved {}\n".format(nextCoords[2]))
if printOut:
for i in cells:
for j in i:
print("| ", end='')
print(j, end=' | ')
print()
print("----------"*w)
return cells

after i cleaned up your code it's now working and looking fine :]
import pygame, sys, random
class Cell:
visited=isStart=isEnd=False
u=d=l=r=isNormal=True
def __init__(self,x,y): self.x,self.y = x,y
def mazegen(w,h):
x,y = 0,0
cells = [[Cell(x,y) for y in range(h)] for x in range(w)]
stack = []
cells[x][y].isStart = True
cells[x][y].isNormal = False
while True:
allVisited = True
for i in cells:
for j in i:
if not j.visited: allVisited = False
if allVisited:
finalCell = cells[ stack[-1][0] ][ stack[-1][1] ]
finalCell.isNormal = False
finalCell.isEnd = True
break
cells[x][y].visited = True
choices = []
if x>0: choices.append((x-1, y, '<'))
if x<w-1: choices.append((x+1, y, '>'))
if y>0: choices.append((x, y-1, '^'))
if y<h-1: choices.append((x, y+1, 'v'))
betterChoices = []
for c in choices:
if not cells[c[0]][c[1]].visited: betterChoices.append(c)
if betterChoices != []:
nextCoords = random.choice(betterChoices)
else:
popped = stack.pop()
x,y = popped[0],popped[1]
continue
stack.append((x,y))
if nextCoords[2] == '^':
cells[x][y].u = False
x,y = nextCoords[0], nextCoords[1]
cells[x][y].d = False
if nextCoords[2] == 'v':
cells[x][y].d = False
x,y = nextCoords[0], nextCoords[1]
cells[x][y].u = False
if nextCoords[2] == '<':
cells[x][y].l = False
x,y = nextCoords[0], nextCoords[1]
cells[x][y].r = False
if nextCoords[2] == '>':
cells[x][y].r = False
x,y = nextCoords[0], nextCoords[1]
cells[x][y].l = False
return cells
BLACK = (0,0,0)
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
screen = pygame.display.set_mode((400,400))
pygame.display.set_caption("Maze Generator!")
cells = mazegen(10,10)
while True:
key = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type==pygame.QUIT: pygame.quit(); sys.exit()
if event.type==pygame.KEYDOWN:
if key[pygame.K_LALT] and event.key==pygame.K_F4: pygame.quit(); sys.exit() # alt + f4
screen.fill(BLUE)
for i in cells:
for cell in i:
img = pygame.Surface((20,20))
img.fill(WHITE)
if cell.u:pygame.draw.line(img,BLACK,(0,0),(20,0))
if cell.d: pygame.draw.line(img,BLACK,(0,20),(20,20))
if cell.l: pygame.draw.line(img,BLACK,(0,0),(0,20))
if cell.r: pygame.draw.line(img,BLACK,(20,0),(20,20))
screen.blit(img,(cell.x*20, cell.y*20))
pygame.display.flip()
also here's my really compact example. (i use pygame just to save it as an image. lol)
import pygame, random
def maze(*gs):
gs = (gs[0]+3-gs[0]%4,gs[1]+3-gs[1]%4) # rounding grid size for cleaner presentation
adjacent = lambda x,y: [(a,b) for a,b in ((x-2,y),(x+2,y),(x,y-2),(x,y+2)) if (a,b) not in tiles and a+1 and b+1 and a<gs[0] and b<gs[1]]
pos = (gs[0]//2,gs[1]//2); tiles, points, direction = [pos], [], (0,0)
for l in range(((gs[0]-1)//2)*((gs[1]-1)//2)-1): # total loops in algorithm
adj = adjacent(*pos) # get available adjacents
for i in points[::-1]:
if adj: break # we have adjacents, we don't need to backtrack
adj = adjacent(*i) # check if corner has spare adjacents
if adj: points, pos = points[:points.index(i)], i # if so, remove corner, backtrack pos
rand = random.choice(adj); new_dir = rand[0]-pos[0], rand[1]-pos[1] # get random dir
if new_dir != direction and len(adj)>1: points += [pos] # corner and more adj remain
tiles, pos, direction = tiles+[(rand[0]-new_dir[0]//2,rand[1]-new_dir[1]//2),rand], rand, new_dir # add path, move in direction
pygame.init() # lets use pygame
surface = pygame.Surface(gs); surface.fill((0,0,0)) # create black image
for i in tiles: surface.set_at(i,(255,255,255)) # add white path
pygame.image.save(surface,"maze.png") # save as png
maze(100,100) # create 100x100 pixel maze

Related

Optimizing Negamax Function with 5x5 Hexapawn

I need to improve the speed of this program, because at the moment it is pretty slow. I know that representing game states in binary can be very effective, however, I don't know how to do that. I have also tried using numba, however that seems to make it slower. I have attached the code below. Thank you to anyone who can help!
import pygame, sys, time, hashlib
from copy import deepcopy
pygame.init()
red = pygame.Color(255,0,0)
white = pygame.Color(255,255,255)
black = pygame.Color(0,0,0)
pygame.display.set_caption('Hexapawn AI')
width, height = 700,700
game_window = pygame.display.set_mode((width, height))
def set_pawns():
global game_window, board
for y in range(5):
for x in range(5):
if board[y][x] == 1:
game_window.blit( blue_pawn, ( (width/5)*x, (height/5)*(4-y) ))
if board[y][x] == -1:
game_window.blit( red_pawn, ( (width/5)*x , (height/5)*(4-y) ))
def build_lines():
global game_window
for x in range(1,5):
pygame.draw.line(game_window, black, (width/5 * x, 0), (width/5 * x, height), 7)
pygame.draw.line(game_window, black, (0, height/5 * x), (width, height/5 * x), 7)
def get_possible_moves(board, player):
possible_moves = []
forward = 1 if player == 1 else -1
opponent = -1 if player == 1 else 1
for y in range(5):
for x in range(5):
if board[y][x] != player:
continue
if x-1 >= 0 and y+forward < 5 and board[y+forward][x-1] == opponent:
possible_moves.append([x,y,x-1,y+forward])
if x+1 < 5 and y+forward < 5 and board[y+forward][x+1] == opponent:
possible_moves.append([x,y,x+1,y+forward])
if (y+1 < 5 and player == 1) or (y+1 > -1 and player == -1):
if board[y+forward][x] == " ":
possible_moves.append([x,y,x,y+forward])
return possible_moves
def make_move(board,move,player):
global game_window, width, height
game_window.fill(white)
build_lines()
board[move[1]][move[0]] = " "
board[move[3]][move[2]] = player
set_pawns()
def neg_make_move(board, move, player):
x1, y1, x2, y2 = move
board = deepcopy(board)
board[y1][x1] = " "
board[y2][x2] = player
return board
def check_for_win(board,player):
if player == -1:
if -1 in board[0]:
return True
if get_possible_moves(board,1) == []:
return True
elif player == 1:
if 1 in board[4]:
return True
if get_possible_moves(board,-1) == []:
return True
return False
TRANSPOSITION_TABLE = {}
def state_hash(board):
serialized = str(board).encode()
return hashlib.sha256(serialized).hexdigest()
def store(table, board, alpha, beta, best, depth):
state = state_hash(board)
if best[1] <= alpha:
flag = 'UPPERCASE'
elif best[1] >= beta:
flag = 'LOWERCASE'
else:
flag = 'EXACT'
table[state] = [best, flag, depth]
def negamax(board, depth, turn, alpha, beta):
alpha_org = alpha
state = state_hash(board)
if state in TRANSPOSITION_TABLE:
tt_entry = TRANSPOSITION_TABLE[state]
if tt_entry[2] >= depth:
if tt_entry[1] == 'EXACT':
return tt_entry[0]
elif tt_entry[1] == 'LOWERCASE':
alpha = max(alpha, tt_entry[0][1])
elif tt_entry[1] == 'UPPERCASE':
beta = min(beta, tt_entry[0][1])
if alpha >= beta:
return tt_entry[0]
if check_for_win(board, -turn):
return None, -(25+depth)
if depth == 0:
return get_possible_moves(board,turn)[0], (depth)
best_score = -200
for move in get_possible_moves(board,turn):
new_board = neg_make_move(board, move, turn)
score = -negamax(new_board, depth - 1, -turn, -beta, -alpha)[1]
alpha = max(alpha,score)
if score > best_score:
best_score, best_move = score, move
if alpha >= beta:
break
store(TRANSPOSITION_TABLE, board, alpha_org, beta, [best_move,best_score], depth)
return best_move, best_score
# Build board
board = [[1 for x in range(5)]]
for x in range(3):
board.append([" " for x in range(5)])
board.append([-1 for x in range(5)])
game_window.fill(white)
# Draw game board lines
build_lines()
# Load sprites with correct sizes
tile_size = (width/5,height/5)
blue_pawn = pygame.transform.scale(pygame.image.load("blue_pawn.png"), tile_size)
red_pawn = pygame.transform.scale(pygame.image.load("red_pawn.png"), tile_size)
# Draw the pawns to the board
set_pawns()
pygame.display.update()
while True:
for event in pygame.event.get():
# if user clicks the X or they type esc then the screen will close
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
start = time.time()
move = negamax(board,12,1,-10000,10000)[0]
print(f"Blue move took {time.time()-start} seconds to calculate.")
make_move(board,move,1)
pygame.display.update()
if check_for_win(board,1):
print("Blue Wins!")
pygame.quit()
sys.exit()
time.sleep(1)
start = time.time()
move = negamax(board,12,-1,-10000,10000)[0]
print(f"Red move took {time.time()-start} seconds to calculate.")
make_move(board,move,-1)
pygame.display.update()
if check_for_win(board,-1):
print("Red Wins!")
pygame.quit()
sys.exit()
pygame.display.update()
time.sleep(1)

Attribute Error: List object has no attribute CheckClick

In the Swap function, I am checking under some index a button class instance, which I checked using print statements, but for some reason it still gives me an error saying that it has no such attribute check click. Any tips on formatting are also welcome, I am just a beginner. I am using three different arrays to hold various instances, values and coordinates for each corresponding array position. I am trying to make a sort of match 3 game. Thanks for any help
from os import access
import pygame,sys
from random import randrange
import numpy
#Constants
Columns =5
Rows = 5
X,Y = 320,0
class Button:
def __init__(self,x,y,image,scale):
self.x = x
self.y=y
self.image = pygame.transform.scale(image,(scale,scale))
self.scale = scale
self.rect = self.image.get_rect(topleft=(x,y))
self.clicked = False
self.Action = False
def Draw(self):
Win.blit(self.image,(self.x,self.y))
def CheckClick(self):
isClicked = False
mousepos= pygame.mouse.get_pos()
if self.rect.collidepoint(mousepos):
if pygame.mouse.get_pressed()[0] ==1 and self.clicked == False:
self.clicked = True
self.Action = True
if pygame.mouse.get_pressed()[0] ==0:
self.clicked = False
return self.Action
#Win
WinWidth, WinHeight = 1280,800
Win = pygame.display.set_mode((WinWidth,WinHeight))
#IMAGES
test_img = pygame.image.load("test.png")
red_img = pygame.image.load("Red.png")
green_img = pygame.image.load("green.png")
blue_img = pygame.image.load("blue.png")
#Board
Board = [[ randrange(0,3) for column in range(Columns)] for row in range(Rows) ]
BoardObjs = []
BoardXYs = [[None for column in range(Columns)]for row in range(Rows)]
#Fill BoardXYS
for k in range(len(Board)):
for j in range(len(Board[1])):
BoardXYs[k][j] = [X,Y]
X += 160
X = 320
Y += 160
for r in range(len(Board)):
for t in range(len(Board[1])):
if Board[r][t] == 0:
BoardObjs.append(Button(BoardXYs[r][t][0],BoardXYs[r][t][1],red_img,100))
if Board[r][t] == 1:
BoardObjs.append(Button(BoardXYs[r][t][0],BoardXYs[r][t][1],green_img,100))
if Board[r][t] == 2:
BoardObjs.append(Button(BoardXYs[r][t][0],BoardXYs[r][t][1],blue_img,100))
BoardObjs = [[BoardObjs[0],BoardObjs[1],BoardObjs[2],BoardObjs[3],BoardObjs[4]],
[BoardObjs[5],BoardObjs[6],BoardObjs[7],BoardObjs[8],BoardObjs[9]],
[BoardObjs[10],BoardObjs[11],BoardObjs[12],BoardObjs[13],BoardObjs[14]],
[BoardObjs[15],BoardObjs[16],BoardObjs[17],BoardObjs[18],BoardObjs[19]],
[BoardObjs[20],BoardObjs[21],BoardObjs[22],BoardObjs[23],BoardObjs[24]]]
print(len(Board))
print(len(BoardObjs))
#Images
img_0 = pygame.Rect(0,0,64,64)
TouchingReds = 0
def CheckMatches(Board):
VerticalMatch = False
HorizontalMatch = False
for m in range(len(Board)):
for n in range(len(Board[1])-2):
if Board[m][n]==Board[m][n+1]==Board[m][n+2]:
HorizontalMatch = True
Board[m][n] = None
Board[m][n+1] = None
Board[m][n+2] = None
BoardObjs[m][n] = None
BoardObjs[m][n+1] = None
BoardObjs[m][n+2] = None
for o in range(len(Board[1])-2):
for u in range(len(Board)):
if Board[o][u]==Board[o+1][u]==Board[o+2][u]:
VerticalMatch = True
Board[o][u] = None
Board[o+1][u] = None
Board[o+2][u] = None
BoardObjs[o][u] = None
BoardObjs[o+1][u] = None
BoardObjs[o+2][u] = None
def Draw(Board,BoardXYs):
DoAppend = True
Win.fill((255,255,255))
for y in range(len(BoardObjs)):
for u in range(len(BoardObjs[1])):
if BoardObjs[y][u] != None:
BoardObjs[y][u].Draw()
pygame.display.update()
def Swap():
FirstClick = False
for i in range(len(BoardObjs)):
for t in range(len(BoardObjs[1])):
if BoardObjs[i][t] != None:
if BoardObjs[i][t].CheckClick and FirstClick == True:
BoardObjs[num][num2]=BoardObjs[i][t]
BoardObjs[i][t]=Buffer
FirstClick = False
print(BoardObjs[i][t])
if BoardObjs[i][t] !=None:
if BoardObjs[i][t].CheckClick:
Buffer = BoardObjs[i]
num =i
num2 = t
FirstClick = True
#ZEROS - RED
#ONES - GREEN
#TWOS - BLUE
clock = pygame.time.Clock()
def GameLoop():
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
CheckMatches(Board)
Draw(Board,BoardXYs)
Swap()
pygame.quit()
sys.exit()
if __name__ == "__main__":
GameLoop()
The mistake is in the Swap() function. Buffer is assigned to an item in the grid (BoardObjs[i][t]=Buffer). So Buffer needs to be a Button object instead of a row (list of objects):
Buffer = BoardObjs[i]
Buffer = BoardObjs[i][t]
The initialization of the board can be simplified:
#Board
Board = [[randrange(0,3) for column in range(Columns)] for row in range(Rows) ]
BoardXYs = [[(j*160+320, k*160) for j in range(Columns)]for k in range(Rows)]
BoardObjs = []
for r in range(len(Board)):
BoardObjs.append([])
for t in range(len(Board[1])):
image = [red_img, green_img, blue_img][board[r][t]]
BoardObjs[-1].append(Button(*BoardXYs[r][t], image, 100))
The CheckClick function you added is a function, not an attribute. Make sure to put parentheses after the name, even if it takes no argument.
Try, BoardObjs[i][t].CheckClick()

Creating a surface with pygame but when I run program, nothing showing

I am making a menu for a chess game. Since I cannot create multiple pygame windows, I am attempting to create a surface on top of my game. However, when I click my trigger key to show the menu, nothing happens.
Here is the main file of my code:
import pygame as p
import ChessEngine
import os
from tkinter import *
import time
WIDTH = HEIGHT = 512
DIMENSION = 8
SQ_SIZE = HEIGHT//DIMENSION
MAX_FPS = 15
IMAGES = {}
def loadImages():
pieces = ['wp', 'wR', 'wN', 'wB', 'wK',
'wQ', 'bp', 'bR', 'bN', 'bB', 'bK', 'bQ']
for piece in pieces:
IMAGES[piece] = p.transform.scale(
p.image.load('Chess/Images/' + piece + '.png'), (SQ_SIZE, SQ_SIZE))
def main():
p.init()
screen = p.display.set_mode((WIDTH, HEIGHT))
clock = p.time.Clock()
screen.fill(p.Color("white"))
gs = ChessEngine.GameState()
validMoves = gs.getValidMoves()
moveMade = False
animate = False
loadImages()
running = True
sqSelected = ()
playerClicks = []
gameOver = False
CheckV = False
sidebar = False
while running:
for e in p.event.get():
if e.type == p.QUIT:
running = False
elif e.type == p.MOUSEBUTTONDOWN:
if not gameOver:
location = p.mouse.get_pos()
col = location[0]//SQ_SIZE
row = location[1]//SQ_SIZE
if sqSelected == (row, col):
sqSelected = ()
playerClicks = []
else:
sqSelected = (row, col)
playerClicks.append(sqSelected)
if len(playerClicks) == 2:
move = ChessEngine.Move(
playerClicks[0], playerClicks[1], gs.board)
for i in range(len(validMoves)):
if move == validMoves[i]:
gs.makeMove(validMoves[i])
moveMade = True
animate = True
sqSelected = ()
playerClicks = []
if not moveMade:
playerClicks = [sqSelected]
elif e.type == p.KEYDOWN:
if e.key == p.K_z:
gs.undoMove()
moveMade = True
animate = False
checkMate = False
staleMate = False
gameOver = False
if e.key == p.K_r:
gs = ChessEngine.GameState()
validMoves = gs.getValidMoves()
sqSelected = ()
playerClicks = []
moveMade = False
animate = False
checkMate = False
staleMate = False
gameOver = False
if e.key == p.K_s and sidebar == False: # show sidebar
print('show sidebar')
b = p.Surface((SQ_SIZE, SQ_SIZE))
b.set_alpha(255)
b.fill(p.Color('blue'))
screen.blit(b, (HEIGHT, WIDTH))
sidebar = True
elif e.key == p.K_s and sidebar == True: # show board
`print('hide sidebar')`
sidebar = False
if moveMade:
if animate:
animateMove(gs.moveLog[-1], screen, gs.board, clock)
validMoves = gs.getValidMoves()
if gs.inCheck():
CheckV = True
if CheckV == True:
CheckV = False
os.system("say 'check'")
moveMade = False
animate = False
drawGameState(screen, gs, validMoves, sqSelected)
if gs.checkMate:
gameOver = True
if gs.whitetoMove:
drawText(screen, ' Black wins by Checkmate')
else:
drawText(screen, ' White wins by Checkmate')
elif gs.staleMate:
gameOver = True
drawText(screen, 'Stalemate')
clock.tick(MAX_FPS)
p.display.flip()
def highlightSquares(screen, gs, validMoves, sqSelected):
if sqSelected != ():
r, c = sqSelected
if gs.board[r][c][0] == ('w' if gs.whitetoMove else 'b'):
s = p.Surface((SQ_SIZE, SQ_SIZE))
s.set_alpha(100)
s.fill(p.Color('blue'))
screen.blit(s, (c*SQ_SIZE, r*SQ_SIZE))
s.fill(p.Color('yellow'))
for move in validMoves:
if move.startRow == r and move.startCol == c:
screen.blit(s, (SQ_SIZE*move.endCol, SQ_SIZE*move.endRow))
def drawGameState(screen, gs, validMoves, sqSelected):
drawBoard(screen)
highlightSquares(screen, gs, validMoves, sqSelected)
drawPieces(screen, gs.board)
def drawBoard(screen):
global colors
colors = [p.Color("white"), p.Color("gray")]
for r in range(DIMENSION):
for c in range(DIMENSION):
color = colors[((r+c) % 2)]
p.draw.rect(screen, color, p.Rect(
c*SQ_SIZE, r*SQ_SIZE, SQ_SIZE, SQ_SIZE))
def drawPieces(screen, board):
for r in range(DIMENSION):
for c in range(DIMENSION):
piece = board[r][c]
if piece != "--":
screen.blit(IMAGES[piece], p.Rect(
c*SQ_SIZE, r*SQ_SIZE, SQ_SIZE, SQ_SIZE))
def animateMove(move, screen, board, clock):
global colors
dR = move.endRow - move.startRow
dC = move.endCol - move.startCol
framesPerSquare = 10
frameCount = (abs(dR) + abs(dC)) * framesPerSquare
for frame in range(frameCount + 1):
p.event.pump()
r, c = (move.startRow + dR * frame / frameCount,
move.startCol + dC*frame / frameCount)
drawBoard(screen)
drawPieces(screen, board)
color = colors[(move.endRow + move.endCol) % 2]
endSquare = p.Rect(move.endCol*SQ_SIZE,
move.endRow*SQ_SIZE, SQ_SIZE, SQ_SIZE)
p.draw.rect(screen, color, endSquare)
if move.pieceCaptured != '--':
screen.blit(IMAGES[move.pieceCaptured], endSquare)
screen.blit(IMAGES[move.pieceMoved], p.Rect(
c*SQ_SIZE, r*SQ_SIZE, SQ_SIZE, SQ_SIZE))
p.display.flip()
clock.tick(60)
def drawText(screen, text):
font = p.font.SysFont("Helvetica", 32, True, False)
textObject = font.render(text, 0, p.Color('Gray'))
textLocation = p.Rect(0, 0, WIDTH, HEIGHT).move(
WIDTH/2 - textObject.get_width()/2, HEIGHT/2 - textObject.get_height()/2)
screen.blit(textObject, textLocation)
textObject = font.render(text, 0, p.Color("Black"))
screen.blit(textObject, textLocation.move(2, 2))
if __name__ == '__main__':
main()
The menu portion is this bit:
if e.key == p.K_s and sidebar == False: # show sidebar
print('show sidebar')
b = p.Surface((SQ_SIZE, SQ_SIZE))
b.set_alpha(255)
b.fill(p.Color('blue'))
screen.blit(b, (HEIGHT, WIDTH))
sidebar = True
elif e.key == p.K_s and sidebar == True: # show board
`print('hide sidebar')`
sidebar = False
What am I doing wrong? Please help. Thanks.
screen.blit(b, (HEIGHT, WIDTH))
This bit of code places the top left corner of Surface "b" on the screen at the coordinates of the lower right corner of the screen. This means that the Surface is placed, but it isn't visible because it is entirely "offscreen."
Also!
b.set_alpha(255)
Is unnecessary, since fully opaque is the default for a Surface. No need to manually set it.

Python backtracking maze really slow

check the edit,
I wrote some code while watching The Coding Train on youtube.. the maze backtracking generator. The youtuber wrote the code in javascript and I tried to understand the code while writing in python. It seems he had to change the framerate because his program was so fast just to see the generating part. While mine after some 10ish squares it was already so slow.
It cant be an hardware problem, I've got an i5-4690K CPU and a good matching GPU, it must be something in the code! But I can't find what it is.
I rewatched the episodes so I could see what was wrong, but it seems I wrote everything just fine.
from tkinter import *
import math
import random
import time
# initialization canvas
root = Tk()
canvas = Canvas(root, width=400, height=400, bg="#333333")
canvas.pack()
# some global variables
w = 40;
cols = math.floor(int(canvas["width"])/w)
rows = math.floor(int(canvas["height"])/w)
grid = []
current = None
class Cell():
line_color = "#AAAAAA"
visited_color = "green"
visited = False
rectangle = None
def __init__(self, i, j):
self.i = i
self.j = j
self.wall = [True, True, True, True] # top , right, bottom, left
def __repr__(self):
return "({}, {})".format(self.i, self.j)
def draw_lines(self):
x = self.i*w
y = self.j*w
if self.visited :
self.rectangle = canvas.create_rectangle(x, y, x+w, y+w, fill="purple", outline="")
canvas.update()
if self.wall[0]:
canvas.create_line(x, y, x+w, y, fill=self.line_color)
else:
canvas.create_line(x, y, x+w, y, fill="purple")
if self.wall[1]:
canvas.create_line(x+w, y, x+w, y+w, fill=self.line_color)
else:
canvas.create_line(x+w, y, x+w, y+w, fill="purple")
if self.wall[2]:
canvas.create_line(x, y+w, x+w, y+w, fill=self.line_color)
else:
canvas.create_line(x, y+w, x+w, y+w, fill="purple")
if self.wall[3]:
canvas.create_line(x, y, x, y+w, fill=self.line_color)
else:
canvas.create_line(x, y, x, y+w, fill="purple")
def checkNeighbors(self):
neighbors = []
top = None
bottom = None
left = None
right = None
if index(self.i, self.j-1) != -1:
top = grid[index(self.i, self.j-1)]
if index(self.i, self.j+1) != -1:
bottom = grid[index(self.i, self.j+1)]
if index(self.i-1, self.j) != -1:
left = grid[index(self.i-1, self.j)]
if index(self.i+1, self.j) != -1:
right = grid[index(self.i+1, self.j)]
if top is not None and top.visited is False:
neighbors.append(top)
if right is not None and right.visited is False:
neighbors.append(right)
if bottom is not None and bottom.visited is False:
neighbors.append(bottom)
if left is not None and left.visited is False:
neighbors.append(left)
if len(neighbors) > 0:
r = random.randint(0, len(neighbors)-1)
return neighbors[r]
else:
return None
def removeWalls(a, b):
x = a.i - b.i
y = a.j - b.j
if x != 0:
if x == 1:
a.wall[3] = False
b.wall[1] = False
else:
a.wall[1] = False
b.wall[3] = False
if y != 0:
if y == 1:
a.wall[0] = False
b.wall[2] = False
else:
a.wall[2] = False
b.wall[0] = False
def index(i, j):
if j < 0 or j > rows - 1 or i < 0 or i > cols - 1:
return -1
return j + i * cols
def setup():
global current
for i in range(rows):
for j in range(cols):
cell = Cell(i, j)
grid.append(cell)
current = grid[0]
next_one = None
def draw():
global current
global next_one
stack = []
almost = False
while True:
current.visited = True
for cell in grid:
cell.draw_lines()
next_one = current.checkNeighbors()
if next_one:
stack.append(current)
removeWalls(current, next_one)
current = next_one
elif len(stack) > 0:
cell = stack.pop()
current = cell
for cell in grid:
print(cell.visited)
setup()
draw()
root.mainloop()
I'm sorry to put all the code, but I think all of it is relevant for what comes to performance, haven't put any useful comments, sorry I'm trying to become a better programmer and change that bad habit
BIG EDIT:
I tested to just draw my maze once I finished calculating it, and it takes less than a second, so I figure it has to be with the amount of widgets (lines) I'm creating..? How could I minimize the widgets so I could see the maze being created like I wanted to?
You draw lines even if they didn't change. Instead, draw only the changed cells.
Besides, you have endless loop. Even if stack contains no more elements, you don't stop. Here you should break the loop.
Here is an improvement:
def draw():
for cell in grid:
cell.draw_lines()
global current
global next_one
stack = []
almost = False
while True:
current.visited = True
next_one = current.checkNeighbors()
if next_one:
stack.append(current)
removeWalls(current, next_one)
current.draw_lines()
next_one.draw_lines()
current = next_one
elif len(stack) > 0:
cell = stack.pop()
current = cell
else:
break

Conway's game of life list index error

So I'm trying to make Conway's game of life in Python/pygame, and the first iteration of making the new grid works, but the second wont because of a list index out of range error. I have been trying to figure out what's wrong, but the list index shouldn't be out of range. This is my code, the mistake is supposedly in changevalue() but i suspect it isn't, since the first iteration works:
import pygame
import random
width = 400
height = 400
blocksize = 10
white = (255, 255, 255)
black = (0, 0, 0)
visual = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
IsOn = True
grid = []
templist = []
tempgrid = []
class square(object):
def __init__(self, x, y, alive):
self.x = x
self.y = y
self.alive = alive
for y in range(height/blocksize):
templist = []
for x in range(width/blocksize):
templist.append(square(x, y, random.choice([True, False, False, False])))
grid.append(templist)
def changevalue(cx, cy, cgrid):
neighbours = []
for dy in range(3):
ddy = dy - 1
for dx in range(3):
ddx = dx - 1
if not (dx - 1 == 0 and dy - 1 == 0):
#print cgrid[(cy + ddy)%len(cgrid)][(cx + ddx)%len(cgrid[y])].alive
#NO ERRORS
#print len(cgrid) > (cy + ddy)%len(cgrid), len(cgrid[y]) > (cx + ddx)%len(cgrid[cy])
#NO ERRORS
neighbours.append(cgrid[(cy + ddy)%len(cgrid)][(cx + ddx)%len(cgrid[cy])].alive)
return len(filter(lambda p: p == True, neighbours))
while IsOn:
for event in pygame.event.get():
if event.type == pygame.QUIT:
IsOn = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_c:
proceed = True
tempgrid = []
for times in range(len(grid)):
tempgrid.append([])
for ty in range(len(grid)):
for tx in range(len(grid[ty])):
if changevalue(tx, ty, grid) < 2 and grid[ty][tx].alive == True:
tempgrid[ty].append(square(tx, ty, False))
elif changevalue(tx, ty, grid) > 3 and grid[ty][tx].alive == True:
tempgrid[ty].append(square(tx, ty, False))
elif changevalue(tx, ty, grid) == 3 and grid[ty][tx].alive == False:
tempgrid[ty].append(square(tx, ty, True))
grid = list(tempgrid)
visual.fill(white)
for y in range(len(grid)):
for x in range(len(grid[y])):
if grid[y][x].alive == True:
pygame.draw.rect(visual, black, (grid[y][x].x*blocksize, grid[y][x].y*blocksize, blocksize, blocksize))
pygame.display.update()
clock.tick(2)
pygame.quit()
quit()
Thanks for your help!
You don't copy square which doesn't change value - so new rows have different length - and later you have problem with index
You need something like this
if changevalue ...:
...
elif changevalue ...:
...
elif changevalue ...:
...
else:
# copy other elements
tempgrid[ty].append(grid[ty][tx])

Categories