幻方 C代码

幻方的解法:点击打开链接

互动百科:点击打开链接


直接上代码:

#include <stdio.h>
#define MAX_N 12	//幻方阶数 

//判断矩阵arr是否是幻方 
int CheckSquare(int arr[][MAX_N], int n)
{
	//计算幻方和 
	int sum = (n*n*n + n)/2;
	
	//检测各行各列的和是否等于幻方和 
	for(int i = 0; i < n; i ++){
		int rowSum = 0, colSum = 0;
		for(int j = 0; j < n; j ++){
			rowSum += arr[i][j];
			colSum += arr[j][i];
		}
		if(rowSum != sum || colSum != sum)
			return 0;
	}
	
	//检测对角线的和是否等于幻方和 
	int s1 = 0, s2 = 0;
	for(int i = 0; i < n; i ++){
		s1 += arr[i][i];
		s2 += arr[i][n - 1 - i];
	}
	
	return s1 == sum && s2 == sum;
}


//打印矩阵 
void PrintSquare(int arr[][MAX_N], int n)
{
	printf("S(%d) = %d\n", n, (n*n*n + n)/2);
	for(int i = 0; i < n; i ++){
		for(int j = 0; j < n; j ++)
			printf(" %3d", arr[i][j]);
		printf("\n");
	}
	printf(CheckSquare(arr, n) ? "Check Pass\n" : "Check Wrong\n");
	printf("\n");
}


//交换矩阵arr中两个位置的值 
void swap(int arr[][MAX_N], int x1, int y1, int x2, int y2)
{
	arr[x1][y1] ^= arr[x2][y2] ^= arr[x1][y1] ^= arr[x2][y2];
}


//填充n阶奇幻方(斜步法,这里是右上移动,还可以右下,左上,左下)
//以 s 开始填充 arr 中以 arr[si][sj]为偏移的n阶奇幻方 
void OddMagicSquare(int arr[][MAX_N], int si, int sj, int n, int s)
{
	for(int x = 0; x < n; x ++)
		for(int y = 0; y < n; y ++)
			arr[x][y] = 0;

	for(int i = 1, x = 0, y = (n - 1)/2; i <= n*n; i ++){
		arr[si + x][sj + y] = s + i - 1;
		
		if(n*n == i)
			break;
		
		//右上角或有数 
		if(0 == i%n)
			x ++;
		
		//向右上移动 
		else{
			x --;
			if(x == -1)
				x = n - 1;
				
			y ++;
			if(y == n)
				y = 0;
		}
	}
}


//填充n阶双偶幻方(Spring法) 
void TwoEventMagicSquare(int arr[][MAX_N], int n)
{
	for(int x = 0; x < n; x ++)
		for(int y = 0; y < n; y ++)
			arr[x][y] = x * n + y + 1;
	
	for(int x = 0; x < n/2; x ++)
		for(int y = 0; y < n; y ++)
			if((y + 1 <= n/2 && 0 == (x + y)%2) || (y + 1 > n/2 && 1 == (x + y)%2))
			{
				swap(arr, x, y, n - 1 - x, n - 1 - y); 
			}
}


//填充n阶单偶幻方
void OneEventMagicSquare(int arr[][MAX_N], int n)
{
	int m = (n - 2)/4, nn = (2*m + 1);
	
	//填充 A, B, C, D
	OddMagicSquare(arr, nn, 0, nn, 3*nn*nn + 1);
	OddMagicSquare(arr, 0, nn, nn, 2*nn*nn + 1);
	OddMagicSquare(arr, nn, nn, nn, nn*nn + 1);
	OddMagicSquare(arr, 0, 0, nn, 1);
	
	//在A阵中取左侧m列与D阵对应小格对调
	for(int i = 0; i < nn; i ++)
		for(int j = 0; j < m; j ++){
			if(i != (nn - 1)/2)
				swap(arr, i, j, nn + i, j);
		}
	//在A阵中间方格开始的m列与D阵对应小格对调
	for(int i = (nn - 1)/2, j = i, k = 1; k <= m; j ++, k ++)
		swap(arr, i, j, nn + i, j);
		
	//在C阵中取右侧m-1列与B阵对应小格对调
	for(int i = 0; i < nn; i ++)
		for(int j = 0; j < m - 1; j ++)
			swap(arr, i, nn + j, nn + i, nn + j);
}


int main()
{
	int arr[MAX_N][MAX_N] = {0};
	for(int n = 3; n <= MAX_N; n ++){
		//奇数 
		if(n & 1)
			OddMagicSquare(arr, 0, 0, n, 1);

		//偶数 
		else{
			//单偶数 
			if(n & 2)
				OneEventMagicSquare(arr, n); 

			//双偶数 
			else
				TwoEventMagicSquare(arr, n);
		}
		PrintSquare(arr, n);
	}
	return 0;
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值