65.9K
CodeProject 正在变化。 阅读更多。
Home

魔方

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2015年2月2日

CPOL

3分钟阅读

viewsIcon

36537

downloadIcon

364

生成奇数和双偶数阶魔方的代码。

引言

在数学中,魔方是魔方的三维等价物,即,将一些整数排列在一个 n x n x n 的模式中,使得每一行、每一列、每一柱以及四个主空间对角线的数字之和等于一个单独的数字,即所谓的魔方常数。

术语

  • 阶数 - n x n x n 魔方中 n 的值。
  • 魔方常数 - 任何行、列、柱或对角线的唯一和。其值为 n(n3+1)/2

奇数魔方的扩展暹罗法

暹罗法是一种构造奇数阶魔方的方法。这种方法可以扩展到三维来构造魔方。假设读者理解暹罗法。

我们可以使用索引表示法来表示任何魔方,例如 [1,2,3],它代表魔方的第 1 层、第 2 行和第 3 列。索引从 [0,0,0] 开始,索引的最大值为 [n-1,n-1,n-1]。

任何移动都会循环(就像吃豆人或黑客帝国中的列车隧道一样)。-1 值等同于 n-1,n 等同于 0。

我们从一个空的魔方开始。步骤

  1. 将数字 1 放置在顶层中间 [0,(n-1)/2,(n-1)/2]。
  2. 让我们将当前位置表示为 [l,r,c]。
  3. 移动到 [l-1,r,c-1]。
  4. 如果 [l-1,r,c-1] 已经被占用,则移动到 [l-1,r-1,c]。
  5. 如果 [l-1,r-1,c] 也被占用,则移动到 [l+1,r,c]。
  6. 用下一个数字填充当前单元格,并从第 2 步开始迭代,直到所有单元格都填充了从 1 到 n3 的数字。

双偶数魔方

创建魔方的逻辑可以从以下魔方扩展而来

1 15 14 4
12 6 7 9
8 10 11 5
13 3 2 16

上述魔方可以按照以下方式创建。

从左上角开始填充正方形。如果数字位于红色方框中,则填充该数字,否则用 17-数字(或 n2+1-数字)填充。

让我们将红色定义为奇偶校验 0,蓝色定义为奇偶校验 1。

计算魔方索引 [r,c] 奇偶校验的逻辑

int nBy4 = n / 4;
boolean parity = false;
if (r >= nBy4 && r < 3 * nBy4) {
	parity = true;
}
if (c >= nBy4 && c < 3 * nBy4) {
	parity = !parity;
}

类似地,可以构造一个魔方。

单偶数魔方

这里的逻辑变得有些复杂,因此超出了本文的范围。可以使用 Medjig 方法来构造这些魔方。在演示源代码中,我还包含生成任何阶魔方(包括单偶数魔方)的代码。相同的逻辑可以扩展到生成立方体。

代码

这段代码非常简单。

public static int[][][] getMagicCube(int n) {
	if (n % 2 == 1) {
		int[][][] magicCube = new int[n][n][n];
		// layer index, row index, column index
		int l, r, c;
		l = 0;
		r = n / 2;
		c = n / 2;

		// If you want to port this code in C++
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				for (int k = 0; k < magicCube.length; k++) {
					magicCube[i][j][k] = 0;
				}
			}
		}

		int last = (int) Math.pow(n, 3);
		for (int i = 0; i < last; i++) {
			magicCube[l][r][c] = i + 1;
			l--;
			l = normalize(n, l);
			c--;
			c = normalize(n, c);
			if (magicCube[l][r][c] != 0) {
				r--;
				r = normalize(n, r);
				c++;
				c = normalize(n, c);
				if (magicCube[l][r][c] != 0) {
					r++;
					r = normalize(n, r);
					l += 2;
					l = normalize(n, l);
				}
			}
		}

		return magicCube;
	} else if (n % 4 == 0) {
		int[][][] magicCube = new int[n][n][n];
		int lastPlusOne = (int) Math.pow(n, 3) + 1;
		int number = 1;
		int nBy4 = n / 4;
		for (int l = 0; l < n; l++) {
			for (int r = 0; r < n; r++) {
				for (int c = 0; c < magicCube.length; c++) {
					boolean parity = false;
					if (l >= nBy4 && l < 3 * nBy4) {
						parity = true;
					}
					if (r >= nBy4 && r < 3 * nBy4) {
						parity = !parity;
					}
					if (c >= nBy4 && c < 3 * nBy4) {
						parity = !parity;
					}						
					magicCube[l][r][c] = (parity) ? lastPlusOne - number: number;
					number++;
				}
			}
		}
		return magicCube;
	}

	throw new RuntimeException(
			"Singly even magic cubes are not returned by this method.");
}

// index should be between 0 to n-1
private static int normalize(int n, int index) {
	while (index < 0) {
		index = index + n;
	}
	while (index > n - 1) {
		index = index - n;
	}
	return index;
}

这个概念可以扩展到更高维度的立方体(超立方体)。您可以访问我的 网站,在那里您可以生成任何给定阶数和维度的魔方。

5 阶魔方的示例

由代码生成

第 1 层

109 77 75 43 11
97 70 38 6 104
65 33 1 124 92
28 21 119 87 60
16 114 82 55 48

第 2 层

15 108 76 74 42
103 96 69 37 10
91 64 32 5 123
59 27 25 118 86
47 20 113 81 54

第 3 层

41 14 107 80 73
9 102 100 68 36
122 95 63 31 4
90 58 26 24 117
53 46 19 112 85

第 4 层

72 45 13 106 79
40 8 101 99 67
3 121 94 62 35
116 89 57 30 23
84 52 50 18 111

第 5 层

78 71 44 12 110
66 39 7 105 98
34 2 125 93 61
22 120 88 56 29
115 83 51 49 17

 

© . All rights reserved.