?
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <windows.h> 4 5 #define EVEN_DOUBLE_4 4 //雙偶的最基本類型,4階雙偶 6 #define SCREEN_SIZE 19 //屏幕顯示不變形的最大尺寸(主要是因為窗口大小限制) 7 #define MIN_SIZE 3 //最小階數為3 8 #define MAX_SIZE 30 9 /*原則上是任意階,算法是相同的,這里就以30為上限吧, 10 當然如果你愿意,可以修改的更大一些*/ 11 12 #define PRINT printf("Esc退出,Enter繼續"); //打印的宏 13 #define CLEAR row = 0; column = 0; //清零 14 15 int Magic[MAX_SIZE][MAX_SIZE]={0}; //全局,幻方數組 16 int row = 0; column = 0; //全局,幻方的行列數 17 18 19 int main(void) 20 { 21 int read(); //讀取函數 22 void odd(int size, int ini_value ); //奇數階幻方生成 23 void mean_double_4(int size); //4階雙偶生成 24 void mean_double(int size); //雙偶生成 25 void mean_single(int size); //單偶生成 26 void print_magic(int size); //打印幻方 27 void sum_print(int data[], int size); //行、列、對之和打印 28 void clear_sum(int data[]); 29 void check_magic(int data[], int size ); //檢查所得矩陣是否為幻方陣 30 31 int size; //幻方階數 32 int sum[2*MAX_SIZE+2] = {0};//行、列、對之和 33 34 do{ 35 CLEAR 36 clear_sum(sum); 37 size=read(); 38 system("cls"); 39 40 if(size%2 != 0 ) odd(size, 0); 41 else if(size %4 == 0) mean_double(size); 42 else mean_single(size); 43 44 print_magic(size); 45 sum_print(sum, size); 46 check_magic(sum,size); 47 PRINT 48 49 }while (getch() != 27); 50 51 return 0; 52 } 53 54 /*讀入數據*/ 55 int read() 56 { 57 int min_size = MIN_SIZE; 58 int max_size = MAX_SIZE; 59 int size; 60 61 do{ 62 printf("請輸入幻方階數n,n∈[%d,%d]\n", min_size, max_size); 63 scanf("%d", &size); 64 getchar(); 65 if(size<3 || size > MAX_SIZE) printf("非法輸入,請重新輸入[%d,%d]的正整數\n", min_size, max_size); 66 else if(size > SCREEN_SIZE){ 67 printf("大于屏顯最大階數,輸出將變形\n"); 68 Sleep(2000); 69 } 70 }while(size < MIN_SIZE || size > MAX_SIZE); 71 72 return size; 73 } 74 75 76 /*奇數階幻方,采用house法*/ 77 void odd(int size, int ini_value) 78 { 79 int num; //填充數字 80 int min_num = 1+ini_value; 81 int max_num = 1+size*size+ini_value; //填充范圍 82 int x = size/2; 83 int y = 0; //初始填充坐標 84 85 for(num = min_num; num < max_num; num++){ 86 Magic[y+row][x+column] = num; 87 if(num % size == 0) y++; //跳步 88 else x++, y += 2; //馬步,其實Horse法和Siamese是完全類似的 89 x = x % size ; 90 y = y % size ; 91 /*越界反彈,即觸碰到邊界,從另一邊返回*/ 92 } 93 } 94 95 /*雙偶數階幻方,采用對調法*/ 96 97 /*對調法的基礎,4階雙偶。注意要求是將非主副對角線上的元素對調, 98 其實換個角度,你也可以說就是把祝福對角線中心對調。只不過兩種思路得到的矩陣 99 正好是反著來的*/ 100 /*本函數實現主副對角線互調*/ 101 void mean_double_4(int size) 102 { 103 104 int i; 105 int total = size * size +1 ; 106 for(i = 0; i < EVEN_DOUBLE_4; i++){ 107 Magic[row+i][column+i] = total - Magic[row+i][column+i]; 108 Magic[row+i][ EVEN_DOUBLE_4+column-i-1] = 109 total - Magic[row+i][ EVEN_DOUBLE_4+column-i-1]; 110 } 111 112 } 113 114 /*任意階雙偶*/ 115 void mean_double(int size) 116 { 117 int num; //填充數字 118 int min_num = 1; 119 int max_num = 1+size*size; //填充范圍 120 int i = 0; //循環變量 121 int temp; 122 123 /*雙偶,初始化*/ 124 for(num = min_num; num < max_num; num++){ 125 Magic[row][column] = num; 126 if((num ) % (size ) == 0){ 127 column = 0, row++; 128 } 129 else column++; 130 } 131 132 133 /*分割為4×4的小矩陣*/ 134 row = 0; column = 0; 135 temp = size / EVEN_DOUBLE_4; 136 137 for(i = 1; i <=temp *temp; i++){ 138 mean_double_4(size); 139 if(i % temp == 0) column = 0, row += 4 ; 140 else column = (i % temp) * EVEN_DOUBLE_4; 141 } 142 } 143 144 145 /*單偶,用樓梯法*/ 146 void mean_single(int size) 147 { 148 int i,j,k,m; 149 int temp; 150 151 152 /*分象限處理, 153 14 154 32 155 與普通直角坐標系象限區別,說白了,就是個分塊的概念 156 */ 157 row = 0, column = 0; //第一象限 158 odd(size/2, 0); 159 160 row = size/2, column = size/2; //第二象限 161 odd(size/2, (size*size)/4*1); 162 163 row = 0, column = size/2; //第三象限 164 odd(size/2, (size*size)/4*2); 165 166 167 row = size/2, column = 0; //第四象限 168 odd(size/2, (size*size)/4*3); 169 170 m = size / 4; 171 172 /*對換*/ 173 for(i = 0; i< size/2; i++){ 174 /*1、3象限對換*/ 175 for(j = 0; j<m; j++ ){ 176 if(i == m) k = j + m; 177 else k = j; 178 temp = Magic[i][k]; 179 Magic[i][k] = Magic[i + 2*size/4 ][k]; 180 Magic[i + 2*size/4 ][k] = temp; 181 } 182 /*2,4對換*/ 183 for(j = 0; j<m-1; j++ ){ 184 k = 3*size/4 +j; 185 temp = Magic[i][k]; 186 Magic[i][k] = Magic[i + 2*size/4][k]; 187 Magic[i + 2*size/4][k] = temp; 188 } 189 } 190 } 191 192 /*打印幻方*/ 193 void print_magic(int size) 194 { 195 int i,j; 196 for(i = 0; i < size; i++) 197 for(j = 0; j < size; j++){ 198 printf("%4d", Magic[i][j]); 199 if(j == size -1) putchar('\n'); 200 } 201 putchar('\n'); 202 } 203 204 /*打印各行、各列、各對角線數據之和*/ 205 void sum_print(int data[], int size) 206 { 207 int i,j; 208 209 /*打印每行數據之和*/ 210 printf("行之和:"); 211 for(i = 0; i < size; i++) 212 for(j = 0; j < size; j++){ 213 data[i] += Magic[i][j]; //行之和 214 if (j == size -1) printf("%6d", data[i]); 215 } 216 putchar('\n'); 217 218 219 /*打印每列數據之和*/ 220 printf("列之和:"); 221 for(i = 0; i < size; i++) 222 for(j = 0; j < size; j++){ 223 data[size+i] += Magic[j][i]; //列之和 224 if (j == size -1) printf("%6d", data[size+i]); 225 } 226 putchar('\n'); 227 228 229 /*打印主對角線之和*/ 230 for(i=0; i<size; i++) 231 data[2*size] += Magic[i][i]; 232 printf("主對角線之和:%6d", data[2*size]); 233 putchar('\n'); 234 235 /*打印副對角線之和*/ 236 for(i=0; i<size; i++) 237 data[2*size+1] += Magic[i][size-i-1]; 238 printf("主對角線之和:%6d", data[2*size]); 239 putchar('\n'); 240 241 } 242 243 /*行列對和數組清零*/ 244 void clear_sum(int data[]) 245 { 246 int i; 247 for(i = 0; i < 2 * MAX_SIZE; i++) 248 data[i] = 0; 249 } 250 251 /*檢查程序是否運轉正常,所得結果是否是幻方*/ 252 void check_magic(int data[], int size ) 253 { 254 int i; 255 int flag = 0; 256 for(i=1; i<size+2;i++) 257 if(data[0]-data[i]) flag = 1; 258 if(flag) printf("程序出錯,Esc退出,Enter繼續\n"); 259 else printf("\n恭喜你,獲得了一個新的%d階幻方!\n", size); 260 putchar('\n'); 261 262 }
?