I'm trying to create an eight-puzzle game solver, and I have a little problem. My states are being stored as grids(represented by 2D- lists). I am trying to keep track of every resulting state by appending to a succ_states list whenever a move is made by the computer. However, my succ_states 2D array only shows the current state and erases previous states in the list.
Here's my code snippet for the downward move:
def actions(self, state):
actions = []
succ_states = []
print()
rows = [row for row in state]
for row in rows:
for i in row:
# D
if i == 0 and state.index(row) != 2:
print(row, "down action, finally!")
print("Index of i = ", row.index(i))
new_row = rows[state.index(row) 1]
zero = i
zero_index = row.index(zero)
row[zero_index] = new_row[zero_index]
new_row[zero_index] = zero
actions.append("D")
succ_states.append(rows)
return actions, succ_states
Using the initial state [[1, 3, 0], [6, 7, 8], [4, 2, 5]], actions returns [[[8, 7, 3], [5, 4, 6], [2, 1, 0]], [[8, 7, 3], [5, 4, 6], [2, 1, 0]]]. I don't get why it removes the first resulting state and appends the second state twice. I tried changing the position of the append statements and even tried to extend, but nothing is working.
CodePudding user response:
You are appending rows, but this appends a reference to the list, not a copy. This means that when you later modify rows (or one of the items in row, which are lists in themselves), you modify the contents of succ_states as well.
The fix is to append a copy of rows. And, in this case that rows is a list of lists, then you need to use deepcopy.
I believe this will implement the behavior you seek:
import copy
def actions(self,state):
actions = []
succ_states = []
print()
rows = [row for row in state]
for row in rows:
for i in row:
# D
if i == 0 and state.index(row) != 2:
print(row, "down action, finally!")
print("Index of i = ", row.index(i))
new_row = rows[state.index(row) 1]
zero = i
zero_index = row.index(zero)
row[zero_index] = new_row[zero_index]
new_row[zero_index] = zero
actions.append("D")
succ_states.append(copy.deepcopy(rows))
return actions, succ_states