幻方根据阶数不同可分为奇阶幻方、单偶幻方和双偶阶幻方。对于奇阶幻方的构造,可以通过Loubere法,即不断地向右上角填数。遇到有数的格折回来再填。对于双偶阶幻方,可以用Spring法构造:以行为主序列将1-n^2依次填入到方格,然后再将幻方平分四块,左上角的那一块i+j等于偶数的方格的数字与它的中心对称方格的交换,右上角的那一块i+j等奇数的方格的数字与它中心对称方格进行交换。单偶阶幻方可以划分成
AC
DB
四块,每块为一个奇阶幻方,然后将构造四个幻方,再将A幻方的m列与D的对应列进行交换,B的m-1列与C的对应列进行交换。(这个算法好像有问题,计算6阶幻方时没有问题,但计算10阶时有问题)。
实现
用一个Magic类封装,只需要给定一个幻方的阶数,它会自动判断阶数然后调用相应的构造方法。
奇阶幻方的构造调用:filloddmagic
单偶阶幻方的构造调用:fill2timesmagic
双偶阶幻方的构造调用:fill4timesmagic
1#include <iostream>
2#include <iomanip>
3#include <stdlib.h>
4
5using namespace std;
6
7/**
8* 幻方类,可以计算奇阶幻方,双偶阶幻方,单偶阶幻方
9* 目前单偶阶幻方还有点问题。
10* 构造方法:
11* 奇阶幻方: Loubere法
12* 双偶阶幻方:Spring法
13* 单偶阶幻方:Strachey法
14*
15* zyl 2008.1.21
16*/
17typedef int MT;
18
19class Magic
20{
21private:
22 MT **matrix;
23 int size;
24
25 void zeromatrix();
26 void deletematrix();
27 void filloddmagic();
28 void fill2timesmagic();
29 void fill4timesmagic();
30 void movenext(int &i, int &j);
31 inline void swap(MT &v1, MT &v2);
32public:
33 Magic();
34 Magic(int size);
35 virtual ~Magic();
36 inline void setsize(int size);
37 inline int getsize()const;
38 void dofill();
39 void printmagic();
40};
41
42void Magic::setsize(int size)
43{
44 if(size <= 2)
45 return;
46 this->size = size;
47}
48
49int Magic::getsize()const
50{
51 return size;
52}
53
54void Magic::swap(MT &v1, MT &v2)
55{
56 MT temp = v1;
57 v1 = v2;
58 v2 = temp;
59}
60
61void Magic::zeromatrix()
62{
63 if(matrix == NULL)
64 return;
65
66 for(int i=0;i<size;i++)
67 {
68// memset(matrix, 0, size * sizeof(MT));
69 for(int j=0;j<size;j++)
70 matrix[i][j] = 0;
71 }
72}
73
74void Magic::deletematrix()
75{
76 if(matrix == NULL)
77 return;
78 for(int i=0;i<size;i++)
79 delete []matrix[i];
80 delete []matrix;
81 matrix = NULL;
82}
83
84void Magic::movenext(int &i, int &j)
85{
86 if(i == 0 && j == size - 1)
87 {
88 i++;
89 return;
90 }
91 //i = (--i)%size;
92 i = (i + size - 1)%size;
93 j = (j + 1)%size;
94
95 if(matrix[i][j] > 0)
96 {
97 i = (i+2)%size;
98 //j = (j--)%size;
99 j = (j + size - 1)%size;
100 }
101}
102
103Magic::Magic()
104{
105 size = 0;
106 matrix = NULL;
107}
108
109Magic::Magic(int size)
110{
111 this->size = size;
112 matrix = NULL;
113}
114
115Magic::~Magic()
116{
117 deletematrix();
118}
119
120void Magic::dofill()
121{
122 if(size == 0)
123 return;
124 deletematrix();
125
126 matrix = new MT*[size];
127 for(int i=0;i<size;i++)
128 matrix[i] = new MT[size];
129
130 switch(size%4)
131 {
132 case 1:
133 case 3: filloddmagic(); break;
134 case 0: fill4timesmagic(); break;
135 case 2: fill2timesmagic(); break;
136 }
137}
138
139void Magic::filloddmagic()
140{
141 this->zeromatrix();
142 int i, j;
143
144 // 初始位置
145 i = 0;
146 j = (size - 1)/2;
147
148 for(MT v=1; v <= size * size; v++)
149 {
150 // fill
151 matrix[i][j] = v;
152 // get next pos
153 movenext(i, j);
154 }
155}
156
157void Magic::fill2timesmagic()
158{
159 int half = size/2;
160 Magic hm(half);
161 hm.dofill();
162
163 int i, j;
164 int step[4];
165 step[0] = 0;
166 step[1] = half * half;
167 step[2] = step[1] + step[1];
168 step[3] = step[2] + step[1];
169
170 // fill
171 for(i=0; i<half;i++)
172 for(j=0;j<half;j++)
173 {
174 matrix[i][j] = hm.matrix[i][j] + step[0]; // A
175 matrix[i][j + half] = hm.matrix[i][j] + step[2]; // C
176 matrix[i + half][j + half] = hm.matrix[i][j] + step[1]; // B
177 matrix[i + half][j] = hm.matrix[i][j] + step[3]; // D
178 }
179
180 // exchange
181 int m = (size - 2)>>2; // 右移,相当于除以4
182 int mm = size - (m - 1);
183 for(i=0;i<half;i++)
184 for(j=0;j<m;j++)
185 {
186 swap(matrix[i][j], matrix[i + half][j]);
187 if(j > 0)
188 swap(matrix[i][j + mm], matrix[i + half][j + mm]);
189 }
190}
191
192void Magic::fill4timesmagic()
193{
194 int v = 0;
195 int i, j;
196 for(i=0;i<size;i++)
197 for(j=0;j<size;j++)
198 matrix[i][j] = ++v;
199 // exchange
200 i=0, j=0;
201 int before = size/2 - 1;
202
203 for(i=0;i<=before;i++)
204 {
205 // 左半部分
206 j = (i%2==0? 0:1);
207 for(;j<=before;j+=2)
208 swap(matrix[i][j], matrix[size-i-1][size-j-1]);
209 // 右半部分的
210 j--;
211 if(j<=before)
212 j += 2;
213 for(; j<=size-1; j+=2)
214 swap(matrix[i][j], matrix[size-i-1][size-j-1]);
215 }
216}
217
218void Magic::printmagic()
219{
220 if(matrix == NULL)
221 return;
222
223 int w = 1;
224 if(size>= 4 && size <= 9)
225 w = 2;
226 else if(size>= 10 && size <= 31)
227 w = 3;
228 else if(size>= 32 && size <= 99)
229 w = 4;
230
231 for(int i=0;i<size;i++)
232 {
233 for(int j=0;j<size;j++)
234 cout<<setw(w)<<matrix[i][j]<<' ';
235 cout<<endl;
236 }
237
238 cout<<endl;
239 int total = 0;
240 for(int j=0;j<size;j++)
241 total += matrix[0][j];
242 cout<<"第0行和:"<<total<<endl;
243
244 total = 0;
245 for(int j=0;j<size;j++)
246 total += matrix[j][0];
247 cout<<"第0列和:"<<total<<endl;
248}
249
250
251int main(int argc, char *argv[])
252{
253 int size;
254 cout<<"输入幻方的阶数(>=3):";
255 cin>>size;
256 cout<<endl;
257
258 if(size <= 2)
259 return 0;
260 Magic m;
261 m.setsize(size);
262 m.dofill();
263 m.printmagic();
264
265
266 system("PAUSE");
267 return 0;
268}
269
270
2#include <iomanip>
3#include <stdlib.h>
4
5using namespace std;
6
7/**
8* 幻方类,可以计算奇阶幻方,双偶阶幻方,单偶阶幻方
9* 目前单偶阶幻方还有点问题。
10* 构造方法:
11* 奇阶幻方: Loubere法
12* 双偶阶幻方:Spring法
13* 单偶阶幻方:Strachey法
14*
15* zyl 2008.1.21
16*/
17typedef int MT;
18
19class Magic
20{
21private:
22 MT **matrix;
23 int size;
24
25 void zeromatrix();
26 void deletematrix();
27 void filloddmagic();
28 void fill2timesmagic();
29 void fill4timesmagic();
30 void movenext(int &i, int &j);
31 inline void swap(MT &v1, MT &v2);
32public:
33 Magic();
34 Magic(int size);
35 virtual ~Magic();
36 inline void setsize(int size);
37 inline int getsize()const;
38 void dofill();
39 void printmagic();
40};
41
42void Magic::setsize(int size)
43{
44 if(size <= 2)
45 return;
46 this->size = size;
47}
48
49int Magic::getsize()const
50{
51 return size;
52}
53
54void Magic::swap(MT &v1, MT &v2)
55{
56 MT temp = v1;
57 v1 = v2;
58 v2 = temp;
59}
60
61void Magic::zeromatrix()
62{
63 if(matrix == NULL)
64 return;
65
66 for(int i=0;i<size;i++)
67 {
68// memset(matrix, 0, size * sizeof(MT));
69 for(int j=0;j<size;j++)
70 matrix[i][j] = 0;
71 }
72}
73
74void Magic::deletematrix()
75{
76 if(matrix == NULL)
77 return;
78 for(int i=0;i<size;i++)
79 delete []matrix[i];
80 delete []matrix;
81 matrix = NULL;
82}
83
84void Magic::movenext(int &i, int &j)
85{
86 if(i == 0 && j == size - 1)
87 {
88 i++;
89 return;
90 }
91 //i = (--i)%size;
92 i = (i + size - 1)%size;
93 j = (j + 1)%size;
94
95 if(matrix[i][j] > 0)
96 {
97 i = (i+2)%size;
98 //j = (j--)%size;
99 j = (j + size - 1)%size;
100 }
101}
102
103Magic::Magic()
104{
105 size = 0;
106 matrix = NULL;
107}
108
109Magic::Magic(int size)
110{
111 this->size = size;
112 matrix = NULL;
113}
114
115Magic::~Magic()
116{
117 deletematrix();
118}
119
120void Magic::dofill()
121{
122 if(size == 0)
123 return;
124 deletematrix();
125
126 matrix = new MT*[size];
127 for(int i=0;i<size;i++)
128 matrix[i] = new MT[size];
129
130 switch(size%4)
131 {
132 case 1:
133 case 3: filloddmagic(); break;
134 case 0: fill4timesmagic(); break;
135 case 2: fill2timesmagic(); break;
136 }
137}
138
139void Magic::filloddmagic()
140{
141 this->zeromatrix();
142 int i, j;
143
144 // 初始位置
145 i = 0;
146 j = (size - 1)/2;
147
148 for(MT v=1; v <= size * size; v++)
149 {
150 // fill
151 matrix[i][j] = v;
152 // get next pos
153 movenext(i, j);
154 }
155}
156
157void Magic::fill2timesmagic()
158{
159 int half = size/2;
160 Magic hm(half);
161 hm.dofill();
162
163 int i, j;
164 int step[4];
165 step[0] = 0;
166 step[1] = half * half;
167 step[2] = step[1] + step[1];
168 step[3] = step[2] + step[1];
169
170 // fill
171 for(i=0; i<half;i++)
172 for(j=0;j<half;j++)
173 {
174 matrix[i][j] = hm.matrix[i][j] + step[0]; // A
175 matrix[i][j + half] = hm.matrix[i][j] + step[2]; // C
176 matrix[i + half][j + half] = hm.matrix[i][j] + step[1]; // B
177 matrix[i + half][j] = hm.matrix[i][j] + step[3]; // D
178 }
179
180 // exchange
181 int m = (size - 2)>>2; // 右移,相当于除以4
182 int mm = size - (m - 1);
183 for(i=0;i<half;i++)
184 for(j=0;j<m;j++)
185 {
186 swap(matrix[i][j], matrix[i + half][j]);
187 if(j > 0)
188 swap(matrix[i][j + mm], matrix[i + half][j + mm]);
189 }
190}
191
192void Magic::fill4timesmagic()
193{
194 int v = 0;
195 int i, j;
196 for(i=0;i<size;i++)
197 for(j=0;j<size;j++)
198 matrix[i][j] = ++v;
199 // exchange
200 i=0, j=0;
201 int before = size/2 - 1;
202
203 for(i=0;i<=before;i++)
204 {
205 // 左半部分
206 j = (i%2==0? 0:1);
207 for(;j<=before;j+=2)
208 swap(matrix[i][j], matrix[size-i-1][size-j-1]);
209 // 右半部分的
210 j--;
211 if(j<=before)
212 j += 2;
213 for(; j<=size-1; j+=2)
214 swap(matrix[i][j], matrix[size-i-1][size-j-1]);
215 }
216}
217
218void Magic::printmagic()
219{
220 if(matrix == NULL)
221 return;
222
223 int w = 1;
224 if(size>= 4 && size <= 9)
225 w = 2;
226 else if(size>= 10 && size <= 31)
227 w = 3;
228 else if(size>= 32 && size <= 99)
229 w = 4;
230
231 for(int i=0;i<size;i++)
232 {
233 for(int j=0;j<size;j++)
234 cout<<setw(w)<<matrix[i][j]<<' ';
235 cout<<endl;
236 }
237
238 cout<<endl;
239 int total = 0;
240 for(int j=0;j<size;j++)
241 total += matrix[0][j];
242 cout<<"第0行和:"<<total<<endl;
243
244 total = 0;
245 for(int j=0;j<size;j++)
246 total += matrix[j][0];
247 cout<<"第0列和:"<<total<<endl;
248}
249
250
251int main(int argc, char *argv[])
252{
253 int size;
254 cout<<"输入幻方的阶数(>=3):";
255 cin>>size;
256 cout<<endl;
257
258 if(size <= 2)
259 return 0;
260 Magic m;
261 m.setsize(size);
262 m.dofill();
263 m.printmagic();
264
265
266 system("PAUSE");
267 return 0;
268}
269
270