今天为大家分享数独游戏的开发与制作,目前系统已经完成了初步功能,后续会进一步完善。整个系统界面漂亮,有完整得源码,希望大家可以喜欢。喜欢的帮忙点赞和关注。一起编程、一起进步
开发环境
开发语言为Java,开发环境Eclipse或者IDEA都可以。运行主程序,或者执行打开JAR文件即可以运行本程序。
系统框架
利用JDK自带的SWING框架开发,不需要安装第三方JAR包。纯窗体模式,直接运行Main文件即可以。同时带有详细得设计文档。
主要功能
游戏原理
数独(shù dú)是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9 。数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。
解题原理
摒除法:用数字去找单元内唯一可填空格,称为摒除法,数字可填唯一空格称为排除法 (Hidden Single)。
根据不同的作用范围,摒余解可分为下述三种:
数字可填唯一空格在「宫」单元称为宫排除(Hidden Single in Box),也称宫摒除法。
数字可填唯一空格在「行」单元称为行排除法(Hidden Single in Row),也称行摒除法。
数字可填唯一空格在「列」单元称为列排除法(Hidden Single in Column),也称列摒除法。
游戏主要功能
1 运行AppStart.java文件
2 程序出现数独游戏的面板
3 在橙色的面板地方单击下,会弹出一个3*3的小窗口,单击具体的数字,实现数字的回填
4 系统实时显示当前的时间和玩游戏的使用时间
5 程序分为N关,每关的模板不一样,需要补充的数字不一样,难度有所差异
运行效果
关键代码
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;
}
}