幻方根据阶数不同可分为奇阶幻方、单偶幻方和双偶阶幻方。对于奇阶幻方的构造,可以通过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
5
using namespace std;
6
7
/**
8
* 幻方类,可以计算奇阶幻方,双偶阶幻方,单偶阶幻方
9
* 目前单偶阶幻方还有点问题。
10
* 构造方法:
11
* 奇阶幻方: Loubere法
12
* 双偶阶幻方:Spring法
13
* 单偶阶幻方:Strachey法
14
*
15
* zyl 2008.1.21
16
*/
17
typedef int MT;
18
19
class Magic
20
{
21
private:
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);
32
public:
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
42
void Magic::setsize(int size)
43
{
44
if(size <= 2)
45
return;
46
this->size = size;
47
}
48
49
int Magic::getsize()const
50
{
51
return size;
52
}
53
54
void Magic::swap(MT &v1, MT &v2)
55
{
56
MT temp = v1;
57
v1 = v2;
58
v2 = temp;
59
}
60
61
void 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
74
void 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
84
void 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
103
Magic::Magic()
104
{
105
size = 0;
106
matrix = NULL;
107
}
108
109
Magic::Magic(int size)
110
{
111
this->size = size;
112
matrix = NULL;
113
}
114
115
Magic::~Magic()
116
{
117
deletematrix();
118
}
119
120
void 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
139
void 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
157
void 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
192
void 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
218
void 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
251
int 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

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270
