因此,我正在尝试为学校的一个项目创建一个带有关卡的迷宫游戏。该代码有点重复,对不起,我才刚刚开始使用pygame进行编码。运行时,程序应输出一个迷宫,一旦用户完成,该迷宫将移至下一个级别-每个级别都是随机生成的。但是,只有第一个关卡可以正确显示,其余的关卡似乎是一个网格-这让我认为游戏正在旧版本上创建一个新的迷宫。
我粘贴了以下代码-很多东西与登录部分没有多大关系,因为我只是在尝试许多不同的事情来使我的代码正常工作-随时留下有关改进的建议我有什么:)
from tkinter import*
import time;
import os
import pygame
from sys import argv
from pygame.locals import *
from random import shuffle
blue = (51,153,255)
grey = (192,192,192)
purple = (204,153,255)
def main():
global main
main = Tk()
main.geometry("400x250")
main.title("Login Page")
main.configure(background="thistle1")
Label(text="Please login or register for a new account", bg="plum2", width="300", height="2", font=("Calibri", 13)).pack()
Button(text="Login",bg="SkyBlue1", height="2", width="30", command=login).pack()
Button(text="Register",bg="SkyBlue1", height="2", width="30", command=register).pack()
main.mainloop()
def register():
global register
global username
global password
global username_entry
global password_entry
register = Toplevel(main)
register.geometry("300x250")
register.title("Register")
register.configure(background="thistle1")
Label(register, text="Fill in the boxes below to register as a new user", bg="plum2").pack()
username = StringVar()
username_label = Label(register, text="Username: ", bg="SkyBlue1").pack()
usernameRegister_entry = Entry(register, textvariable=username).pack()
password = StringVar()
password_label = Label(register, text="Password: ",bg="SkyBlue1").pack()
passwordRegister_entry = Entry(register, textvariable=password, show='*').pack()
Button(register, text="Register", width=10, height=1, bg="plum2", command = new_user).pack()
def new_user():
usernameDetails = username.get()
passwordDetails = password.get()
file = open(usernameDetails, "w")
file.write(usernameDetails + "\n")
file.write(passwordDetails)
file.close()
## usernameRegister_entry.delete(0, END)
## passwordRegister_entry.delete(0, END)
Label(register,text="Registration Success", bg="plum2", font=("calibri", 11)).pack()
def login():
global usernameCheck
global passwordCheck
global usernameLogin_entry
global passwordLogin_entry
global login
login = Toplevel(main)
login.title("Login")
login.geometry("300x250")
login.configure(background="thistle1")
Label(login, text="Fill in the boxes below to login", bg="plum2").pack()
usernameCheck = StringVar()
Label(login, text="Username: ", bg="SkyBlue1").pack()
usernameLogin_entry = Entry(login, textvariable=usernameCheck).pack()
passwordCheck = StringVar()
Label(login, text="Password: ", bg="SkyBlue1").pack()
passwordLogin_entry = Entry(login, textvariable=passwordCheck, show= '*').pack()
Button(login, text="Login", width=10, height=1, bg="plum2", command=login_verification).pack()
def login_verification():
username1 = usernameCheck.get()
password1 = passwordCheck.get()
## usernameLogin_entry.delete(0, END)
## passwordLogin_entry.delete(0, END)
userfiles = os.listdir()
if username1 in userfiles:
file1 = open(username1, "r")
verify = file1.read().splitlines()
if password1 in verify:
login_success()
else:
incorrect_password()
else:
incorrect_user()
def login_success():
global login_success
login_success = Toplevel(login)
login_success.title("Success")
login_success.geometry("250x100")
login_success.configure(background="thistle1")
Label(login_success, text="You have logged in successfully!", bg="plum2").pack()
## destroySuccess_message()
##
##def destroySuccess_message():
##
## time.sleep(20)
## login_success.destory()
return login_success
def incorrect_password():
incorrect_password = Toplevel(login)
incorrect_password.title("Incorrect Password")
incorrect_password.geometry("250x100")
incorrect_password.configure(background="thistle1")
Label(incorrect_password, text="Invalid Password ", bg="plum2").pack()
## time.sleep(20)
## incorrect_password.destroy()
def incorrect_user():
incorrect_user = Toplevel(login)
incorrect_user.title("Incorrect User")
incorrect_user.geometry("250x100")
incorrect_user.configure(background="thistle1")
Label(incorrect_user, text="User Not Found", bg="plum2").pack()
##def game():
## pygame.init()
## screen = pygame.display.set_mode((400,300))
## done = False
## x = 50
## y = 50
## clock = pygame.time.Clock()
##
## while not done:
## for event in pygame.event.get():
## if event.type == pygame.QUIT:
## done = True
##
## pressed = pygame.key.get_pressed()
## if pressed[pygame.K_UP]: y -= 1
## if pressed[pygame.K_DOWN]: y += 1
## if pressed[pygame.K_LEFT]: x -= 1
## if pressed[pygame.K_RIGHT]: x += 1
##
## clock.tick(60)
##
## pygame.display.flip()
##
pygame.init
class Maze:
def __init__(self, rows=30, cols=40):
self.rows = rows
self.cols = cols
self.keep_going = 1
self.maze = {}
for y in range(rows):
for x in range(cols):
cell = {'south' : 1, 'east' : 1, 'visited': 0}
self.maze[(x,y)] = cell
def generate(self, start_cell=None, stack=[]):
"""Generates a random maze using a magical simple recursive function."""
if start_cell is None:
start_cell = self.maze[(self.cols-1, self.rows-1)]
if not self.keep_going:
return
self.check_finished()
neighbors = []
# if the stack is empty, add the start cell
if len(stack) == 0:
stack.append(start_cell)
# set current cell to last cell
curr_cell = stack[-1]
# get neighbors and shuffle 'em up a bit
neighbors = self.get_neighbors(curr_cell)
shuffle(neighbors)
for neighbor in neighbors:
if neighbor['visited'] == 0:
neighbor['visited'] = 1
stack.append(neighbor)
self.knock_wall(curr_cell, neighbor)
self.generate(start_cell, stack)
def get_coords(self, cell):
# grabs coords of a given cell
coords = (-1, -1)
for k in self.maze:
if self.maze[k] is cell:
coords = (k[0], k[1])
break
return coords
def get_neighbors(self, cell):
# obvious
neighbors = []
(x, y) = self.get_coords(cell)
if (x, y) == (-1, -1):
return neighbors
north = (x, y-1)
south = (x, y+1)
east = (x+1, y)
west = (x-1, y)
if north in self.maze:
neighbors.append(self.maze[north])
if south in self.maze:
neighbors.append(self.maze[south])
if east in self.maze:
neighbors.append(self.maze[east])
if west in self.maze:
neighbors.append(self.maze[west])
return neighbors
def knock_wall(self, cell, neighbor):
# knocks down wall between cell and neighbor.
xc, yc = self.get_coords(cell)
xn, yn = self.get_coords(neighbor)
# Which neighbor?
if xc == xn and yc == yn + 1:
# neighbor's above, knock out south wall of neighbor
neighbor['south'] = 0
elif xc == xn and yc == yn - 1:
# neighbor's below, knock out south wall of cell
cell['south'] = 0
elif xc == xn + 1 and yc == yn:
# neighbor's left, knock out east wall of neighbor
neighbor['east'] = 0
elif xc == xn - 1 and yc == yn:
# neighbor's right, knock down east wall of cell
cell['east'] = 0
def check_finished(self):
# Checks if we're done generating
done = 1
for k in self.maze:
if self.maze[k]['visited'] == 0:
done = 0
break
if done:
self.keep_going = 0
class Game:
def __init__(self, diff, dim, path):
self.size = (500,500)
self.screen = pygame.display.set_mode(self.size)
pygame.display.set_caption('Maze')
font = pygame.font.SysFont(pygame.font.get_default_font(), 55)
text = font.render("Loading...", 1, (255,255,255))
rect = text.get_rect()
rect.center = self.size[0]/2, self.size[1]/2
self.screen.blit(text, rect)
pygame.display.update(rect)
self.diff = diff
self.dim = map(int, dim.split('x'))
self.path = path
def start(self):
self.maze_obj = Maze(*self.dim)# pass args to change maze size: Maze(10, 10)
if self.diff == 0:
self.maze_obj.generate(self.maze_obj.maze[(0,0)])
else:
self.maze_obj.generate()
self.draw_maze()
self.reset_player()
self.loop()
def reset_player(self):
# Make the sprites for the player.
w, h = self.cell_width - 3, self.cell_height - 3
rect = 0, 0, w, h
base = pygame.Surface((w,h))
base.fill( (255,255,255) )
self.red_p = base.copy()
self.green_p = base.copy()
self.blue_p = base.copy()
self.goldy = base.copy()
if self.path == 1:
r = (255,0,0)
g = (0,255,0)
else:
r = g = (255,255,255)
b = (0,0,255)
gold = (0xc5,0x93,0x48)
pygame.draw.ellipse(self.red_p, r, rect)
pygame.draw.ellipse(self.green_p, g, rect)
pygame.draw.ellipse(self.blue_p, b, rect)
pygame.draw.ellipse(self.goldy, gold, rect)
# Make a same-size matrix for the player.
self.player_maze = {}
for y in range(self.maze_obj.rows):
for x in range(self.maze_obj.cols):
cell = {'visited' : 0} # if 1, draws green. if >= 2, draws red.
self.player_maze[(x,y)] = cell
self.screen.blit(base, (x*self.cell_width+2, y*self.cell_height+2))
self.screen.blit(self.goldy, (x*self.cell_width+2, y*self.cell_height+2))
self.cx = self.cy = 0
self.curr_cell = self.player_maze[(self.cx, self.cy)] # starts at origin
self.last_move = None # For last move fun
def draw_maze(self):
self.screen.fill( (255,255,255) )
self.cell_width = self.size[0]/self.maze_obj.cols
self.cell_height = self.size[1]/self.maze_obj.rows
for y in range(self.maze_obj.rows):
for x in range(self.maze_obj.cols):
if self.maze_obj.maze[(x, y)]['south']: # draw south wall
pygame.draw.line(self.screen, (0,0,0), \
(x*self.cell_width, y*self.cell_height + self.cell_height), \
(x*self.cell_width + self.cell_width, \
y*self.cell_height + self.cell_height) )
if self.maze_obj.maze[(x, y)]['east']: # draw east wall
pygame.draw.line(self.screen, (0,0,0), \
(x*self.cell_width + self.cell_width, y*self.cell_height), \
(x*self.cell_width + self.cell_width, y*self.cell_height + \
self.cell_height) )
# Screen border
pygame.draw.rect(self.screen, (0,0,0), (0,0, self.size[0], self.size[1]), 1)
pygame.display.update()
def loop(self):
self.clock = pygame.time.Clock()
self.keep_going = 1
while self.keep_going:
moved = 0
self.clock.tick(10)
for event in pygame.event.get():
if event.type == QUIT:
self.keep_going = 0
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
self.keep_going = 0
if event.key == K_r:
self.reset_player()
if event.key == K_DOWN:
self.move_player('d')
moved = 1
if event.key == K_UP:
self.move_player('u')
moved = 1
if event.key == K_LEFT:
self.move_player('l')
moved = 1
if event.key == K_RIGHT:
self.move_player('r')
moved = 1
keys = pygame.key.get_pressed()
if not moved:
if keys[K_DOWN]:
self.move_player('d')
if keys[K_UP]:
self.move_player('u')
if keys[K_LEFT]:
self.move_player('l')
if keys[K_RIGHT]:
self.move_player('r')
self.draw_player()
pygame.display.update()
def move_player(self, dir):
no_move = 0
try:
if dir == 'u':
if not self.maze_obj.maze[(self.cx, self.cy-1)]['south']:
self.cy -= 1
self.curr_cell['visited'] += 1
else: no_move = 1
elif dir == 'd':
if not self.maze_obj.maze[(self.cx, self.cy)]['south']:
self.cy += 1
self.curr_cell['visited'] += 1
else: no_move = 1
elif dir == 'l':
if not self.maze_obj.maze[(self.cx-1, self.cy)]['east']:
self.cx -= 1
self.curr_cell['visited'] += 1
else: no_move = 1
elif dir == 'r':
if not self.maze_obj.maze[(self.cx, self.cy)]['east']:
self.cx += 1
self.curr_cell['visited'] += 1
else: no_move = 1
else:
no_move = 1
except KeyError: # Tried to move outside screen
no_move = 1
# Handle last move...
if ((dir == 'u' and self.last_move == 'd') or \
(dir == 'd' and self.last_move == 'u') or \
(dir == 'l' and self.last_move == 'r') or \
(dir == 'r' and self.last_move == 'l')) and \
not no_move:
self.curr_cell['visited'] += 1
if not no_move:
self.last_move = dir
self.curr_cell = self.player_maze[(self.cx, self.cy)]
if self.cx + 1 == self.maze_obj.cols and self.cy + 1 == self.maze_obj.rows:
print ('Congratulations, you beat this maze.')
font = pygame.font.SysFont(pygame.font.get_default_font(), 55)
text = font.render("Congratulations! You beat this maze.", 1, (255,255,255))
rect = text.get_rect()
self.keep_going = 0
## pygame.quit()
## Check for victory.
## if self.cx + 1 == self.maze_obj.cols and self.cy + 1 == self.maze_obj.rows:
## print ('Congratulations, you beat this maze.')
##
## font = pygame.font.SysFont(pygame.font.get_default_font(), 55)
## text = font.render("Congratulations! You beat this maze.", 1, (255,255,255))
## rect = text.get_rect()
## self.keep_going = 0
def draw_player(self):
for y in range(self.maze_obj.rows):
for x in range(self.maze_obj.cols):
if self.player_maze[(x,y)]['visited'] > 0:
if self.player_maze[(x,y)]['visited'] == 1:
circ = self.green_p
# draw green circles
self.screen.blit(circ, (x*self.cell_width+2, y*self.cell_height+2))
self.screen.blit(self.blue_p, (self.cx*self.cell_width+2, \
self.cy*self.cell_height+2))
##def levels():
## pygame.init()
## done = False
## while not done:
## for event in pygame.event.get():
## if event.type == pygame.QUIT:
## done = True
##
## def level_one():
## pygame.init()
## args = argv[1:]
## diff = 0
## dim = '5x5'
## path = 1
## for arg in args:
## if '--diff' in arg:
## diff = int(arg.split('=')[-1])
## elif '--dim' in arg:
## dim = arg.split('=')[-1]
## elif '--path' in arg:
## path = int(arg.split('=')[-1])
##
## g = Game(diff, dim, path)
## g.start()
## sys.exit()
##
## ##if __name__ == '__main__':
## def level_two():
## pygame.init()
## args = argv[1:]
## diff = 0
## dim = '5x5'
## path = 1
## for arg in args:
## if '--diff' in arg:
## diff = int(arg.split('=')[-1])
## elif '--dim' in arg:
## dim = arg.split('=')[-1]
## elif '--path' in arg:
## path = int(arg.split('=')[-1])
##
## g = Game(diff, dim, path)
## g.start()
## pygame.quit()
##
## ##if __name__ == '__main__':
## def level_three():
## pygame.init()
## args = argv[1:]
## diff = 0
## dim = '5x5'
## path = 1
## for arg in args:
## if '--diff' in arg:
## diff = int(arg.split('=')[-1])
## elif '--dim' in arg:
## dim = arg.split('=')[-1]
## elif '--path' in arg:
## path = int(arg.split('=')[-1])
##
## g = Game(diff, dim, path)
## g.start()
## pygame.quit()
main()
if __name__ == '__main__':
for levels in range(1,10):
pygame.init()
args = argv[1:10]
diff = 0
dim = '10x10'
path = 1
for arg in args:
if '--diff' in arg:
diff = int(arg.split('=')[-1])
elif '--dim' in arg:
dim = arg.split('=')[-1]
elif '--path' in arg:
path = int(arg.split('=')[-1])
maze = Game(diff, dim, path)
maze.start()
pygame.display.update
pygame.display.flip
pygame.quit()
base = pygame.Surface((20,30))
base.fill( (255,255,255) )
pygame.quit()
## maze.loop()
## pygame.init()
## args = argv[]
## diff2 = 0
## dim2 = '11x11'
## path2 = 1
## for arg in args:
## if '--diff2' in arg:
## diff2 = int(arg.split('=')[-2])
## elif '--dim2' in arg:
## dim2 = arg.split('=')[-2]
## elif '--path2' in arg:
## path2 = int(arg.split('=')[-2])
##
## pygame.display.update
## pygame.display.flip
##
## base = pygame.Surface((20,30))
## base.fill( (255,255,255) )
##
## maze2 = Game(diff2, dim2, path2)
## maze2.start()
## pygame.quit()
##levels()
答案 0 :(得分:2)
[...]其余的关卡似乎是一个网格,这让我认为游戏正在旧版本上创建新的迷宫。
此问题是由Python中的常见错误引起的。
重要警告:默认值仅被评估一次。当默认值是可变对象(例如列表,字典或大多数类的实例)时,这会有所不同
在您的情况下,类generate
的方法Maze
的参数具有默认参数:
class Maze: # [...] def generate(self, start_cell=None, stack=[]): # [...]
在方法generate
中,元素被附加到stack
中。迷宫是通过信任默认参数生成的:
self.maze_obj.generate(self.maze_obj.maze[(0,0)])
这导致钉头锤的第一代成功,但是第二代失败。因为stack
包含前代过程的所有元素。
将一个空白列表传递给generate
以解决该问题:
self.maze_obj.generate(self.maze_obj.maze[(0,0)])
self.maze_obj.generate(self.maze_obj.maze[(0,0)], [])
或将默认参数更改为None
:
class Maze:
# [...]
def generate(self, start_cell=None, stack=None):
if stack == None:
stack = []