Hey. I'm working on a simple project that requires a way to find all the empty grid cells accessible along a path that's <= n cells long (an analogy would be TBS movement), and I've got an almost-working piece of code for it. Here's the function I wrote:

``````def findArea(distance,origin,gridUsed,emptyChar):
if emptyChar == "x":
seenChar = "X"
else:
seenChar = "x"
grid = gridUsed
grid[origin[0]][origin[1]] = seenChar
returnList = [[origin[0],origin[1]]]
if distance > 0:
# x,y-1
if (origin[1]-1) >= 0:
if (grid[origin[0]][origin[1]-1] == emptyChar):
returnList += findArea(distance-1,[origin[0],origin[1]-1],grid,emptyChar)

# x,y+1
if (origin[1]+1) < len(grid[0]):
if (grid[origin[0]][origin[1]+1] == emptyChar):
returnList += findArea(distance-1,[origin[0],origin[1]+1],grid,emptyChar)

# x-1,y
if (origin[0]-1) >= 0:
if (grid[origin[0]-1][origin[1]] == emptyChar):
returnList += findArea(distance-1,[origin[0]-1,origin[1]],grid,emptyChar)

# x+1,y
if (origin[0]+1) < len(grid):
if (grid[origin[0]+1][origin[1]] == emptyChar):
returnList += findArea(distance-1,[origin[0]+1,origin[1]],grid,emptyChar)
returnList.sort()
print "gridUsed:"
print gridUsed
print "grid:"
print grid
return returnList

gridW = 4
gridH = 4
emptyChar = " "

gameGrid = []
for xVar in range(0,gridW):
gameGrid.append([])
for yVar in range(0,gridH):
gameGrid[xVar].append(emptyChar)

print "Before anything:"
print gameGrid
findArea(1,[2,2],gameGrid,emptyChar)
print "After everything:"
print gameGrid``````

You'll notice a lot of print-ing going on that's not really needed. The reason for that is I'm trying to debug it, and I'm having serious trouble. gameGrid, which exists on the main level, is somehow being altered within findArea. Which makes no sense. As far as I know, findArea has its own level of scope, it shouldn't be able to make changes outside that. Not to mention that I don't actually use gameGrid within findArea. The problem persists no matter what the variable is named.

This really is starting to get to me. Anyone know what's going on, and how to fix it?

2
Contributors
1
2
Views
10 Years
Discussion Span
Last Post by vegaseat

When you send a mutable object like a list to a function as an argument, a pointer to the object is established (allows the objects to be mutable). Inside the function you have created a simple alias copy of the list, that still has the same pointer reference. With a nested list like you have, you really have to make a true or deep copy that will have its own reference even to the nested lists inside of it. Just look over the modified code ...

``````def findArea(distance, origin, gridUsed, emptyChar):
if emptyChar == "x":
seenChar = "X"
else:
seenChar = "x"
# make a true copy rather than an alias copy  !!!!!
import copy
grid = copy.deepcopy(gridUsed)
grid[origin[0]][origin[1]] = seenChar
returnList = [[origin[0],origin[1]]]
if distance > 0:
# x,y-1
if (origin[1]-1) >= 0:
if (grid[origin[0]][origin[1]-1] == emptyChar):
returnList += findArea(distance-1,[origin[0],origin[1]-1],grid,emptyChar)

# x,y+1
if (origin[1]+1) < len(grid[0]):
if (grid[origin[0]][origin[1]+1] == emptyChar):
returnList += findArea(distance-1,[origin[0],origin[1]+1],grid,emptyChar)

# x-1,y
if (origin[0]-1) >= 0:
if (grid[origin[0]-1][origin[1]] == emptyChar):
returnList += findArea(distance-1,[origin[0]-1,origin[1]],grid,emptyChar)

# x+1,y
if (origin[0]+1) < len(grid):
if (grid[origin[0]+1][origin[1]] == emptyChar):
returnList += findArea(distance-1,[origin[0]+1,origin[1]],grid,emptyChar)
returnList.sort()
print "gridUsed:"
print gridUsed
print "grid:"
print grid
return returnList

gridW = 4
gridH = 4
emptyChar = " "

gameGrid = []
for xVar in range(0,gridW):
gameGrid.append([])
for yVar in range(0,gridH):
gameGrid[xVar].append(emptyChar)

print "Before anything:"
print gameGrid
returnList = findArea(1, [2,2], gameGrid, emptyChar)
print "After everything:"
print gameGrid  # now unchanged!
print returnList``````

Actually, Zoe brought this up just recently:
http://www.daniweb.com/forums/post593852-134.html