C++生成1-30阶魔方阵/纵横图/幻方-奇/偶阶(有些戏剧性)

#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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值