所谓魔方阵是指这样的方阵,它的每一行,每一列和每条对角线之和均相等。n阶魔方阵由1~n*n,n*n个自然数组成,且阶数n只能为奇数。要生成这样的方阵,看似非常玄乎,但其实它只有简单的三条规则,如下:
①自然数1总是在方阵的第一行中间一列;
②从自然数2到自然数n*n依次按下列规则摆放:每一个数摆放的行数比前一个数的行数少1,列数多1(注意循环);
③如果按上面规则确定的位置已经被占用,则摆放在此位置的下方(注意循环)。
代码如下(编译环境Visual C++ 6.0):
//MagicCube.h
#ifndef CARL_SEN_MAGICCUBE_H
#define CARL_SEN_MAGICCUBE_H
#include <iostream>
using std::ostream;
class MagicCube {
private:
int n;
int** cube;
void setCube();
public:
MagicCube(int _n=1);
MagicCube(const MagicCube& mc);
MagicCube& operator=(const MagicCube& mc);
~MagicCube();
int getN() const {return n;}
friend ostream& operator<<(ostream& os, const MagicCube& mc);
};
#endif
//MagicCube.cpp
#include "MagicCube.h"
using std::invalid_argument;
using std::endl;
MagicCube::MagicCube(int _n): n(_n){
if(n<0||n%2==0) {
throw invalid_argument("invalid value n");
}
cube=new int*[n];
for(int i=0; i<n; ++i) {
cube[i]=new int[n];
}
setCube();
}
MagicCube::MagicCube(const MagicCube& mc) {
n=mc.n;
cube=new int*[n];
int i, j;
for(i=0; i<n; ++i) {
cube[i]=new int[n];
}
for(i=0; i<n; ++i) {
for(j=0; j<n; ++j) {
cube[i][j]=mc.cube[i][j];
}
}
}
MagicCube& MagicCube::operator=(const MagicCube& mc) {
if(&mc!=this) {
int i, j;
for(i=0; i<n; ++i) {
delete[] cube[i];
}
delete[] cube;
n=mc.n;
cube=new int*[n];
for(i=0; i<n; ++i) {
cube[i]=new int[n];
}
for(i=0; i<n; ++i) {
for(j=0; j<n; ++j) {
cube[i][j]=mc.cube[i][j];
}
}
}
return *this;
}
MagicCube::~MagicCube() {
for(int i=0; i<n; ++i) {
delete[] cube[i];
}
delete[] cube;
}
void MagicCube::setCube() {
int i, j;
for(i=0; i<n; ++i) {
for(j=0; j<n; ++j) {
cube[i][j]=0;
}
}
//规则一:将1放在第一行中间一列
int mid=n/2;
cube[0][mid]=1;
//按魔方阵的第二、三条规则处理其它自然数(2到n*n)
int proRowNum=0, proColNum=mid;
int curRowNum, curColNum;
for(int num=2; num<=n*n; ++num) {
//规则二:当前这个自然数的位置是前一自然数位置的行标减1,列标加1
curRowNum=(proRowNum+n-1)%n;
curColNum=(proColNum+1)%n;
//规则三:如果计算出来的位置已被占用,则放在该位置的下方
if(cube[curRowNum][curColNum]!=0) {
curRowNum=(proRowNum+1)%n;
curColNum=proColNum;
}
cube[curRowNum][curColNum]=num;
proRowNum=curRowNum;
proColNum=curColNum;
}
}
ostream& operator<<(ostream& os, const MagicCube& mc) {
int i, j;
for(i=0; i<mc.n; ++i) {
for(j=0; j<mc.n; ++j) {
os<<mc.cube[i][j]<<"/t";
}
if(i!=mc.n-1) {
os<<endl;
}
}
return os;
}
//测试程序
#include <iostream>
#include "MagicCube.h"
using std::invalid_argument;
using std::cout;
using std::cerr;
using std::cin;
using std::endl;
int main() {
int n=0;
cout<<"MagicCube dimension 'n': (n>0 and n%2==1) ";
cin>>n;
try {
MagicCube mc(n);
cout<<"MagicCube["<<mc.getN()<<"]"<<endl;
cout<<mc<<endl;
}
catch(const invalid_argument& e) {
cerr<<e.what()<<endl;
}
return EXIT_SUCCESS;
}