我尝试创建一个基于this javascript的菱形方块算法,因为它是可读的并且对我来说也很有意义。我遇到了一些我似乎无法解决的问题。
运行代码时,所需的输出是填充2D阵列的每个位置的一些随机值,该位置与初始阵列初始化不同。我遇到的问题是结果2D数组没有完全填充,当网格大小增加到3以上时,我得到IndexError: list index out of range
错误。
以下是代码:
class DiamondSquare:
def __init__(self, size, roughness):
self.size = (size ** 2) + 1
self.max = self.size - 1
self.roughness = roughness
self.grid = self.make_grid(self.size)
self.divide(self.max)
print(self.grid)
def divide(self, size):
x = size / 2
y = size / 2
half = size / 2
scale = self.roughness * size
if (half < 1):
return
# Squares
for y in range(half, self.max, size):
for x in range(half, self.max, size):
s_scale = random.uniform(0, 1) * scale * 2 - scale
self.square(x, y, half, s_scale)
# Diamonds
for y in range(0, self.max, half):
for x in range((y + half) % size, self.max, size):
d_scale = random.uniform(0, 1) * scale * 2 - scale
self.diamond(x, y, half, d_scale)
self.divide(size / 2)
def square(self, x, y, size, scale):
"""
TL TR
X
BL BR
"""
tl = self.grid[x - size][y - size]
tr = self.grid[x + size][y - size]
bl = self.grid[x + size][y + size]
br = self.grid[x - size][y + size]
average = ((tl + tr + bl + br) / 4) + scale
self.grid[x][y] = average
def diamond(self, x, y, size, scale):
"""
T
L X R
B
"""
t = self.grid[x][y - size]
r = self.grid[x + size][y]
b = self.grid[x][y + size]
l = self.grid[x - size][y + size]
average = ((t + r + b + l) / 4) + scale
self.grid[x][y] = average
def make_grid(self, size):
grid = []
for y in range(size):
temp = []
for x in range(size):
temp.append(-1)
grid.append(temp)
grid[0][0] = self.max
grid[self.max][0] = self.max / 2
grid[self.max][self.max] = 0
grid[0][self.max] = self.max / 2
return grid
def get_grid(self):
return self.grid
当尝试将size变量(在init中)增加到大于2的值时,我得到以下回溯:
Traceback (most recent call last):
File "C:\Users\user\Documents\Development\Python\Fractal\diamond_square.py", line 150, in <module>
a = DiamondSquare(5, 0.7)
File "C:\Users\user\Documents\Development\Python\Fractal\diamond_square.py", line 14, in __init__
self.divide(self.max)
File "C:\Users\user\Documents\Development\Python\Fractal\diamond_square.py", line 35, in divide
self.diamond(x, y, half, d_scale)
File "C:\Users\user\Documents\Development\Python\Fractal\diamond_square.py", line 68, in diamond
r = self.grid[x + size][y]
IndexError: list index out of range
老实说,我不确定为什么会这样,我根本无法理解。我使用以下代码来产生此错误:
a = DiamondSquare(x, 0.7)
其中x是大于2的任何整数,第二个参数是粗糙度。
关于网格错误,尝试从DiamondSquare.divide()创建网格,产生以下内容:
[[4, 1.0649105908291359, 1.234026481506731, 0.07818244918327344, 2],
[0.43855022217756057, 0.4659935454877355, 1.283183468707215, 0.28019876872734906, -1],
[-0.4946413746345607, -1.1327574166276582, 0.45804405178511276, -1.4905717022572778, -1],
[-1.4175095415414622, -0.660055583070249, -0.8017056243549873, -0.18216161649389495, -1],
[2, -1, -1, -1, 0]]
在-1的位置,应该有其他随机数与网格的其余部分一样。 -1表示底部和右侧的中点。我相信这与我的钻石循环有关,但我不确定我哪里出错了。
我实现了这个网格,我使用以下代码:
a = DiamondSquare(2, 0.7)
其中第一个参数是大小,第二个参数是粗糙度。
我可以帮助解决上述问题吗?提前谢谢!
答案 0 :(得分:4)
创建尺寸参数时,您更改了底座和电源的位置。您撰写了(size ** 2) + 1
,但应该是(2 ** size) + 1
。这有望解决您的问题。
答案 1 :(得分:1)
我设法通过删除2D列表并简单地使用1D列表来解决这个问题,这是我本来应该做的事情,但我没有,因为我误读了原始代码。
class DiamondSquare:
def __init__(self, size, roughness):
self.size = (2 ** size) + 1
self.max = self.size - 1
self.roughness = roughness
self.make_grid(self.size)
self.divide(self.max)
# Sets x,y position in self.grid
def set(self, x, y, val):
self.grid[x + self.size * y] = val;
# Get's value of x, y in self.grid
def get(self, x, y):
if (x < 0 or x > self.max or y < 0 or y > self.max):
return -1
return self.grid[x + self.size * y]
def divide(self, size):
x = size / 2
y = size / 2
half = size / 2
scale = self.roughness * size
if (half < 1):
return
# Square
for y in range(half, self.max, size):
for x in range(half, self.max, size):
s_scale = random.uniform(0, 1) * scale * 2 - scale
self.square(x, y, half, s_scale)
# Diamond
for y in range(0, self.max + 1, half):
for x in range((y + half) % size, self.max + 1, size):
d_scale = random.uniform(0, 1) * scale * 2 - scale
self.diamond(x, y, half, d_scale)
self.divide(size / 2)
def square(self, x, y, size, scale):
top_left = self.get(x - size, y - size)
top_right = self.get(x + size, y - size)
bottom_left = self.get(x + size, y + size)
bottom_right = self.get(x - size, y + size)
average = ((top_left + top_right + bottom_left + bottom_right) / 4)
self.set(x, y, average + scale)
def diamond(self, x, y, size, scale):
"""
T
L X R
B
"""
top = self.get(x, y - size)
right = self.get(x + size, y)
bottom = self.get(x, y + size)
left = self.get(x - size, y)
average = ((top + right + bottom + left) / 4)
self.set(x, y, average + scale)
def make_grid(self, size):
self.grid = []
for x in range(size * size):
self.grid.append(-1)
self.set(0, 0, self.max)
self.set(self.max, 0, self.max /2 )
self.set(self.max, self.max, 0)
self.set(0, self.max, self.max / 2)
def get_grid(self):
return self.grid
a = DiamondSquare(3, 0.5)
print(a.get_grid())