python - 我的 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)
解决方案
应该修改的代码是:
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]]
推荐阅读
- r - 如何在R中导入不同的文件,每个文件都包含xml文件?
- geoserver - 地理服务器:没有这样的工作区 'gwc/service'
- python - 为什么我不能在代码中确定对象是 DataTime 类型?
- c# - 从本机代码控制第三方线程
- python-3.x - 使用 Gensim 进行动态主题建模/哪个代码?
- javascript - 我已将函数名称“测试”添加到关注中,但错误提示它无法识别为函数。谁能帮助我
- java - 如何在Java中转换字符集?
- jquery - 淘汰赛:未捕获的 ReferenceError:分配中的左侧无效
- javascript - 提交时调用 php 函数,如果可能,不使用 jQuery
- tensorflow - 需要帮助??为 Win 10 Pro 9-2-18 安装 Tensorflow-GPU