java 数独算法_java版数独游戏核心算法(一)

这篇博客分享了如何使用Java实现数独游戏的核心算法,包括初始化数独地图、放置数字、回溯等关键步骤。作者指出算法仍有优化空间,并鼓励读者探讨改进方法。
摘要由CSDN通过智能技术生成

之前学习javascript时用javascript写过一个数独游戏,最近看了一点java的内容,于是就心血来潮想搞一个java版的数独游戏。

现在将全部代码分享出来和大家学习交流,当然代码中有着各种各样的问题和不足之处,望各位朋友批评指点。

以下是生成数独地图的核心算法,算法不是很好,也是之前参考过网上的一些思想:

package hlc.shudu.src;

/*

* 数独的帮助类,里面提供数据所需的所有算法

*/

public class ShuduHelper {

//数独地图数组

private static int[][] maps = new int[9][9];

//每个小九宫格可放置位置的数

private static int[] canPutSum = new int[9];

//用来存储之前放置过的位置

static int[] used = new int[9];

//是否已经完成地图的生成

static boolean isOk = true;

/*

* 得到数独地图数组

*/

public static int[][] getMap() {

//判断是否已经完成地图的生成,要是没有完成就重新生成。

//从这里就可以看出算法还有待优化,如果回溯的好的话就一直可以通过回溯来重新生成,而这里是通过重新执行生成算法来重新生成。希望感兴趣的朋友可以去实现以下。

do{

isOk = true;

initMaps();

}while(!isOk);

return maps;

}

/*

* 初始化maps

*/

private static void initMaps() {

// 初始化地图数组中没有填入任何数字

for (int i = 0; i < 9; i++) {

for (int j = 0; j < 9; j++) {

maps[i][j] = -1;

}

}

// 依次填入1~9

for (int num = 1; num <= 9; num++) {

for (int i = 0; i < 9; i++) {

used[i] = -1;

canPutSum[i] = -1;

}

// 遍历大九宫格中的每个小九宫格

for (int i = 0; i < 9; i++) {

if (canPutSum[i]==-1) {

canPutSum[i] = getCanPutSum(i, num);

}

if (canPutSum[i]==1) {

used[i] = -1;

}

if (canPutSum[i] == 0) {

canPutSum[i] = -1;

used[i] = -1;

// 如果当前小九宫格中不能放入数字num,则回到前一个小九宫格

if (i > 0) {

// 将前一个九宫格中放num的位置清空

if (used[i-1]!=-1) {

//maps[(int) (Math.floor(used[i-1]/3)+Math.floor((i-1)/3)*3)][used[i-1]%3+((i-1)%3)*3]=-1;

clearNum(i - 1, num);

}

// i回退一个,因为等会for循环灰给i加一,所以这里减2

i -= 2;

continue;

} else {

isOk = false;

return;

}

} else {

// 将num放入当前小九宫格中

boolean flag = false;

while (!flag) {

int j = (int) (Math.random() * 9);

// 当前小方格横坐标

int ii = (i / 3) * 3 + j / 3;

// 当前小方格纵坐标

int jj = (i % 3) * 3 + j % 3;

//System.out.println("num:"+num+"\tii:"+ii+"\tjj:"+jj);

// 如果可以放置num则放置

if (maps[ii][jj] == -1 && j!=used[i] && isCanPut(ii, jj, num)) {

maps[ii][jj] = num;

used[i] = j;

canPutSum[i] -= 1;

flag = true;

}

}

}

}

}

}

/*

* 清空第i个小九宫格中的num

*/

private static void clearNum(int i, int num) {

for (int j = 0; j < 9; j++) {

// 当前小方格横坐标

int ii = (i / 3) * 3 + j / 3;

// 当前小方格纵坐标

int jj = (i % 3) * 3 + j % 3;

// 判断当前小方格是否可以放置

if (maps[ii][jj] == num) {

maps[ii][jj] = -1;

}

}

}

/*

* 得到当前小九宫格可以放入数字num的位置数目

*/

private static int getCanPutSum(int i, int num) {

int sum = 0;

// 遍历小九宫格

for (int j = 0; j < 9; j++) {

// 当前小方格横坐标

int ii = (i / 3) * 3 + j / 3;

// 当前小方格纵坐标

int jj = i % 3 * 3 + j % 3;

// 判断当前小方格是否可以放置

if (maps[ii][jj] == -1 && isCanPut(ii, jj, num)) {

++sum;

}

}

return sum;

}

/*

* 指定横纵坐标点是否可以放置num

*/

private static boolean isCanPut(int ii, int jj, int num) {

// 判断指定坐标点的同行或同列是否有相同数字,要是有则为false

for (int i = 0; i < 9; i++) {

if (maps[ii][i] == num) {

return false;

}

if (maps[i][jj] == num) {

return false;

}

}

return true;

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值