一个生成幻方的类(C++)[原创]

描述

幻方根据阶数不同可分为奇阶幻方、单偶幻方和双偶阶幻方。对于奇阶幻方的构造,可以通过Loubere法,即不断地向右上角填数。遇到有数的格折回来再填。对于双偶阶幻方,可以用Spring法构造:以行为主序列将1-n^2依次填入到方格,然后再将幻方平分四块,左上角的那一块i+j等于偶数的方格的数字与它的中心对称方格的交换,右上角的那一块i+j等奇数的方格的数字与它中心对称方格进行交换。单偶阶幻方可以划分成

AC
DB

四块,每块为一个奇阶幻方,然后将构造四个幻方,再将A幻方的m列与D的对应列进行交换,Bm-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
原文地址:https://www.cnblogs.com/qkhh/p/1047975.html