长话短说,没有啥特别的就是说给出一个数N,然后画出一个N*N的表格,将1-N**2的数字填入,使得每一列和、每一列和、每个对角和都相等。
查找资料发现幻方的获得分两种情况,第一个就是奇数阶幻方的获取方法
劳伯法
把1(或最小的数)放在第一行正中;按以下规律排列剩下的(n×n-1)个数:
(1)每一个数放在前一个数的右上一格;
(2)如果这个数所要放的格已经超出了顶行那么就把它放在底行,仍然要放在右一列;
(3)如果这个数所要放的格已经超出了最右列那么就把它放在最左列,仍然要放在上一行;
(4)如果这个数所要放的格已经超出了顶行且超出了最右列,那么就把它放在底行且最左列;
(5)如果这个数所要放的格已经有数填入,那么就把它放在前一个数的下一行同一列的格内。
17 | 24 | 1 | 8 | 15 |
---|---|---|---|---|
23 | 5 | 7 | 14 | 16 |
4 | 6 | 13 | 20 | 22 |
10 | 12 | 19 | 21 | 3 |
11 | 18 | 25 | 2 | 9 |
还有一种是双偶数阶幻方
海尔法
先把数字按顺序填。然后,按4×4把它分割成4块
每个小方阵对角线上的数字(如左上角小方阵部分),换成和它互补的数。
实现代码
import math
# 魔方阵又称幻方
class MFZ():
def __init__(self):
self.n = int(input("请输入您要创建几阶魔法阵:"))
def main(self):
if self.n % 2 == 1:
self.mFZJ(self.n)
elif self.n % 2 == 0:
if self.n % 4 == 0:
self.mFZO1(self.n)
elif self.n % 4 == 2:
self.mFZO2(self.n)
def mFZJ(self,n):
'''魔方阵奇数阶算法
# 一居上行正中央:数字 1 放在首行最中间的格子中;。
# 依次斜填切莫忘:向右上角斜行,依次填入数字;
# 上出框时向下放:如果右上方向出了上边界,就以出框后的虚拟方格位置为基准
# ,将数字竖直降落至底行对应的格子中 。
# 右出框时向左放:同上,向右出了边界,就以出框后的虚拟方格位置为基准,
# 将数字平移至最左列对应的格子中;。
# 排重便在下格填:如果数字右上的格子已被其它数字占领,
# 就将 填写在下面的格子中;
# 右上排重一个样:如果朝右上角出界,和上面重复的情况做同样处理。'''
n = self.n
erWei = [[0] * n for i in range(n)]
num_h = list(range(1, n ** 2 + 1))
F1 = math.floor(n / 2) # 第一个数组1所在数组 的下标位置;
erWei[0][F1] = 1
HH = n * (n ** 2 + 1) / 2 # 阶幻和
n1 = 0 # erwei[n1][n2]
n2 = F1
for i in range(len(num_h) - 1): # 斜填
if n1 == 0 and n2 == n - 1:
erWei[n1 + 1][n2] = num_h[i + 1]
n1 = n1 + 1
elif n1 == 0:
erWei[n - 1][n2 + 1] = num_h[i + 1]
n1 = n - 1
n2 = n2 + 1
elif n2 == n - 1:
erWei[n1 - 1][0] = num_h[i + 1]
n1 = n1 - 1
n2 = 0
else:
if erWei[n1 - 1][n2 + 1] == 0:
erWei[n1 - 1][n2 + 1] = num_h[i + 1]
n1 = n1 - 1
n2 = n2 + 1
elif erWei[n1 - 1][n2 + 1] != 0:
erWei[n1 + 1][n2] = num_h[i + 1]
n1 = n1 + 1
for i in erWei: ## 这个方法是用来用空格分隔每个数字输出
for j in i:
print(j, end='\t\t')
print()
print("幻和为:%d" % HH)
# 以下代码用来验证幻方
# for i in range(0, n):
# sum = 0
# for j in range(0, n):
# sum += erWei[i][j]
# print("The sum of column %d is:%d" % (i + 1, sum))
#
# for j in range(0, n):
# sum = 0
# for i in range(0, n):
# sum += erWei[i][j]
# print("The sum of row %d is:%d" % (j + 1, sum))
# i = 0
# sum = 0
# for i in range(0, n):
# sum += erWei[i][j]
# i = i + 1
# print("左上右下对角线和为:", sum)
# i = 0
# sum = 0
# for i in range(0, n):
# sum += erWei[i][j]
# i = i + 1
# print("左下右上对角线和为:", sum)
# print("幻方和为:%d" % HH)
# return erWei
###########################################################################
# 4k阶幻方
def mFZO1(self, n):
n = self.n
erWei = [[0] * n for i in range(n)]
num_h = list(range(1, n ** 2 + 1))
HH = n * (n ** 2 + 1) / 2 # 阶幻和
for i in range(len(erWei)):
for j in range(len(erWei[i])):
erWei[i][j] = num_h[i * n + j]
k = int(n / 4) # 求解k值
zfxxb = [] # 正方形下标列表
# erWei[0][0]-erWei[k-1][k-1] # 第一个小正方形
for i in range(k):
for j in range(k):
zfxxb.append([i, j])
# erWei[0][n-1]-erWei[k-1][n-k]# 第二个
for i in range(k):
for j in range(n - k, n):
zfxxb.append([i, j])
# erWei[n-1][0]-erWei[n-k][k-1]#第三个
for i in range(n - k, n):
for j in range(k):
zfxxb.append([i, j])
# erWei[n-1][n-1]-erWei[n-3][n-3]# 第四个
for i in range(n - k, n):
for j in range(n - k, n):
zfxxb.append([i, j])
#
# erWei[k-1][k-1]-erWei[n-k][n-k] # 中间
for i in range(k, n - k):
for j in range(k, n - k):
zfxxb.append([i, j])
for i in range(len(erWei)):
for j in range(len(erWei[i])):
for p in zfxxb:
if p == [i, j]:
num_h.remove(erWei[i][j])
zfxxb.remove(p)
break
if p != [i, j]:
erWei[i][j] = 0
i = n - 1
j = n - 1
while i >= 0:
while j >= 0:
if erWei[i][j] == 0:
erWei[i][j] = num_h[0]
del num_h[0]
j -= 1
j = n - 1
i -= 1
for i in erWei: ## 这个方法是用来用空格分隔每个数字输出
for j in i:
print(j, end='\t\t')
print()
print("幻和为:%d" % HH)
#######################################################################################################
# 4k+2阶幻方
def mFZO2(self, n):
n = self.n
nn = int(n / 2)
a1 = []
b1 = []
c1 = []
d1 = []
for o in range(4): # 循环四次
s = o * (nn * nn) + 1 # s是num_h开始的数
erWei = [[0] * nn for i1 in range(nn)]
num_h = list(range(s, s + nn ** 2))
F1 = math.floor(nn / 2) # 第一个数组1所在数组 的下标位置;
erWei[0][F1] = num_h[0]
HH = n * (n ** 2 + 1) / 2 # 奇偶数阶幻和
n1 = 0 # erwei[n1][n2]
n2 = F1
for i2 in range(len(num_h) - 1): # 斜填
if n1 == 0 and n2 == nn - 1:
erWei[n1 + 1][n2] = num_h[i2 + 1]
n1 = n1 + 1
elif n1 == 0:
erWei[nn - 1][n2 + 1] = num_h[i2 + 1]
n1 = nn - 1
n2 = n2 + 1
elif n2 == nn - 1:
erWei[n1 - 1][0] = num_h[i2 + 1]
n1 = n1 - 1
n2 = 0
else:
if erWei[n1 - 1][n2 + 1] == 0:
erWei[n1 - 1][n2 + 1] = num_h[i2 + 1]
n1 = n1 - 1
n2 = n2 + 1
elif erWei[n1 - 1][n2 + 1] != 0:
erWei[n1 + 1][n2] = num_h[i2 + 1]
n1 = n1 + 1
if o == 0:
a1 = erWei
elif o == 1:
b1 = erWei
elif o == 2:
c1 = erWei
elif o == 3:
d1 = erWei
for i3 in range(len(a1)):
if i3 != F1:
for j1 in range(F1):
d1[i3][j1], a1[i3][j1] = a1[i3][j1], d1[i3][j1]
elif i3 == F1:
for j2 in range(F1, 2 * F1):
d1[i3][j2], a1[i3][j2] = a1[i3][j2], d1[i3][j2]
for i4 in range(len(c1)):
for j3 in range(2, F1 + 1):
b1[i4][j3], c1[i4][j3] = c1[i4][j3], b1[i4][j3]
zl = [[0] * n for i5 in range(n)] # 最终的队列
for i6 in range(len(zl)):
if i6 <= (nn - 1):
for j4 in range(len(zl)):
if j4 <= (nn - 1):
zl[i6][j4] = a1[i6][j4]
else:
zl[i6][j4] = c1[i6][j4 - nn]
else:
for j5 in range(len(zl)):
if j5 <= (nn - 1):
zl[i6][j5] = d1[i6 - nn][j5]
else:
zl[i6][j5] = b1[i6 - nn][j5 - nn]
for i7 in zl:
for j6 in i7:
print(j6, end="\t\t")
print()
print("幻和为:%d" % HH)
MFZ_test = MFZ()
MFZ_test.main()