#楼主# 2019-11-6

跳转到指定楼层

马上注册,分享更多源码,享用更多功能,让你轻松玩转云大陆。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
作者:刘亮
幻方(Magic Square)是一种将数字安排在正方形格子中,使每行、列和对角线上的数字和都相等的方法。
幻方也是一种中国传统游戏。旧时在官府、学堂多见。它是将从一到若干个数的自然数排成纵横各为若干个数的正方形,使在同一行、同一列和同一对角线上的几个数的和都相等。
三阶幻方
161114y4ybzljdjs24hy3h.jpg



本篇主聊高阶幻方构造方法的java实现
数据结构:以二维数组存放数字
例:上面的三阶幻方数组数据如下(不考虑幻方阶次较高,最大值超过int最大值)
int[][] square = {
{8,1,6},
{3,5,7},
{4,9,2}
};
161115hr656hhpzvpzv1hp.jpg


数据结构有了,怎么去验证一个二阶数组的数据是不是一个有效的幻方构造数据呢?
具体思路就是反正法,默认数据符合幻方数据内容:
/**验证一个二阶数组里的数是不是符合一个幻方的要求*/
public static boolean isValidSquare(int[][] nums){
try {
//i阶次幻方
int i = nums.length;
//行列斜的和为
int s = (i*i+1)*i/2;
//数据完整性校验数组
int[] check = new int[i*i+1];
//校验每一行/每一列的和是不是等于s
for (int x = 0; x < i; x++) {
int lineSum = 0;
int colSum = 0;
for (int y = 0; y < i; y++) {
check[nums[x][y]]=nums[x][y];
lineSum += nums[x][y];
colSum += nums[y][x];
}
if (lineSum!=s || colSum!=s) {
return false;
}
}
//校验两个对角线的和是否等于s
int s1Sum = 0;
int s2Sum = 0;
for (int x = 0; x < i; x++) {
s1Sum += nums[x][x];
s2Sum += nums[i-x-1][x];
}
if (s1Sum!=s || s2Sum!=s) {
return false;
}
//校验check数组中是否包含1到i*i中的每一个数
for (int j = 0; j < check.length; j++) {
if (j!=check[j]) {
return false;
}
}
} catch (Exception e) {
e.printStackTrace();
//默认符合幻方规则,任意数组越界等错误都认为是不合格的数据
return false;
}
return true;
}
161115ywbq48cr3gowg4od.jpg


下面开讲n(>=3)阶幻方的构造及实现
奇数阶幻方
拉-卢贝尔算法
这个算法又称“阶梯法”。算法如下:

  • 将1置于第一行中间。
  • 将下一个数字置于当前数字的右上角。假如已经处于方阵的边界,则放在方阵的对边(如图1中的2和4)。
  • 若出现下面两种情况,则将下一个数字放于当前数字的下方:
①当前位置的右上角已经有一个数字(如图2中的6和11)。
②当前位置已经是方阵的右上方(如图2中的16)。

  • 结束,如下图3:
161115yve22h0delnqqvn2.jpg


161115nobkxd4fwzkabd4m.jpg



161115jgie2y5v6c657ten.jpg


161115xpgz4hdava9bfesh.jpg



161115i1spapdglryrwv9k.jpg


161115j70u1tmu0kk1zx1m.jpg



Java实现:
/**
* k=2*n+1
* 拉-卢贝尔算法
* 阶梯法
*/
public static int[][] getSquare2k1LenF1(int k) throws Exception{
int[][] res = new int[k][k];
int x = 0;
int y = k/2;
int total = k*k;
for (int i = 1; i 0) {
x = (x+1)%k;
}else{
x= m;
y= n;
}
}
return res;
}
161115eh223t39ltetp2si.jpg


菱形算法
另一种由康韦(J.H.Conway)建立的算法被称为“菱形算法”,步骤如下(以5x5为例):

  • 从左边中间开始,将奇数在方阵内填成一个菱形。
  • 将方阵分成5条对角线,每条对角线上有5个方格。假如图1所示。
  • 从第一条对角线开始将偶数填入剩余的空格内,图2中填满了前两条对角线。
  • 结束,如图3。
161115txiqwm5apfafqaim.jpg


161116r7cox1hhdzx1xqxz.jpg



161116uae5zz6ketegn655.jpg


161116joes1mxqse1xogzm.jpg



161116jwpazrw0pazdwrxt.jpg


161116kyqnzkvexnny7n7r.jpg



再给一个7阶的构造填数过程,具体规则大家自己揣摩
Java实现:
/**
* 菱形算法
* k=2*n+1
*/
public static int[][] getSquare2k1LenF2(int k) throws Exception{
int[][] res = new int[k][k];
//初始化奇数空间
int n = k/2;
//奇数起点坐标
int baseX = n,baseY = 0;
//起点走向,true向右 false向下
boolean type = true;
//奇数计数
int count = 1;
//当前奇数坐标
int x = baseX;
int y = baseY;
while(true){
res[x][y] = count;
count = count+2;
x--;y++;
if (y>=x-n && y
分享淘帖
回复

使用道具

您的回复是对作者最大的奖励

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于作者

召军_a9de

新手猿

  • 主题

    11

  • 帖子

    11

  • 关注者

    0

Archiver|手机版|小黑屋|云大陆 | 赣ICP备18008958号-4|网站地图
Powered by vrarz.com!  © 2019-2020版权所有云大陆