扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
/***魔术矩阵,也被称为魔方矩阵。目前魔术矩阵主要有三种结构:N为奇数、N为4的倍数、N为其它偶数(4n+2)。br/*其中目前很多数学家都还在研究“N为4的倍数”、“N为其它偶数(4n+2)”,可见它们对于初学者而言太难。br/*因此此处演示的代码,仅仅考虑N为奇数的情况。br/*此代码作为课件提供给学生参考,在学完数组、循环、判断后练习。br/*@authorluo_wenqiang在126点com*@version1.0.0*/classMagicArray{publicstaticvoidmain(String[]args){/*1.把1放在第一行的最中间2.每个数字向右上角填充3.如果往右已经是最大数了,就从最左边重新继续4.如果往上已经是最大数了,就从最下边重新继续5.如果遇到行数的整数倍,则下一个数直接放到该数的下面*//*1.声明一个n*n二维数组2.声明一个int类型的变量记录每个元素递增的值,每次自加即可3.需要一个嵌套循环来填充二维数组3.1.把横向的索引认为x,x=n/23.2.把纵向的所应认为y,y=03.3.在循环中,先把x、y坐标上的值填充,然后计算下一个坐标*/intn=3;int[][]array=newint[n][n];intcounter=1;//自加的计数器intx=n/2;inty=0;//二维数组,需要用两层的嵌套循环来完成比较简单for(inti=0;in*n;i++){//根据坐标填充值array[y][x]=counter;//计算下一个坐标的位置if(counter%n==0){//如果counter是n的整数倍,下一个坐标是在当前数字的下面y++;}else{x++;y--;if(y0){//如果y超出范围,把y设置成最大y=n-1;}if(x==n){//如果x超出范围,把x设置成最小x=0;}}//使用完以后计数器需要自加counter++;}for(int[]row:array){for(inti:row){System.out.print(i);System.out.print(\t);}System.out.println();}}}
网站建设公司,为您提供网站建设,网站制作,网页设计及定制网站建设服务,专注于企业网站制作,高端网页制作,对石牌坊等多个行业拥有丰富的网站建设经验的网站建设公司。专业网站设计,网站优化推广哪家好,专业营销推广优化,H5建站,响应式网站。
、4M阶幻方和4M + 2阶幻方,其中M为自然数,2阶幻方不存在。幻方构造法主要有:连续摆数法、阶梯法(楼梯法)、奇偶数分开的菱形法、对称法、对角线法、比例放大法、斯特雷奇法、LUX法、拉伊尔法(基方、根方合成法)、镶边法、相乘法、幻方模式等。
奇数阶幻方构造法
Siamese方法(Kraitchik 1942年,pp. 148-149)是构造奇数阶幻方的一种方法,说明如下:
把1放置在第一行的中间。
顺序将等数放在右上方格中。
当右上方格出界的时候,则由另一边进入。
当右上方格中已经填有数,则把数填入正下方的方格中。
按照以上步骤直到填写完所有N2个方格。
(由于幻方的对称性,也可以把右上改为右下、左上以及左下等方位)
以5阶幻方为例,1填写在(1,3)(第一行第三列)的位置上;2应当填写在其右上方格即(0,4)中,由于(0,4)超出顶边界,所以从最底行进入,即(5,4);3填写在(5,4)的右上方格(4,5)中;4填写在(4,5)的右上方格(3,6)中,由于(3,6)超出右边界,所以从最左列进入,即(3,1);5填写在(3,1)的右上方格(2,2)中;6应该填写的方格(1,3)已经被1所占据,因此填写在(2,2)的正下方格(3,2)中;按照上面的步骤直到所有数填入。
偶数阶幻方构造法
4M阶幻方构造法
对于4M阶幻方一般都用对调法,制作起来很容易。如4阶幻方的排列法:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
按如上图排列好,再将非主副对角线上的各个数关于中心对调,即成下图:
1 15 14 4
12 6 7 9
8 10 11 5
13 3 2 16
4M+2阶幻方的求解方法
加边法
以6阶为例子,先排出4阶的幻方,如上图,再将图中每一个数都加上8m + 2 = 10
11 25 24 14
22 16 17 19
18 20 21 15
23 13 12 26
在外围加上一圈格子,把和这些数安排在外圈格子内,把1到8M+2和4m*4m+8m+3到(4m+2)*(4m+2)安排到外圈格子内,但要使相对两数之和等于16m(m + 1) + 5。
有了这些公式算法,我们就可以用程序语言来实现它了
首先,这是一个十阶的幻方也就是说我们要用4M+2阶幻方的模式来实现他,其中M=2;
并且要先求出4*2也就是8阶幻方,在把
下面是我编的C语言算法:
#include "stdio.h"
void mian()
{
int arr[10][10];
int no=1;
for(int i=1;i9;i++)
{
for(int j=1;j9;j++)
{
arr[i][j]=no;
no++;
}
}
for(int i=1;i5;i++)
{
for(int j=1;j9;j++)
{
if(i=j||i=(9-j))
contine;
else
{
int need=0;
need=arr[i][j];
arr[i][j]=arry[9-i][9-j];
arry[9-i][9-j]=need;
}
}
}
for(int i=1;i9;i++)
{
for(int j=1;j9;j++)
{
arr[i][j]=arr[i][j]+18;
}
}
int a[18],b[18];
int q=1,w=83;
for(int i=0;i18;i++)
{
a[i]=q;
b[i]=w;
q++;
w++;
}
for(int i=1;i9;i++)
{
for(int j=1;j9;j++)
{
if(j=8)
printf("%d\n",arr[i][j]);
else
printf("%d",arr[i][j])
}
}
for(int i=0;i18;i++)
{
printf("%d\n",a[i]);
printf("%d\n",b[i]);
}
}
因为我没有C编译器,所以我就只有这样把没检验过的代码给你了,我说明一下,我这个编译的是8*8的二维数组的幻方,公式也给你了,也许答案和你的不一样,但是绝对是正确的,楼主可以验算,至于为什么我没有加上其他二方,那是因为我暂时还没有想到有更优化的方法来实现4M+2种类的幻方方法,只能把他剩下的二方数字输出来,让别人自己填,我也就能做到这样了,打了大半天,虽说不完美,但是也只有将就了
另外,虚机团上产品团购,超级便宜
import java.io.*;
import java.util.*;
public class TestMag {
public void Magic(int n){
int a[][]=new int[n][n];
int row,col;
row=0;col=(n-1)/2;
a[row][col]=1;
for(int j=2;j=n*n;j++){
if ((j-1)%n==0) {
row=(row+1)%n;
}else{
row=(row+n-1)%n;
col=(col+1)%n;
}
a[row][col]=j;
}//end for
for(row=0;rown;row++){
for(col=0;coln;col++) System.out.print(a[row][col]+" ");
System.out.println();
};
}
public static void main(String[]args){
int n=0;
TestMag tm=new TestMag();
String sn;
do{
System.out.print("请输入一个奇数:");
BufferedReader streami = new BufferedReader(
new InputStreamReader(System.in));
try {
sn=streami.readLine();
n=Integer.parseInt(sn);
}
catch (Exception ex) {
}
} while (n%2==0);
tm.Magic(n);
}
}
public class ShuDu {
/**存储数字的数组*/
static int[][] n = new int[9][9];
/**生成随机数字的源数组,随机数字从该数组中产生*/
static int[] num = {1,2,3,4,5,6,7,8,9};
public static void main(String[] args) {
//生成数字
for(int i = 0;i 9;i++){
//尝试填充的数字次数
int time = 0;
//填充数字
for(int j = 0;j 9;j++){
//产生数字
n[i][j] = generateNum(time);
//如果返回值为0,则代表卡住,退回处理
//退回处理的原则是:如果不是第一列,则先倒退到前一列,否则倒退到前一行的最后一列
if(n[i][j] == 0){
//不是第一列,则倒退一列
if(j 0){
j-=2;
continue;
}else{//是第一列,则倒退到上一行的最后一列
i--;
j = 8;
continue;
}
}
//填充成功
if(isCorret(i,j)){
//初始化time,为下一次填充做准备
time = 0;
}else{ //继续填充
//次数增加1
time++;
//继续填充当前格
j--;
}
}
}
//输出结果
for(int i = 0;i 9;i++){
for(int j = 0;j 9;j++){
System.out.print(n[i][j] + " ");
}
System.out.println();
}
}
/**
* 是否满足行、列和3X3区域不重复的要求
* @param row 行号
* @param col 列号
* @return true代表符合要求
*/
public static boolean isCorret(int row,int col){
return (checkRow(row) checkLine(col) checkNine(row,col));
}
/**
* 检查行是否符合要求
* @param row 检查的行号
* @return true代表符合要求
*/
public static boolean checkRow(int row){
for(int j = 0;j 8;j++){
if(n[row][j] == 0){
continue;
}
for(int k =j + 1;k 9;k++){
if(n[row][j] == n[row][k]){
return false;
}
}
}
return true;
}
/**
* 检查列是否符合要求
* @param col 检查的列号
* @return true代表符合要求
*/
public static boolean checkLine(int col){
for(int j = 0;j 8;j++){
if(n[j][col] == 0){
continue;
}
for(int k =j + 1;k 9;k++){
if(n[j][col] == n[k][col]){
return false;
}
}
}
return true;
}
/**
* 检查3X3区域是否符合要求
* @param row 检查的行号
* @param col 检查的列号
* @return true代表符合要求
*/
public static boolean checkNine(int row,int col){
//获得左上角的坐标
int j = row / 3 * 3;
int k = col /3 * 3;
//循环比较
for(int i = 0;i 8;i++){
if(n[j + i/3][k + i % 3] == 0){
continue;
}
for(int m = i+ 1;m 9;m++){
if(n[j + i/3][k + i % 3] == n[j + m/3][k + m % 3]){
return false;
}
}
}
return true;
}
/**
* 产生1-9之间的随机数字
* 规则:生成的随机数字放置在数组8-time下标的位置,随着time的增加,已经尝试过的数字将不会在取到
* 说明:即第一次次是从所有数字中随机,第二次时从前八个数字中随机,依次类推,
* 这样既保证随机,也不会再重复取已经不符合要求的数字,提高程序的效率
* 这个规则是本算法的核心
* @param time 填充的次数,0代表第一次填充
* @return
*/
public static int generateNum(int time){
//第一次尝试时,初始化随机数字源数组
if(time == 0){
for(int i = 0;i 9;i++){
num[i] = i + 1;
}
}
//第10次填充,表明该位置已经卡住,则返回0,由主程序处理退回
if(time == 9){
return 0;
}
//不是第一次填充
//生成随机数字,该数字是数组的下标,取数组num中该下标对应的数字为随机数字
int ranNum = (int)(Math.random() * (9 - time));
//把数字放置在数组倒数第time个位置,
int temp = num[8 - time];
num[8 - time] = num[ranNum];
num[ranNum] = temp;
//返回数字
return num[8 - time];
}
}
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流