Pygame迷宫游戏无法正确创建关卡

问题描述 投票:0回答:1

因此,我正在尝试为学校的一个项目创建一个带有关卡的迷宫游戏。该代码有点重复,对不起,我才刚刚开始使用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()
python-3.x pygame maze
1个回答
0
投票

此问题是由Python中的常见错误引起的。

请参见4.7.1. Default Argument Values

重要警告:默认值仅被评估一次。当默认值是可变对象(例如列表,字典或大多数类的实例)时,这会有所不同。

在您的情况下,类generate的方法Maze的参数具有默认参数:

class Maze:
   # [...]

   def generate(self, start_cell=None, stack=[]):
       # [...]

迷宫通过信任默认参数生成:

self.maze_obj.generate(self.maze_obj.maze[(0,0)])

这导致第一代狼牙棒成功,但以下失败。

将空白列表传递给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 = []
© www.soinside.com 2019 - 2024. All rights reserved.