Python - 变量设置为0,无法弄清楚原因

时间:2013-04-29 05:45:57

标签: python for-loop pygame

好的,所以我正在用pygame做一个小游戏,并通过生成多维数组的图块来构建地图。为了做到这一点,我使用两个for循环。

def create(this, t):

    if t == "grasslands":
        for j in range(0, this.numRows):
            for i in range(0, this.numColumns):
                this.column.append(this.Tile("grass", j * this.tileWidth, i * this.tileHeight))
            this.row.append(this.column)

j * this.tileWidth 的值正在正确传递到Tile初始化。虽然列[无论] .x 值仍为0. y 值设置得很好,如果我使用 i 或任何其他价值而不是 j 事情就好了。这是我做错了什么还是用Python来解决的问题?

mapgen.py

import pygame
from sprite import *
from assets import *

class mapG:

def __init__(this, resw, resh):
    this.numRows = 3
    this.numcolumns = 3
    this.tileWidth = 128
    this.tileHeight = 128

    this.row = []
    this.column = []
    this.width = this.numRows * this.tileWidth
    this.height = this.numcolumns * this.tileHeight


def create(this, t):

    if t == "grasslands":
        for j in range(0, this.numRows):
            for i in range(0, this.numcolumns):
                this.column.append(this.Tile("grass", j * this.tileWidth, i * this.tileHeight))
            this.row.append(this.column)


def tileAt(this, x, y):
    pass

def moveRight(this):
    for j in range(0,this.numRows):
        for i in range(0, this.numcolumns):
            this.row[j][i].incX(1)

def Update(this, src):
    for j in range(0,this.numRows):
        for i in range(0, this.numcolumns):
            this.row[j][i].Update(src)
            print(this.row[j][i].y, this.row[j][i].x)

class Tile:

    def __init__(this, name, xpos, ypos):
        this.y = ypos
        this.x = xpos
        this.image = assets.tile[name + ".png"]
        this.sprite = sprite(this.image, this.x, this.y, 100, 100)

    def incX(this, amount):
        this.sprite.IncX(amount)

    def decX(this, amount):
        this.sprite.DecX(amount)

    def incY(this, amount):
        this.sprite.IncY(amount)

    def decY(this, amount):
        this.sprite.DecY(amount)

    def Update(this, src = None):
        if src != None:
            this.sprite.Update(src)

sprite.py

import pygame
import assets

class sprite:

def __init__(this, image, xpos, ypos, width = None, height = None):

    this.image = image
    this.x = xpos
    this.y = ypos
    this.width = width
    this.height = height

    if this.width != None and this.height != None:
        this.image = pygame.transform.scale(image, (this.width,this.height))

def GetPos(this):
    return (this.x, this.y)

def IncX(this, amount):
    this.x += amount

def IncY(this, amount):
    this.y += amount

def DecX(this, amount):
    this.x -= amount

def DecY(this, amount):
    this.y -= amount

def Update(this, src = None):
    if src != None:
        src.blit(this.image, this.GetPos())

2 个答案:

答案 0 :(得分:5)

我相信您遇到的问题来自于您使用this.column方法中的create变量。

您只需创建一个列列表(在__init__中),然后将其重新用于地图的所有列。这不起作用。

您的this.row列表最终会对同一列列表进行多次引用,最终会包含您创建的所有Tile个对象。您之后只能看到其中的一些,因为您的迭代代码使用预定义的维度,而不是实际迭代整个列表。

要理解这一点,请尝试设想2x2网格的迭代进度(忽略切片尺寸)。我将每个ij值放在它自己的行上以显示它的进展情况,并在每个步骤后给出rowcolumns的值:

j=0:
   i=0:
      column.append(Tile(i, j))
      # column is [Tile(0, 0)]
      # row is []

   i=1:
      column.append(Tile(i, j))
      # column is [Tile(0, 0), Tile(0, 1)]
      # row is []

   row.append(column)
   # column is [Tile(0, 0), Tile(0, 1)]
   # row is [[Tile(0, 0), Tile(0, 1)]]

j=1: # column is not reset!
   i=0:
      column.append(Tile(i, j))
      # column is [Tile(0, 0), Tile(0, 1), Tile(1, 0)]
      # row is [[Tile(0, 0), Tile(0, 1), Tile(1, 0)]]

   i=1:
      column.append(Tile(i, j))
      # column is [Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]
      # row is [[Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]]

   row.append(column)
   # column is [Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]
   # row is [[Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)],
   #          [Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]]

row列表包含两个对四个图块的column列表的引用。您的代码曾打算将前两个Tile(0, 0)Tile(0,1)添加到第一列,然后将最后两个切片Tile(1, 0)Tile(1, 1)添加到第二列。但是因为两次使用相同的列表,所以你最终得到了所有的值,然后重复了一堆。迭代时,您只能看到上图左侧的重复值。

以下是修复方法:

def create(this, t):
    if t == "grasslands":
        for j in range(0, this.numRows):

            column = [] # Create a new list! This is the key!

            for i in range(0, this.numColumns):
                column.append(this.Tile("grass",
                              j * this.tileWidth,
                              i * this.tileHeight))
            this.row.append(column)

您可以删除构造函数中初始化self.column的行。它只是暂时需要的,所以不需要使用实例变量。

答案 1 :(得分:0)

您最终不会创建宽度为3的行(numColumns)。最终会得到宽度为9(行* cols)的行,因为每次循环都不会创建新行。

你的循环应如下所示:

for j in range(0, this.numRows):
    row=[]
    for i in range(0, this.numColumns):
        row.append(this.Tile("grass", j * this.tileWidth, i * this.tileHeight))
    this.rows.append(row)

然后你可能在调试它时最终查看了错误的数据,没有意识到行的长度超出了你的预期。 (名字也有点令人困惑,所以我稍微改了一下。)