首页 > 解决方案 > 我的 python 代码正在更改列表中的变量,但我看不到它是如何/为什么被更改的

问题描述

您好,我正在尝试通过犯一些错误来学习一些基础知识。我正在制作一个基本的基于 python 的蛇游戏,尽可能少地使用非内置模块。目前主要的是tkinter。

我的一些逻辑是更改列表的成员,当我不希望它这样做并且我不明白为什么时。

更改发生在第 60 (21) 行,其中索引 1 更改为等于索引 0,仅当第 71 (31) 行出现“中间”时,索引 0 才应更改

错误在这个函数内

self.player[1] 在我没想到的时候发生了变化

def move(self):
    print("old snake pos {}".format(self.player))
    for i in range(len(self.player)-1, -1, -1):
        # runs through loop backwards as the positions of the next piece needs to be known
        print(i)
        if i == len(self.player)-1:
            print("last piece")
            if self.eat():
                print("eat = True")
                self.player.append(self.player[-1])
            print("{} changed from {} to {}".format(i, self.player[i], self.player[i-1]))
            self.player[i] = self.player[i-1]

        else:
            if i == 0:
                print("Head")
                print(self.vel)
                print(self.player[0])
                print(self.player[1])
                self.player[0][0] = self.player[0][0] + self.vel[0]
                print("why has it changed????????")
                print(self.player[0])
                print(self.player[1])
                self.player[0][1] = self.player[0][1] + self.vel[1]
                print(self.player[1])
                print(self.player)
                continue
            print("middle piece")
            print("{} changed from {} to {}".format(i, self.player[i], self.player[i - 1]))
            self.player[i] = self.player[i - 1]
            print(self.player[i])
        print(self.player[i])
        print(self.player)
    print("new snake pos {}".format(self.player))

我尝试了不同的检查,但它似乎没有在正确的时间做任何我不期望的行。

完整的代码是这样的:

# programme for learning more about creating graphical displays in Python
# will start with some investigation and use of tkinter resource
# then move to creating a snake style game

import tkinter as tk
import random as r
import time

class SnakeApp(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.setup()
        self.gameloop()

    def mat2str(self, matrix):
        string = ""
        for y in matrix:
            for x in y:
                string += x
            string += "\n"
        return string

    # random an int co-ordinate
    def newpos(self):
        return [r.randint(0, self.wx), r.randint(0, self.wy)]

    # check if the fruit has been eaten
    def eat(self):
        if any([s == self.fruit for s in self.player]):
            print("fruit col detected {}".format(self.fruit))
            # new position
            self.fruit = self.newpos()
            # increase the game speed by 2.5%
            self.dt = self.dt * 0.975
            # need to add a segment to the player
            return True

    # move the game 1 turn and compute all the logic before the next frame is drawn
    def move(self):
        print("old snake pos {}".format(self.player))
        for i in range(len(self.player)-1, -1, -1):
            # runs through loop backwards as the positions of the next piece needs to be known
            print(i)
            if i == len(self.player)-1:
                print("last piece")
                if self.eat():
                    print("eat = True")
                    self.player.append(self.player[-1])
                print("{} changed from {} to {}".format(i, self.player[i], self.player[i-1]))
                self.player[i] = self.player[i-1]

            else:
                if i == 0:
                    print("Head")
                    print(self.vel)
                    print(self.player[0])
                    print(self.player[1])
                    self.player[0][0] = self.player[0][0] + self.vel[0]
                    print("why has it changed????????")
                    print(self.player[0])
                    print(self.player[1])
                    self.player[0][1] = self.player[0][1] + self.vel[1]
                    print(self.player[1])
                    print(self.player)
                    continue
                print("middle piece")
                print("{} changed from {} to {}".format(i, self.player[i], self.player[i - 1]))
                self.player[i] = self.player[i - 1]
                print(self.player[i])
            print(self.player[i])
            print(self.player)
        print("new snake pos {}".format(self.player))

    def up(self, event):
        print("up")
        if self.vel != [0, 1]:
            self.vel = [0, -1]

    def down(self, event):
        print("down")
        if self.vel != [0, -1]:
            self.vel = [0, 1]

    def left(self, event):
        print("left")
        if self.vel != [1, 0]:
            self.vel = [-1, 0]

    def right(self, event):
        print("right")
        if self.vel != [-1, 0]:
            self.vel = [1, 0]

    def drawempty(self, wx, wy):
        frame = []
        for y in range(wy):
            xlayer = []
            for x in range(wx):
                xlayer.append("-")
            frame.append(xlayer)
        return frame

    def redraw(self, player, object):
        # self.drawempty(self.wx, self.wy)
        # replaced redraw each frame with a static empty frame build
        print(self.gameframe)
        self.gameframe = self.drawempty(self.wx, self.wy)
        print(self.gameframe)
        # set the string in the co-ord of the object to A
        # check for collision needs to occur before this - all game logic before
        # set the string in the co-ords of all players to *
        print(object)
        self.gameframe[object[1]][object[0]] = "A"
        for b in player:
            self.gameframe[b[1]][b[0]] = "*"

    def setup(self):
        # set game size
        self.wx = 20
        self.wy = 20
        self.master.geometry("300x300")
        self.vel = [-1, 0]
        self.dt = 1

        # create text matrices of spaces of size wx * wy
        #self.gameframe = tk.Variable()
        self.gameframe = []
        #self.emptyframe = tk.Variable()
        self.emptyframe = self.drawempty(self.wx, self.wy)
        self.gameframe = self.emptyframe

        # create a player and fruit object in the space
        self.player = [[round(self.wx / 2), round(self.wy / 2)],[round(self.wx / 2) + 1, round(self.wy / 2)],[round(self.wx / 2) + 2, round(self.wy / 2)]]
        self.fruit = self.newpos()
        self.redraw(self.player, self.fruit)

        self.game = tk.Text(self, height=self.wy, width=self.wx)
        self.game.pack()
        self.game.insert(tk.END, self.mat2str(self.gameframe))

        self.master.bind("<Up>", self.up)
        self.master.bind("<Down>", self.down)
        self.master.bind("<Left>", self.left)
        self.master.bind("<Right>", self.right)

    def gameloop(self):
        while True:
            self.redraw(self.player, self.fruit)
            self.game.delete('1.0', tk.END)
            self.game.insert(tk.END, self.mat2str(self.gameframe))
            self.move()
            self.master.update()
            time.sleep(self.dt)


Snake = tk.Tk()
app = SnakeApp(master=Snake)

标签: pythonvariables

解决方案


应该修改的代码是:

self.player[i] = self.player[i - 1]

当您将元素 1 更改为元素 0 时,您不是在制作副本,而是让它们指向同一个元素,即 0。因此,当您更改元素 0 时,元素 1 也会发生变化。

示例为什么这会导致您在代码中看到:

player = [[1,2], [3,4]]
i = 1
player[i] = player[i - 1]
player[0][0] = 100
print(player)
[[100, 2], [100, 2]]

创建副本的一种快速解决方案:

self.player[i] = [x for x in self.player[i - 1]]

推荐阅读