之前学习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;
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。