C#输出N阶魔方方阵(带校验)[原创]

昨天同事发了个图片过来,要求输出N阶魔方的,横竖跟对角线的和都相等!

所以就研究了一下,感觉里面的算法比较容易把人搞晕,C#代码如下:

using System;

namespace MagiCube
{
class Program
{
static void Main(string[] args)
{
int n = 0;
bool parseOK = false;
bool exit = false;
do
{
do
{
try
{
Console.Clear();
Console.WriteLine(
"请输入魔方的阶数:");
n
= Int32.Parse(Console.ReadLine());
if (n < 3 || n > 99)
{
Console.WriteLine(
"输入的数字不能小于3或大于99,请重试!");
Console.ReadKey();
parseOK
= false;
continue;
}
parseOK
= true;
}
catch (FormatException)
{
Console.WriteLine(
"输入的不是整数,请重试!");
parseOK
= false;
Console.ReadKey();
}
}
while (!parseOK);
GetData(n,
true);
Console.WriteLine(
"是否继续运行?(按“Y”继续,否则退出!)");
exit
= (Console.ReadKey().Key.ToString().ToLower() == "y" ? false : true);
}
while (!exit);
}

public static void GetData(int n,bool checkSum) //根据n的值决定调用的函数,并输出结果
{
int[,] N = new int[n, n];
if (n % 2 != 0) //n为基数时
{
N
= Odd(n);
}
else if (n % 4 == 0) //n为4的倍数时
{
N
= Even(n);
}
else if (n % 4 == 2) //n为非4的倍数的其他偶数时(n%4==2)
{
N
= Even2(n);
}
//else
//{
// Console.WriteLine("无法处理数字 {0} !", n);
//}
Console.WriteLine(new string('=', 50));
Print(N);
if (checkSum)
{
Console.WriteLine(
new string('=', 50));
CheckSum(N);
}
Console.WriteLine(
new string('=', 50));
}

public static void CheckSum(int[,] N) //输出N阶魔方每行每列及对角线的和
{
int row = N.GetLength(0);
int col = N.GetLength(1);
int sumrow = 0;
int sumcol = 0;
int sumdia = 0;
for (int x = 0; x < row; x++)
{
for (int y = 0; y < col; y++)
{
sumrow
+= N[x, y];
sumcol
+= N[y, x];
}
Console.WriteLine(
"行{0}:{1},列{0}:{1}", x + 1, sumrow, x + 1, sumcol);
sumrow
= 0;
sumcol
= 0;
}
for (int m = 0; m < row; m++)
{
sumdia
+= N[m, m];
}
Console.Write(
"对角线1:{0},", sumdia);
sumdia
= 0;
int i = 0;
for (int j = (col - 1); j >= 0; j--)
{
sumdia
+= N[i, j];
}
Console.WriteLine(
"对角线2:{0}", sumdia);
}

public static int[,] Odd(int n) //n为基数时
{
int[,] N = new int[n, n];
int x = 0;
int y = (n - 1) / 2;
for (int i = 1; i <= n * n; i++)
{
x
= (x < 0 ? (n + x) : (x > (n - 1) ? (x - n) : x));
y
= (y > (n - 1) ? (y - n) : (y < 0 ? (n + y) : y));
if (N[x, y] == 0)
{
if ((i % n) == 0 && i != 1)
{
N[x
++, y] = i;
}
else
{
N[x
--, y++] = i;
}
}
}
return N;
}

public static int[,] Even(int n) //n为4的倍数时
{
int[,] N = new int[n, n];
/*消去对角线法
* 适用:四之倍数阶魔方阵
* 方法:(1)先将整个方阵划分成k*k个4阶方阵,然后在每个4阶方阵的对角线上做记号
* (2)由左而右、由上而下,遇到没有记号的位置才填数字,但不管是否填入数字,每移动一格数字都要加1
* (3)自右下角开始,由右而左、由下而上,遇到没有数字的位置就填入数字,但每移动一格数字都要加1
* 参考:
http://blog.dns0351.com/article/DailyBlog/479.htm
*/
for (int x = 0; x < n; x += 4)
{
for (int y = 0; y < n; y += 4)
{
N[x, y]
= 1;
N[x
+ 3, y + 3] = 1;

N[x
+ 1, y + 1] = 1;
N[x
+ 2, y + 2] = 1;

N[x, y
+ 3] = 1;
N[x
+ 3, y] = 1;

N[x
+ 1, y + 2] = 1;
N[x
+ 2, y + 1] = 1;
}
}
int m = n * n;
for (int i = 1; i <= n * n; i++)
{
if (N[(i - 1) / n, (i - 1) % n] != 1)
{
N[(i
- 1) / n, (i - 1) % n] = i;
}
else
{
N[(i
- 1) / n, (i - 1) % n] = m;
}
m
--;
}
return N;
}

public static int[,] Even2(int n) //n为非4的倍数的其他偶数时(n%4==2)
{
/* n为非4的倍数的其他偶数时,划分成四个奇数方阵示意图
* |
* B区(次小) | C区(次大)
* ---------------------------
* D区(最大) | A区(最小)
* |
*/
int[,] N = new int[n, n];
int[,] initN = Odd(n / 2);
int v = n * n / 4;
for (int x = 0; x < n / 2; x++)
{
for (int y = 0; y < n / 2; y++)
{
N[x
+ n / 2, y + n / 2] = initN[x, y]; //A区
N[x, y] = initN[x, y] + v; //B区
N[x, y + n / 2] = initN[x, y] + 2 * v; //C区
N[x + n / 2, y] = initN[x, y] + 3 * v; //D区
}
}
int tmp;
int m = (n - 2) / 4;
if (m > 1)
{
for (int i = 0; i <= m - 2; i++)
{
for (int j = 0; j < n / 2; j++)
{
tmp
= N[i, j];
N[i, j]
= N[i, n / 2 + j];
N[i, n
/ 2 + j] = tmp;
}
}
}
for (int i = n - m; i < n; i++)
{
for (int j = 0; j < n / 2; j++)
{
tmp
= N[i, j];
N[i, j]
= N[i, n / 2 + j];
N[i, n
/ 2 + j] = tmp;
}
}
tmp
= N[n / 2 + m, m];
N[n
/ 2 + m, m] = N[n / 2 + m, n / 2 + m];
N[n
/ 2 + m, n / 2 + m] = tmp;
tmp
= N[n - 1, m];
N[n
- 1, m] = N[n - 1, n / 2 + m];
N[n
- 1, n / 2 + m] = tmp;
return N;
}

public static void Print(int[,] N)
{
int maxLength = 4;
int preLen = 0;
for (int i = 0; i < N.GetLength(0); i++)
{
for (int j = 0; j < N.GetLength(1); j++)
{
Console.Write(
new String(' ', maxLength - preLen));
Console.Write(N[i, j]);
preLen
= N[i, j].ToString().Length;
}
for (int k = 0; k < maxLength - 2; k++)
{
Console.WriteLine(
"");
}
preLen
= 0;
}
}
}
}
原文地址:https://www.cnblogs.com/mic86/p/1905988.html