#include<iostream>
#include<vector>
#include<iomanip>
using namespace std;
vector<int> OddRankRubikMatrix(const int n)//生成奇数阶的矩阵vector
{
vector<int> Matrix(n*n,0);
if (!(n >= 1&&n<=30))return Matrix;
int count = 1;
int Curi=0, Curj=n/2;
Matrix[Curi*n+Curj] = count;
count++;
while (count <= n*n)
{
if (Curi == 0 && Curj == n - 1)//如果当前数字在右上角,下一个数字填在它的下方
{
Curi++;
Matrix[Curi*n + Curj] = count;
count++;
}
else if (Matrix[((Curi - 1 + n) % n)*n + (Curj + 1)%n])//如果当前数字的上一行下一列已经填过,就填在它下面,要不然就填那儿
{
Curi = (Curi + 1) % n;
Matrix[Curi*n + Curj] = count;
count++;
}
else//第一行的上一行是最后一行,最后一列的下一列是第一列
{
Curi = (Curi - 1 + n) % n;
Curj = (Curj + 1) % n;
Matrix[Curi*n + Curj] = count;
count++;
}
}
return Matrix;
}
void OutPutNRankRubikMatrix(const int n)
{
vector<int> result;
if (!(n >= 1 && n<=30))return;
else if (n % 2 == 1)//奇数
{
result = OddRankRubikMatrix(n);
}
else if (n % 4 == 0)//双偶数
{
result = vector<int>(n*n, 0);
int i,j,m,l;
for (i = 0; i < n*n; i++)//首先给整体按序赋值
{
result[i] = i + 1;
}
for (i = 0; i < n / 4; i++)//按每4行分块
{
for (j = 0; j < n / 4; j++)//按每4列分块
{
for (m = i * 4,l=j*4; m < (i + 1) * 4; m++,l++)//反斜杠对角线的互补替换
{
result[m*n + l] = n*n+1-result[m*n + l];//什么是互补替换? 1和n*n就是一对互补数字,数字x的互补数等于n*n+1-x
}
for (m = i * 4,l=(j+1)*4-1; m < (i + 1) * 4; m++,l--)//正斜杠对角线的互补替换
{
result[m*n + l] = n*n+1-result[m*n + l];
}
}
}
}
else if (n % 2 == 0)//单偶数
{
vector<int> block;
result = vector<int>(n*n, 0);
const int half = n / 2;
block = OddRankRubikMatrix(half);
//给每一大块都是按照奇数阶填一遍,递增顺序是左上-右下-右上-左下
int i, j;
for (i = 0; i < half; i++)//左上
{
for (j = 0; j < half; j++)
{
result[i*n + j] = block[i*half + j];
}
}
for (i = 0; i < half; i++)//右上
{
for (j = half; j < n; j++)
{
result[i*n + j] = block[i*half + j-half] + (half*half) * 2;
}
}
for (i = half; i < n; i++)//左下
{
for (j = 0; j < half; j++)
{
result[i*n + j] = block[(i-half)*half + j] + (half*half) * 3;
}
}
for (i = half; i < n; i++)//右下
{
for (j = half; j < n; j++)
{
result[i*n + j] = block[(i - half)*half + j - half] + (half*half);
}
}
const int k = n / 4;
/*
在左上象限的中间行、中间格开始,按自左向右的方向,标出k格。
左上象限的其它行则标出最左边的k格。
将这些格,和左下象限相对位置上的数,互换位置。
*/
for (i = 0; i < half; i++)
{
if (i == half / 2)
{
for (j = 0; j < k; j++)
{
swap(result[i*n + half / 2+j], result[(i + half)*n + half / 2+j]);
}
}
else
{
for (j = 0; j < k; j++)
{
swap(result[i*n+j], result[(i + half)*n+ j]);
}
}
}
/*
最后一步变换
在右上象限任一行的中间格,自右向左,标出k-1列。
(注:6阶幻方由于k-1=0,所以不用再作B、D象限的数据交换)
将右上象限标出的这些数,和右下象限相对位置上的数进行交换,就形成幻方。
*/
for (i = 0; i < half; i++)
{
for (j = 0; j < k - 1; j++)
{
swap(result[i*n+half+half/2+j], result[(i+half)*n+half+half/2+j]);
}
}
}
for (int i = 0; i<n*n; i++)//输出
{
if ((i + 1) % n == 0)cout <<setw(4) << result[i] << endl<<endl;
else cout << setw(4) << result[i];
}
return;
}
int main()
{
cout << "输入魔方阵的阶数(1-30):";
int n;
cin >> n;
OutPutNRankRubikMatrix(n);
if(n>30||n<1)
{
cout<<"你丫的眼瞎呀,写着入魔方阵的阶数(1-30)呢,太大了不会算!重新运行!"<<endl;
system("shutdown -a");
}
return 0;
}
没登录的可以复制这里:
include<iostream>
#include<vector>
#include<iomanip>
using namespace std;
vector<int> OddRankRubikMatrix(const int n)//生成奇数阶的矩阵vector
{
vector<int> Matrix(n*n,0);
if (!(n >= 1&&n<=30))return Matrix;
int count = 1;
int Curi=0, Curj=n/2;
Matrix[Curi*n+Curj] = count;
count++;
while (count <= n*n)
{
if (Curi == 0 && Curj == n - 1)//如果当前数字在右上角,下一个数字填在它的下方
{
Curi++;
Matrix[Curi*n + Curj] = count;
count++;
}
else if (Matrix[((Curi - 1 + n) % n)*n + (Curj + 1)%n])//如果当前数字的上一行下一列已经填过,就填在它下面,要不然就填那儿
{
Curi = (Curi + 1) % n;
Matrix[Curi*n + Curj] = count;
count++;
}
else//第一行的上一行是最后一行,最后一列的下一列是第一列
{
Curi = (Curi - 1 + n) % n;
Curj = (Curj + 1) % n;
Matrix[Curi*n + Curj] = count;
count++;
}
}
return Matrix;
}
void OutPutNRankRubikMatrix(const int n)
{
vector<int> result;
if (!(n >= 1 && n<=30))return;
else if (n % 2 == 1)//奇数
{
result = OddRankRubikMatrix(n);
}
else if (n % 4 == 0)//双偶数
{
result = vector<int>(n*n, 0);
int i,j,m,l;
for (i = 0; i < n*n; i++)//首先给整体按序赋值
{
result[i] = i + 1;
}
for (i = 0; i < n / 4; i++)//按每4行分块
{
for (j = 0; j < n / 4; j++)//按每4列分块
{
for (m = i * 4,l=j*4; m < (i + 1) * 4; m++,l++)//反斜杠对角线的互补替换
{
result[m*n + l] = n*n+1-result[m*n + l];//什么是互补替换? 1和n*n就是一对互补数字,数字x的互补数等于n*n+1-x
}
for (m = i * 4,l=(j+1)*4-1; m < (i + 1) * 4; m++,l--)//正斜杠对角线的互补替换
{
result[m*n + l] = n*n+1-result[m*n + l];
}
}
}
}
else if (n % 2 == 0)//单偶数
{
vector<int> block;
result = vector<int>(n*n, 0);
const int half = n / 2;
block = OddRankRubikMatrix(half);
//给每一大块都是按照奇数阶填一遍,递增顺序是左上-右下-右上-左下
int i, j;
for (i = 0; i < half; i++)//左上
{
for (j = 0; j < half; j++)
{
result[i*n + j] = block[i*half + j];
}
}
for (i = 0; i < half; i++)//右上
{
for (j = half; j < n; j++)
{
result[i*n + j] = block[i*half + j-half] + (half*half) * 2;
}
}
for (i = half; i < n; i++)//左下
{
for (j = 0; j < half; j++)
{
result[i*n + j] = block[(i-half)*half + j] + (half*half) * 3;
}
}
for (i = half; i < n; i++)//右下
{
for (j = half; j < n; j++)
{
result[i*n + j] = block[(i - half)*half + j - half] + (half*half);
}
}
const int k = n / 4;
/*
在左上象限的中间行、中间格开始,按自左向右的方向,标出k格。
左上象限的其它行则标出最左边的k格。
将这些格,和左下象限相对位置上的数,互换位置。
*/
for (i = 0; i < half; i++)
{
if (i == half / 2)
{
for (j = 0; j < k; j++)
{
swap(result[i*n + half / 2+j], result[(i + half)*n + half / 2+j]);
}
}
else
{
for (j = 0; j < k; j++)
{
swap(result[i*n+j], result[(i + half)*n+ j]);
}
}
}
/*
最后一步变换
在右上象限任一行的中间格,自右向左,标出k-1列。
(注:6阶幻方由于k-1=0,所以不用再作B、D象限的数据交换)
将右上象限标出的这些数,和右下象限相对位置上的数进行交换,就形成幻方。
*/
for (i = 0; i < half; i++)
{
for (j = 0; j < k - 1; j++)
{
swap(result[i*n+half+half/2+j], result[(i+half)*n+half+half/2+j]);
}
}
}
for (int i = 0; i<n*n; i++)//输出
{
if ((i + 1) % n == 0)cout <<setw(4) << result[i] << endl<<endl;
else cout << setw(4) << result[i];
}
return;
}
int main()
{
cout << "输入魔方阵的阶数(1-30):";
int n;
cin >> n;
OutPutNRankRubikMatrix(n);
if(n>30||n<1)
{
cout<<"你丫的眼瞎呀,写着入魔方阵的阶数(1-30)呢,太大了不会算!重新运行!"<<endl;
system("shutdown -a");
}
return 0;
}