在 python 中将两个自变量分配给彼此的问题
Issue assigning two self variables to each other in python
我正在构建一个 2048 游戏并尝试构建一个停止条件。但是面临着两个变量的一些问题。我尝试的想法很简单——当两个矩阵值(一个包含当前 4x4 板值,另一个包含前一步的值)彼此相等时停止执行。
基本上代码是这样的。
import numpy as np
import random
class Board():
def __init__(self):
self.board = np.zeros((4,4), dtype = np.int)
self.prev_board = np.zeros((4,4), dtype = np.int)
self.new_game()
print("New Board Created")
self.newgame = False
def new_game(self):
for cnt in range(2):
i = random.randint(0,3)
j = random.randint(0,3)
self.board[i][j] = random.choice([2,4])
def populate(self):
empty = []
for i in range(4):
for j in range(4):
if self.board[i][j] == 0:
empty.append([i,j])
i,j = random.choice(empty)
self.board[i][j] = random.choice([2,4])
def move(self,board):
k = 0
for row in board:
new_col = np.zeros(len(row), dtype=row.dtype)
j = 0
previous = None
for i in range(row.size):
if row[i] != 0:
if previous == None:
previous = row[i]
else:
if previous == row[i]:
new_col[j] = 2 * row[i]
j += 1
previous = None
else:
new_col[j] = previous
j += 1
previous = row[i]
if previous != None:
new_col[j] = previous
board[k] = new_col
k += 1
return board
def next_move(self,direction):
rotated_board = np.rot90(self.board, direction)
rotated_board = self.move(rotated_board)
self.board = np.rot90(rotated_board, -direction)
def play_game(self,direction):
self.next_move(direction)
self.prev_board = self.board
print("Before populate")
print(self.prev_board)
self.populate()
print("After populate")
print(self.prev_board)
game = Board()
for i in range(2):
game.play_game(0)
这是执行游戏一步的方法,这个方法会被反复调用,直到达到上面提到的停止条件。问题是当我尝试这种方式时,self.prev_board 值在调用 self.populate() 之前和之后发生变化。就是不明白这是怎么回事
输出是,
Before populate
[[0 0 0 0]
[2 0 0 0]
[0 0 0 0]
[2 0 0 0]]
After populate
[[0 0 0 0]
[2 0 0 0]
[0 0 0 0]
[2 0 4 0]]
Before populate
[[0 0 0 0]
[2 0 0 0]
[0 0 0 0]
[2 4 0 0]]
After populate
[[0 0 0 0]
[2 0 2 0]
[0 0 0 0]
[2 4 0 0]]
P.S: self.next_move(direction) - 进行下一步移动并且 self.populate() - 在矩阵中填充一个新的随机值。
https://docs.python.org/2/library/copy.html
Python 中的赋值语句不复制对象,它们在目标和对象之间创建绑定。对于可变的或包含可变项的集合,有时需要一个副本,以便可以更改一个副本而不更改另一个。该模块提供通用的浅拷贝和深拷贝操作(如下所述)。
界面摘要:
copy.copy(x)
Return x 的浅拷贝。
copy.deepcopy(x)
Return x 的深拷贝。
请仔细阅读以上内容link,这应该会对您的问题有所帮助
如果我理解正确,当您尝试将 self.board
变量复制到 self.prev_board
时,您的问题就会发生。 Python 在两个变量之间传递时默认使用 "pass by reference" 模式。因此 self.board
中的任何更改也会更改 self.prev_board
。它并没有真正复制值,而只是 link
您可以通过输入 [:]
或使用 copy
or deepcopy
.
来避免它
def play_game(self,direction):
self.next_move(direction)
self.prev_board = self.board[:]
print(self.prev_board)
self.populate()
print(self.prev_board)
使用深拷贝:
from copy import deepcopy
def play_game(self,direction):
self.next_move(direction)
self.prev_board = deepcopy(self.board)
print(self.prev_board)
self.populate()
print(self.prev_board)
我正在构建一个 2048 游戏并尝试构建一个停止条件。但是面临着两个变量的一些问题。我尝试的想法很简单——当两个矩阵值(一个包含当前 4x4 板值,另一个包含前一步的值)彼此相等时停止执行。
基本上代码是这样的。
import numpy as np
import random
class Board():
def __init__(self):
self.board = np.zeros((4,4), dtype = np.int)
self.prev_board = np.zeros((4,4), dtype = np.int)
self.new_game()
print("New Board Created")
self.newgame = False
def new_game(self):
for cnt in range(2):
i = random.randint(0,3)
j = random.randint(0,3)
self.board[i][j] = random.choice([2,4])
def populate(self):
empty = []
for i in range(4):
for j in range(4):
if self.board[i][j] == 0:
empty.append([i,j])
i,j = random.choice(empty)
self.board[i][j] = random.choice([2,4])
def move(self,board):
k = 0
for row in board:
new_col = np.zeros(len(row), dtype=row.dtype)
j = 0
previous = None
for i in range(row.size):
if row[i] != 0:
if previous == None:
previous = row[i]
else:
if previous == row[i]:
new_col[j] = 2 * row[i]
j += 1
previous = None
else:
new_col[j] = previous
j += 1
previous = row[i]
if previous != None:
new_col[j] = previous
board[k] = new_col
k += 1
return board
def next_move(self,direction):
rotated_board = np.rot90(self.board, direction)
rotated_board = self.move(rotated_board)
self.board = np.rot90(rotated_board, -direction)
def play_game(self,direction):
self.next_move(direction)
self.prev_board = self.board
print("Before populate")
print(self.prev_board)
self.populate()
print("After populate")
print(self.prev_board)
game = Board()
for i in range(2):
game.play_game(0)
这是执行游戏一步的方法,这个方法会被反复调用,直到达到上面提到的停止条件。问题是当我尝试这种方式时,self.prev_board 值在调用 self.populate() 之前和之后发生变化。就是不明白这是怎么回事
输出是,
Before populate
[[0 0 0 0]
[2 0 0 0]
[0 0 0 0]
[2 0 0 0]]
After populate
[[0 0 0 0]
[2 0 0 0]
[0 0 0 0]
[2 0 4 0]]
Before populate
[[0 0 0 0]
[2 0 0 0]
[0 0 0 0]
[2 4 0 0]]
After populate
[[0 0 0 0]
[2 0 2 0]
[0 0 0 0]
[2 4 0 0]]
P.S: self.next_move(direction) - 进行下一步移动并且 self.populate() - 在矩阵中填充一个新的随机值。
https://docs.python.org/2/library/copy.html
Python 中的赋值语句不复制对象,它们在目标和对象之间创建绑定。对于可变的或包含可变项的集合,有时需要一个副本,以便可以更改一个副本而不更改另一个。该模块提供通用的浅拷贝和深拷贝操作(如下所述)。
界面摘要:
copy.copy(x) Return x 的浅拷贝。
copy.deepcopy(x) Return x 的深拷贝。
请仔细阅读以上内容link,这应该会对您的问题有所帮助
如果我理解正确,当您尝试将 self.board
变量复制到 self.prev_board
时,您的问题就会发生。 Python 在两个变量之间传递时默认使用 "pass by reference" 模式。因此 self.board
中的任何更改也会更改 self.prev_board
。它并没有真正复制值,而只是 link
您可以通过输入 [:]
或使用 copy
or deepcopy
.
def play_game(self,direction):
self.next_move(direction)
self.prev_board = self.board[:]
print(self.prev_board)
self.populate()
print(self.prev_board)
使用深拷贝:
from copy import deepcopy
def play_game(self,direction):
self.next_move(direction)
self.prev_board = deepcopy(self.board)
print(self.prev_board)
self.populate()
print(self.prev_board)