- 浏览: 465975 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
ty1972873004:
sunwang810812 写道我运行了这个例子,怎么结果是这 ...
Java并发编程: 使用Semaphore限制资源并发访问的线程数 -
lgh1992314:
simpleDean 写道请问,Logger.setLevel ...
Java内置Logger详解 -
sunwang810812:
我运行了这个例子,怎么结果是这样的:2号车泊车6号车泊车5号车 ...
Java并发编程: 使用Semaphore限制资源并发访问的线程数 -
jp260715007:
nanjiwubing123 写道参考你的用法,用如下方式实现 ...
面试题--三个线程循环打印ABC10次的几种解决方法 -
cb_0312:
SurnameDictionary文章我没看完,现在懂了
中文排序
前面两篇博文介绍了数独终盘生成的两种方法。
Swing数独游戏(一):终盘生成之矩阵转换法 ==> http://mouselearnjava.iteye.com/blog/1941483
Swing数独游戏(二):终盘生成之随机法 ==> http://mouselearnjava.iteye.com/blog/1941693
拥有了数独终盘之后,我们需要在这个终盘上挖去一些数字,然后就能产生数独难题。
在这篇博文中将简单介绍一下“挖洞”法生成数独难题的方式,并采用随机挖洞的方式,对同一份数独终盘产生不同难度的数独难题。
“挖洞”的方式可以有多种实现,一般有四种方式:
参考自:http://zhangroup.aporc.org/images/files/Paper_3485.pdf
本文采用随机法来实现。
生成的步骤如下:
1. 首先采用前面两篇文章提供的产生数独终盘的方式,产生1000个.txt文件,作为每一关关卡的数独终盘。
Swing数独游戏(一):终盘生成之矩阵转换法 ==> http://mouselearnjava.iteye.com/blog/1941483
Swing数独游戏(二):终盘生成之随机法 ==> http://mouselearnjava.iteye.com/blog/1941693
2. 每个数独终盘由9个 3 * 3 的块组成,根据设定的关卡难度随机产生一个适合关卡难度的随机数,比如5, 然后在某个 3*3的块中随机剔除5个数。
剔除数据的位置记为1,代表这个位置没有数字,用户可以输入数字。保留数字的位置记为0, 用于在页面上显示出数字,但用户不能对其进行修改操作。
比如:
我们可以定义游戏难度为四个等级:简单,中等,困难和非常困难。
定义每个困难等级随机数剔除数据的数目:
简单 --> [4,5]
中等 --> [5,6]
困难 --> [5,8]
非常困难 --> [6,9]
3. 根据关卡的数独终盘及其根据困难等级随机挖空某些数据产生的文件一起,共同确定数独难题
比如,第一关对应的数独终盘如下图所示,终盘内容存储在文件1.txt中。
结合为简单难度产生的“挖洞”后的文件,生成对应的数独难题:
这样一来,不同困难难度的数独难题就产生了,一个关卡,根据剔除数据个数的不同,将为每个困难等级产生一个挖洞文件,也就是有四个数独难题。如果随机产生1000个数独终盘,那么玩家可以玩4000个数独题目,每个困难等级1000个关卡可供选择。
总结:
本篇文章使用简单的随机剔除数据的方法去产生数独难题,这个方法比较方便简单。但是并不能保证解的唯一性,也就是一道数独难题可能拥有超过一个解法。如果用户填入的数据都满足数独条件,那么他的解就是可用的,有效的,可以通过该关卡。
另外随机剔除数据可能没有剔除某些数据的关联性,可能使得尽管剔除的数据不少,但是玩起来并不难的情况。
下面是随机剔除数据的一个工具类:
Swing数独游戏(一):终盘生成之矩阵转换法 ==> http://mouselearnjava.iteye.com/blog/1941483
Swing数独游戏(二):终盘生成之随机法 ==> http://mouselearnjava.iteye.com/blog/1941693
拥有了数独终盘之后,我们需要在这个终盘上挖去一些数字,然后就能产生数独难题。
在这篇博文中将简单介绍一下“挖洞”法生成数独难题的方式,并采用随机挖洞的方式,对同一份数独终盘产生不同难度的数独难题。
“挖洞”的方式可以有多种实现,一般有四种方式:
参考自:http://zhangroup.aporc.org/images/files/Paper_3485.pdf
本文采用随机法来实现。
生成的步骤如下:
1. 首先采用前面两篇文章提供的产生数独终盘的方式,产生1000个.txt文件,作为每一关关卡的数独终盘。
Swing数独游戏(一):终盘生成之矩阵转换法 ==> http://mouselearnjava.iteye.com/blog/1941483
Swing数独游戏(二):终盘生成之随机法 ==> http://mouselearnjava.iteye.com/blog/1941693
2. 每个数独终盘由9个 3 * 3 的块组成,根据设定的关卡难度随机产生一个适合关卡难度的随机数,比如5, 然后在某个 3*3的块中随机剔除5个数。
剔除数据的位置记为1,代表这个位置没有数字,用户可以输入数字。保留数字的位置记为0, 用于在页面上显示出数字,但用户不能对其进行修改操作。
比如:
我们可以定义游戏难度为四个等级:简单,中等,困难和非常困难。
定义每个困难等级随机数剔除数据的数目:
简单 --> [4,5]
中等 --> [5,6]
困难 --> [5,8]
非常困难 --> [6,9]
/** * 根据不同的游戏难度,获取随机数 */ public int getRandomNumberByLevel(DifficultyLevel level) { int randomValue = 5; switch (level) { case EASY: /** * 产生随机数[4,5] */ randomValue = random.nextInt(2) + 4; break; case MEDIUM: /** * 产生随机数[5,6] */ randomValue = random.nextInt(2) + 5; break; case DIFFICULT: /** * 产生随机数[5,8] */ randomValue = random.nextInt(4) + 5; break; case EVIL: /** * 产生随机数[6,9] */ randomValue = random.nextInt(4) + 6; break; default: break; } return randomValue; }
3. 根据关卡的数独终盘及其根据困难等级随机挖空某些数据产生的文件一起,共同确定数独难题
比如,第一关对应的数独终盘如下图所示,终盘内容存储在文件1.txt中。
结合为简单难度产生的“挖洞”后的文件,生成对应的数独难题:
- 简单难度==>
- 中等难度==>
- 困难难度==>
同理可以获得中等难度,困难难度等对应的数独难题。
这样一来,不同困难难度的数独难题就产生了,一个关卡,根据剔除数据个数的不同,将为每个困难等级产生一个挖洞文件,也就是有四个数独难题。如果随机产生1000个数独终盘,那么玩家可以玩4000个数独题目,每个困难等级1000个关卡可供选择。
总结:
本篇文章使用简单的随机剔除数据的方法去产生数独难题,这个方法比较方便简单。但是并不能保证解的唯一性,也就是一道数独难题可能拥有超过一个解法。如果用户填入的数据都满足数独条件,那么他的解就是可用的,有效的,可以通过该关卡。
另外随机剔除数据可能没有剔除某些数据的关联性,可能使得尽管剔除的数据不少,但是玩起来并不难的情况。
下面是随机剔除数据的一个工具类:
package my.sudoku.utils; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Random; import java.util.logging.Logger; import my.sudoku.constant.SudokuContants; import my.sudoku.enums.DifficultyLevel; public class HoleDigUtils { private static final Logger logger = Logger .getLogger("my.sudoku.utils.HoleDigUtils"); private Random random = new Random(); public void digHolesByGameDifficulty(int numOfFiles, DifficultyLevel level) { for (int num = 1; num <= numOfFiles; num++) { int[][] array = new int[9][9]; int randomInt = 0; for (int i = 0; i < 9; i++) { randomInt = getRandomNumberByLevel(level); int[] randomPositions = populateRandomArray(randomInt); for (int j = 0; j < randomPositions.length; j++) { int col = (i % 3) * 3 + (randomPositions[j] - 1) % 3; int row = (i / 3) * 3 + ((randomPositions[j] - 1) / 3); array[row][col] = 1; } /** * 将array写入文件 */ BufferedWriter bw = null; try { bw = new BufferedWriter(new FileWriter(new File( SudokuContants.SUDOKU_FOLDER_NAME, buildFileName( level, num)))); } catch (IOException e) { logger.severe(e.getMessage()); } StringBuilder sb = new StringBuilder(); for (int k = 0; k < 9; k++) { sb.setLength(0); for (int j = 0; j < 9; j++) { sb.append(array[k][j]); sb.append(","); } try { bw.write(sb.substring(0, sb.length() - 1).toString()); bw.newLine(); } catch (IOException e) { logger.severe(e.getMessage()); } } if (bw != null) { try { bw.close(); } catch (IOException e) { logger.severe(e.getMessage()); } finally { bw = null; } } } } } private String buildFileName(DifficultyLevel level, int fileNumberl) { StringBuilder sb = new StringBuilder(); sb.append(fileNumberl); switch (level) { case EASY: sb.append("_easy.txt"); break; case MEDIUM: sb.append("_medium.txt"); break; case DIFFICULT: sb.append("_difficult.txt"); break; case EVIL: sb.append("_evil.txt"); break; default: break; } return sb.toString(); } /** * 根据不同的游戏难度,获取随机数 */ public int getRandomNumberByLevel(DifficultyLevel level) { int randomValue = 5; switch (level) { case EASY: /** * 产生随机数[4,5] */ randomValue = random.nextInt(2) + 4; break; case MEDIUM: /** * 产生随机数[5,7] */ randomValue = random.nextInt(3) + 5; break; case DIFFICULT: /** * 产生随机数[5,8] */ randomValue = random.nextInt(4) + 5; break; case EVIL: /** * 产生随机数[6,9] */ randomValue = random.nextInt(4) + 6; break; default: break; } return randomValue; } private int[] populateRandomArray(int numOfRandoms) { int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int randomInt = 0; for (int i = 0; i < 20; i++) { randomInt = random.nextInt(8) + 1; int temp = array[0]; array[0] = array[randomInt]; array[randomInt] = temp; } int[] result = new int[numOfRandoms]; System.arraycopy(array, 0, result, 0, numOfRandoms); return result; } public static void main(String[] args) throws IOException { HoleDigUtils digger = new HoleDigUtils(); /** * 采用"挖洞"法,产生不同难度的数独难题文件。 * 文件中 0 表示 有数据且不可编辑,1 表示不显示数据,且可编辑 */ for (DifficultyLevel level : DifficultyLevel.values()) { digger.digHolesByGameDifficulty( SudokuContants.NUMBER_OF_SUDOKU_ARRAYS, level); } } }
发表评论
-
工厂类中移除if/else语句
2016-07-10 19:52 900面向对象语言的一个强大的特性是多态,它可以用来在代码中移除 ... -
Java编程练手100题
2014-12-11 17:13 6728本文给出100道Java编程练手的程序。 列表如下: 面 ... -
数组复制的三种方法
2014-11-30 12:57 2212本文将给出三种实现数组复制的方法 (以复制整数数组为例)。 ... -
数组复制的三种方法
2014-11-30 12:54 0本文将给出三种实现数组复制的方法 (以复制整数数组为例)。 ... -
四种复制文件的方法
2014-11-29 13:21 1739尽管Java提供了一个类ava.io.File用于文件的操 ... -
判断一个字符串中的字符是否都只出现一次
2014-11-25 12:58 2724本篇博文将给大家带来几个判断一个字符串中的字符是否都只出现一 ... -
使用正则表达式判断一个数是否为素数
2014-11-23 13:35 2166正则表达式能够用于判断一个数是否为素数,这个以前完全没有想过 ... -
几个可以用英文单词表达的正则表达式
2014-11-21 13:12 3748本文,我们将来看一下几个可以用英文单词表达的正则表达式。这些 ... -
(广度优先搜索)打印所有可能的括号组合
2014-11-20 11:58 1953问题:给定一个正整n,作为括号的对数,输出所有括号可能 ... -
随机产生由特殊字符,大小写字母以及数字组成的字符串,且每种字符都至少出现一次
2014-11-19 14:48 3976题目:随机产生字符串,字符串中的字符只能由特殊字符 (! ... -
找出1到n缺失的一个数
2014-11-18 12:57 3173题目:Problem description: You h ... -
EnumSet的几个例子
2014-11-14 16:24 8749EnumSet 是一个与枚举类型一起使用的专用 Set 实现 ... -
给定两个有序数组和一个指定的sum值,从两个数组中各找一个数使得这两个数的和与指定的sum值相差最小
2014-11-12 11:24 3327题目:给定两个有序数组和一个指定的sum值,从两个数组 ... -
Java面试编程题练手
2014-11-04 22:49 6700面试编程 写一个程序,去除有序数组中的重复数字 编 ... -
Collections用法整理
2014-10-22 20:55 9846Collections (java.util.Collect ... -
The Code Sample 代码实例 个人博客开通
2014-09-04 18:48 1417个人博客小站开通 http://thecodesample. ... -
Collections.emptyXXX方法
2014-06-08 13:37 2145从JDK 1.5开始, Collections集合工具类中预先 ... -
这代码怎么就打印出"hello world"了呢?
2014-06-08 00:37 7396for (long l = 4946144450195624L ... -
最短时间过桥
2014-04-21 22:03 4137本文用代码实现最短时间过桥,并且打印如下两个例子的最小过桥时间 ... -
将数组分割成差值最小的子集
2014-04-20 22:34 2899本文使用位掩码实现一个功能 ==》将数组分割成差值最小的子集 ...
相关推荐
在Java中,我们可以使用Swing或JavaFX库来构建图形用户界面(GUI),这两个库提供了创建窗口、按钮、文本框等组件的工具,用于构建数独游戏的界面。 对于网页版数独游戏,开发者可能使用了HTML、CSS和JavaScript来...
而"双人共战数独游戏"则在此基础上,引入了合作元素,使得玩家可以与朋友一同解决数独难题,增加了游戏的互动性和趣味性。本文将围绕这款由Java编写的双人数独游戏,探讨其背后的技术实现与设计理念。 首先,从技术...
在这个"数独辅助工具"中,我们可以推测这是一个使用Java编程语言开发的应用,专门为了帮助玩家解决数独难题而设计。Java是一种跨平台的面向对象的编程语言,以其“一次编写,到处运行”的特性著称,因此这个工具可以...
生成数独难题通常涉及到算法设计。其中一种可能的方法是遗传算法。遗传算法是一种启发式搜索方法,灵感来源于自然选择和遗传学。在这个应用中,算法可能会生成一系列随机的数独板,然后通过交叉、变异等操作逐步优化...
生成算法可能会包括先生成一个全填满的数独,然后随机删除一些数字,或者从已知的难题开始进行调整。 最后,源码可能还包括一些优化措施,如使用数据结构优化查找和存储,或者使用多线程提高用户体验。例如,使用位...
【标题】中的“java+applet源码-Sudoku”指的是一个使用Java编程语言编写的Applet程序,专门用于生成和解决数独游戏的难题。Applet是Java的一种小程序,可以在支持Java的Web浏览器中运行,为用户提供交互式体验。这...
3. **求解算法**:"sudoku-swinger" 应该包含一个高效的数独求解算法,例如回溯法或者候选数法,用于自动解决数独难题。 五、Swing GUI 设计与交互 1. **布局管理**:Swing 提供了几种布局管理器,如 FlowLayout、...
Keith Corlett 的开源数独解释器解释了任何数独谜题,并生成了人类谜题。 这是一个 Java (Swing) GUI,基于 Nicolas Juillerat 的 DIUF Sudoku Explainer(为了速度而重写),所有提示都来自 Bernhard Hobiger 的 ...
7. **性能优化**:对于复杂度较高的算法,如解决复杂的数独难题,可能需要考虑优化算法效率。例如,通过使用候选数列表减少无效的回溯次数,或者利用特定的数独技巧进行剪枝。 8. **测试与调试**:开发过程中,使用...
8. **用户界面**:尽管题目没有提及,但一个完整的项目可能还包括用户界面,让用户可以交互式地输入数独谜题或查看解决方案,这需要对Java Swing或JavaFX等图形库有一定的了解。 通过这个项目,开发者可以深入理解...
它会生成基本的(人类可解决的)数独谜题,但要花很长时间才能生成困难的数独。 除非偶然,否则它不会产生真正的难题(留给棺材)。 我的编码思想将速度放在可维护性之前,因此多段代码实现了相同的模式(样板),...