【问题标题】:Python automatically changing all dictionary valuesPython自动更改所有字典值
【发布时间】:2021-05-08 06:53:43
【问题描述】:

我一直在开发基于文本的冒险游戏,正在为游戏构建系统制作骨架。我最初是通过键入 NESW 来使机芯工作的,但在删除调试代码后,它被破坏了一天多。以为我会寻求帮助...

这里是主要问题: 一个网格是自动生成的,坐标对象包含一个字典值,它“canGo”对应于单个字母键和一个布尔值,默认为 False。初始化网格后,我将要激活的坐标列表传递给执行以下功能的网格:(1)它激活传递的列表中的所有网格; (2)它运行一个生成活动方块列表的函数; (3) 它将该列表传递给一个函数,该函数检查每个活动坐标的一个方格并查看它是否处于活动状态,如果是,则将该方向 bool 标记为 True(例如 canGo["N"] = True.

问题:(下面的调试)初始化时正确设置属性,完成后键返回错误但似乎没有再次设置为我的代码中的其他内容。此外,它将所有键设置为同一事物(在这种情况下,所有坐标中的所有键都是 ["S"] = True)

-SD--------
SETTING DIRECTIONG debug
(1, 1) >> N
-SD--------
(1, 1) directions = N
(1, 1){'N': True, 'S': False, 'E': False, 'W': False}
-------------------
-SD--------
SETTING DIRECTIONG debug
(1, 2) >> S
-SD--------
(1, 2) directions = S
(1, 2){'N': False, 'S': True, 'E': False, 'W': False}
-------------------
(1,1): {'N': False, 'S': True, 'E': False, 'W': False}
Which direction would you like to move? <NESW>:

到目前为止的调试:我在里面有调试代码,显示它正确识别激活的网格,正确地将它们传递给列表,并且列表正确设置了 ["canGo"] 坐标属性。在初始化和处理激活的坐标之后,在它询问你想要去哪个方向之前,不会执行任何其他代码。

代码如下...

主要

from coordinates import Coordinates as Coords
from grid import Grid
from player import Player


def main():
    gridSizeX = 5
    gridSizeY = 5

    game = Grid(gridSizeX,gridSizeY, Player("John Doe", 1, 1))
    #game.setActiveGridSquares([(1,1),(1,2),(1,3)])
    game.grid[1][1].active = True
    game.grid[1][2].active = True
    game.grid[1][1].setDirections("N")
    game.grid[1][2].setDirections("S")

    while(True):
        x,y = game.player.getLocation()
        print("({x},{y}): {canGo}".format(x=x,y=y,canGo=game.grid[x][y].canGo))
        move = input("Which direction would you like to move? <NESW>: ")
        if(move.upper() == "EXIT"):
            break
        game.movePlayer(move.upper())

if __name__ == "__main__":
    main()

网格

在这里,我传递了一个不可变的元组 (x,y) 列表,然后迭代并分解。错误中方向的主要处理发生在directionsProcessing()中的Grid类下

from coordinates import Coordinates as  Coords
from player import Player

class Grid:
    """Builds Grid and takes Player Object to move along grid"""
    playerLocation = None

    def __init__(self, gridSizeX, gridSizeY, player):
        self.grid = self.buildGrid(gridSizeX,gridSizeY)
        self.player = player

    def buildGrid(self, gridSizeX, gridSizeY):
        """Builds and returns a grid object as a dictionary of [x][y]
        Starts at 1 and ends at gridSize(X/Y)
        gridSize(X/Y) will be the (x/y) max. -> 5 would be 1 to 5
        """
        Grid = {}
        for x in range(1, gridSizeX+1):
            Grid[x] = {}
            for y in range(1, gridSizeY+1):
                Grid[x][y] = Coords(x, y)
        return Grid

    def copyGrid(self):
        """Returns a copy of grid dictionary"""
        return self.grid

    def setPlayer(self, playerToSet):
        """Sets player object into grid class to allow for player tracking"""
        self.player = playerToSet

    def setActiveGridSquares(self, squares):
        """Sets a list of grid squares to active"""
        for t in squares:
            x,y = t
            self.grid[x][y].isActive = True
        self.solveGridDirections(self.getAllActiveSquares())

    def getAllActiveSquares(self):
        """Returns list of all active grid squares"""
        activeGridSquares = []
        for x in self.grid:
            for y in self.grid[x]:
                if(self.grid[x][y].isActive):
                    activeGridSquares.append((self.grid[x][y].x,self.grid[x][y].y))
        return activeGridSquares

    def solveGridDirections(self, activeSquares):
        """Resolves all active grid squares direction components to
        allow movement into nearby active squares"""
        for t in activeSquares:
            adjoiningDirections = []
            x,y = t
            #print("Evaluating ActiveSquare: ("+str(x)+","+str(y)+")")
            if((x,y+1) in activeSquares):
                adjoiningDirections.append("N")
            if((x,y-1) in activeSquares):
                adjoiningDirections.append("S")
            if((x+1,y) in activeSquares):
                adjoiningDirections.append("E")
            if((x-1,y) in activeSquares):
                adjoiningDirections.append("W")
            self.grid[x][y].setDirections("".join(adjoiningDirections)) #Sets allowed move directions inside grid
            


    def movePlayer(self, direction):
        """Moves player in direction, preforms coordinate check if player can move"""
        if(len(direction) > 1):
            print("Lenght must be 1 character ONLY <NESW>")
            return
        x,y = self.player.getLocation()
        print("-MP-------------") #####
        print("({x},{y})Can I move in {direction} direction? {tf}".format(x=str(x),y=str(y),direction=direction,tf=str(self.grid[x][y].canGo[direction])))
        print("-MP-------------") #####
        if(self.grid[x][y].canGo[direction]):
            self.player.movePlayer(direction)
        else:
            print("Player cannot move in that direciton on this grid square.")

坐标

class Coordinates:
    """Set coordinates of path squards in the world"""

    actionOnEnter = None
    choices = {"a":None,"b":None,"c":None}
    canGo = {"N": False,"S": False,"E": False,"W": False}
    isActive = False

    def __init__(self, x, y):
        self.x = x  #set x coords
        self.y = y  #set y coords

    def directionsProcessing(self, directions):
        """Directions are processed into a specific order and canGo is amended"""
        listOfDirections = ["N", "S", "E", "W"]
        verifiedDirections = []
        coordsDir = str(self.getCoords())
        print(coordsDir+" directions = "+directions) #####
        for m in listOfDirections:
            if(directions.find(m) != -1):
                self.canGo[m] = True
                verifiedDirections.append(m)
            else:
                self.canGo[m] = False
        print(coordsDir+str(self.canGo)) #####
        print("-------------------") #####

    def setDirections(self, direcitons):
        """Sets directions a player can move, updates from initialization"""
        print("-SD--------")#####
        coordsDir = str(self.getCoords())#####
        print("SETTING DIRECTIONG debug")#####
        print(coordsDir+" >> "+direcitons)#####
        print("-SD--------")#####
        self.directionsProcessing(direcitons)

    def getCoords(self):
        """Return x,y coordinate duple"""
        return self.x,self.y

玩家(不那么重要,但仍然在运动中滚动)

class Player:
    """Player class used to hold player data.
    X and Y coords are player's starting coordinates
    Control inventory, keys, etc.
    """
    inventory = {"sword": False}
    keys = {"rectangle": False, "half moon": False}

    def __init__(self, name, x, y):
        self.name = name
        self.x = x
        self.y = y

    def movePlayer(self, direction):
        """Moves player toards certain coordinates, <NESW>"""
        if (len(direction) != 1):
            raise Exception("Only 1 letter may be used.")
        updown = {"N": 1, "S": -1, "W": -1, "E": 1}
        validDirections = ["N","S","E","W"]
        
        if(direction.upper() in validDirections):
            if (direction in ["N","S"]):
                self.y += updown[direction]
            if (direction in ["W","E"]):
                self.x += updown[direction]
        else:
            Exception("Direction is invalid")

    def getLocation(self):
        """Returns tuple of player location x,y"""
        return self.x,self.y

    def setLocation(self, locationTuple):
        """Sets location based on input tuple
        Syntax -> Player.setLocation((x,y))
        """
        x,y = locationTuple
        self.x = x
        self.y = y

    def toString(self):
        """Converts player data into string"""
        return "Player: {name} Location: {x},{y}".format(name=self.name, x=self.x, y=self.y)

【问题讨论】:

  • 对我来说代码太多了;您是否将可变值(列表、集合或字典)​​作为参数传递,所以网格都指的是单个可变值,并且对可变值的任何更改当然在所有网格位置都可见?
  • 我正在传递一个不可变的元组 (x,y) 列表,然后它会遍历并分解。主要处理发生在 GRID 下的方向Processing()
  • 这是您的代码在执行此操作:在我看来,您正在混淆类和实例属性。您希望 canGo 成为实例属性,因此将其初始化从 Coord 中的位置(这使其成为类属性,即它只有一个值)移动到 __init__() 方法中作为 self.canGo=…检查您拥有的其他类属性,看看它们是否需要类似的处理,以便它们成为实例属性。
  • 我没有尝试过这个,但我认为正在发生的事情是如果canGo 是不可变的,例如然后将字符串/整数/元组分配给实例.canGo 将创建具有该值的实例属性。然而,由于Coords.canGo 是可变的,写入它的实例会更新类属性,因此所有实例都会看到相同的值。

标签: python list class


【解决方案1】:

感谢@barny 的帮助。

阅读你的 cmets 后,这可以通过两种方式解决

(1) [更好] 移动 canGo 到 init() 方法

(2) 在directionsProcession() 方法中创建一个“canGoTemp”的空实例并将值传递给该实例,然后将dict传递给canGo属性(这无需将canGo移动到init ())

这两种方法都有效,但我选择了 (1)...

再次感谢伙计,我知道这是一团糟

【讨论】:

  • :-) 不理解您的选项 2 - 我的强烈建议是保持简单/明确:如果您的代码需要一个实例属性,那么 make 它是一个实例属性通过在 __init__() 中初始化 self.canGo。您需要对您当前拥有的其他类属性给予相同的处理;如果您真的想要类属性,请确保将它们引用为例如Coords.choices。如果您想/需要将属性引用为self.x,那么您必须(为了您的理智)将它们初始化为self.x
猜你喜欢
  • 1970-01-01
  • 2015-02-08
  • 2023-01-27
  • 1970-01-01
  • 2016-05-04
  • 1970-01-01
  • 2012-01-18
  • 1970-01-01
  • 2021-12-31
相关资源
最近更新 更多