I’ve been attempting to port a program I’ve written in C++ to Python. Specifically, it is a program for generating heightmaps which can be exported to 3D models, and which ideally, when viewed, would look like realistic terrain.
The HeightMap class wraps a two-dimensional array of float values. For now I’ve kept it as integers because it prints nicer, and I haven’t had a chance to implement any other features. The glitch I’m having is that when I call set(self, x, y, value), which simply sets the value at x, y to value, with the code “self.rows[y][x] = value”, it seems to change the entire column, visiting each member of self.rows and setting the xth member of that array to value.
Here is my code. I am about 90% sure the mistake is somewhere in the 2-array’s initialization.
def filledArray(length, value) :
result = []
for i in range(1, length) :
result.append(value)
return result
def resizeArray(array, newLength, nullValue) :
if newLength == len(array) :
return array
result = []
for i in range(0, newLength) :
if i < len(array) :
result.append(array[i])
else :
result.append(nullValue)
return result
class HeightMap:
"""A class that wraps a 2D array for generating height maps"""
def __init__(self) :
self.width = 0
self.height = 0
self.rows = []
def __init__(self, initWidth, initHeight) :
self.clear(initWidth, initHeight);
def clear(self, initWidth, initHeight) :
self.width = initWidth
self.height = initHeight
self.rows = filledArray(initHeight, filledArray(initWidth, 0))
def setHeight(self, newHeight) :
if self.height == newHeight :
return
self.rows = resizeArray(self.rows, newHeight, filledArray(self.width, 0))
def setWidth(self, newWidth) :
if self.width == newWidth :
return
for i in range(0, len(self.rows)) :
self.rows[i] = resizeArray(self.rows[i], newWidth, 0);
self.width = newWidth
def get(self, x, y) :
return self.rows[y][x]
def set(self, x, y, value) :
self.rows[y][x] = value
def add(self, x, y, value) :
self.rows[y][x] += value
def multiply(self, x, y, value) :
self.rows[y][x] *= value
Your problem is that when you call
filledArray(initHeight, filledArray(initWidth, 0))the second argument is passed by reference (this is always the case with python objects). InsidefilledArrayyou need to make a copy ofvaluefor each. This will require adding a little bit of additional logic to your function, something along the lines of:Or you could do the slightly less pythonic:
to create a copy.