`

生成数独矩阵--《编程之美》1.15节

 
阅读更多
生成数独矩阵,定义参见《编程之美》第1.15节.
程序可以直接运行
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * 生成数独矩阵,定义参见《编程之美》第1.15节.
 * 
 * @author LC
 */
public class Sudoku {
	Cell g[][] = new Cell[9][9];

	public Sudoku() {
		for (int i = 0; i < g.length; i++) {
			for (int j = 0; j < g[i].length; j++) {
				g[i][j] = new Cell();
			}
		}
	}

	//检查整个矩阵是否满足数独的条件,不允许有空格
	boolean check() {
		//检查每行是否数字不重复
		Set<Integer> s = new TreeSet<>();

		//检查每个小块是否数字不重复
		for (int r = 0; r < 3; r++) {
			for (int c = 0; c < 3; c++) {
				int rShift = r * 3;
				int cShift = c * 3;
				s.clear();

				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {
						Cell cell = g[rShift + i][cShift + j];
						if (!cell.isValid() || s.contains(cell.number)) {
							System.out.println("error in block (" + r + ", "
									+ c + ") with duplicated " + cell.number);

							return false;
						} else
							s.add(cell.number);

					}
				}

			}
		}

		for (int i = 0; i < g.length; i++) {
			s.clear();
			for (int j = 0; j < g[i].length; j++) {
				Cell cell = g[i][j];
				if (!cell.isValid() || s.contains(cell.number)) {
					System.out.println("error in row " + i
							+ " with duplicated " + cell.number);
					return false;
				} else
					s.add(cell.number);

			}

		}

		//检查每列是否数字不重复
		for (int j = 0; j < g[0].length; j++) {
			s.clear();
			for (int i = 0; i < g.length; i++) {
				Cell cell = g[i][j];
				if (!cell.isValid() || s.contains(cell.number)) {
					System.out.println("error in column " + j
							+ " with duplicated " + cell.number);
					return false;
				} else
					s.add(cell.number);
			}

		}

		return true;

	}

	//检查整个矩阵是否满足数独的条件,允许有空格;该方法可以用于游戏中检测选手的输入是否有误
	boolean checkCurrent() {
		//检查每行是否数字不重复
		Set<Integer> s = new TreeSet<>();

		//检查每个小块是否数字不重复
		for (int r = 0; r < 3; r++) {
			for (int c = 0; c < 3; c++) {
				int rShift = r * 3;
				int cShift = c * 3;
				s.clear();

				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {
						Cell cell = g[rShift + i][cShift + j];
						if (!cell.isValid())
							continue;

						if (s.contains(cell.number)) {
							System.out.println("error in block (" + r + ", "
									+ c + ") with duplicated " + cell.number);

							return false;
						} else
							s.add(cell.number);

					}
				}

			}
		}

		for (int i = 0; i < g.length; i++) {
			s.clear();
			for (int j = 0; j < g[i].length; j++) {
				Cell cell = g[i][j];
				if (!cell.isValid())
					continue;

				if (s.contains(cell.number)) {
					System.out.println("error in row " + i
							+ " with duplicated " + cell.number);
					return false;
				} else
					s.add(cell.number);

			}

		}

		//检查每列是否数字不重复
		for (int j = 0; j < g[0].length; j++) {
			s.clear();
			for (int i = 0; i < g.length; i++) {
				Cell cell = g[i][j];
				if (!cell.isValid())
					continue;

				if (s.contains(cell.number)) {
					System.out.println("error in column " + j
							+ " with duplicated " + cell.number);
					return false;
				} else
					s.add(cell.number);
			}

		}

		return true;

	}

	//生成合法的数独矩阵,尝试性的生成,选取数字用了随机化方法
	boolean generateValidMatrix() {
		int rollBackCount = 0;

		int i = 0;
		int j = 0;
		//生成数独矩阵,每个单元逐次生成,顺序为从左到右,从上到下
		while (i < g.length) {
			int rShift = i / 3 * 3;
			int cShift = j / 3 * 3;

			Cell cell = g[i][j];

			//剔除该列已有的数字
			for (int r = 0; r < i; r++) {
				cell.alternativeNumbers.remove((Integer) g[r][j].number);
			}

			//剔除该行已有的数字
			for (int c = 0; c < j; c++) {
				cell.alternativeNumbers.remove((Integer) g[i][c].number);
			}

			//剔除该块已有的数字
			for (int r = rShift; r <= i; r++) {
				for (int c = cShift; c < cShift + 3; c++) {
					cell.alternativeNumbers.remove((Integer) g[r][c].number);
				}
			}
			if (cell.hasAlternativeNumber()) {
				cell.pickAnAlternativeNumberRandomlyAndRemoveIt();//这一步中已经将当选的数字从可选数字列表中删除了
				//转到下一个要处理的cell
				j++;
				if (j == g[0].length) {
					j = 0;
					i++;
				}
			} else {//回退
				rollBackCount++;
				cell.init();
				//找到上一个cell
				if (j > 0) {
					--j;
				} else {
					--i;
					j = g[0].length - 1;
				}

				Cell lastCell = g[i][j];//没这一步也行
				lastCell.number = 0;

			}
		}

		System.out.println("生成该数独矩阵时回退了" + rollBackCount + "步");
		return true;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < g.length; i++) {
			for (int j = 0; j < g[i].length; j++) {
				sb.append(g[i][j].toString());
				if (j % 3 == 2)
					sb.append(' ');
			}
			sb.append('\n');
			if (i % 3 == 2 && i != g.length - 1)
				sb.append('\n');
		}

		return sb.toString();
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Sudoku s = new Sudoku();
		s.generateValidMatrix();
		System.out.println(s);
		boolean b = s.check();

		System.out.println("生成的数独矩阵是否通过了检测?  " + b);
	}
}

//数独的一个单元格
class Cell {
	int number = 0;//该单元中的数字,为0表示为空, 有效数字为1~9
	List<Integer> alternativeNumbers;//当前可选的数字, 生成数独矩阵时使用

	void init() {
		number = 0;
		alternativeNumbers = new ArrayList<>();//当前可选的数字
		for (int i = 1; i <= 9; i++) {
			alternativeNumbers.add(i);

		}
	}

	public Cell() {
		init();
	}

	/**
	 * @return 该单元 是否还有满足数独规则的数字可用
	 */
	boolean hasAlternativeNumber() {
		return alternativeNumbers.size() > 0;
	}

	/**
	 * 随机选取一个满足数独规则的数字作为该单元的数字,并将其从可选数字集合中剔除
	 */
	void pickAnAlternativeNumberRandomlyAndRemoveIt() {
		int idx = (int) (Math.random() * alternativeNumbers.size());
		number = alternativeNumbers.get(idx);
		alternativeNumbers.remove(idx);
	}

	@Override
	public String toString() {
		//		System.out.println(number);
		return number <= 0 ? " " : String.valueOf(number);
	}

	/**
	 * @return 当前单元中是否有有效的数字
	 */
	boolean isValid() {
		return number > 0 && number < 10;
	}
}
分享到:
评论

相关推荐

    简洁高效的数独矩阵生成器

    在这个场景中,我们讨论的是一个简洁高效的数独矩阵生成器,该生成器是用C++编程语言编写的,能够根据用户的需求生成不同阶数的数独矩阵。 首先,我们来看数独矩阵生成器的核心算法。生成数独矩阵通常涉及两个主要...

    数独游戏---自写算法。随即生成数独

    2. 实现数独生成器:随机生成一个完整的数独解决方案,然后通过删除部分数字生成一个残局。 3. 检查逻辑:编写函数检查当前填入的数字是否合法,即所在行、列和小宫格内没有重复。 4. 回溯算法:当用户填入数字后,...

    数独随机矩阵生成

    在编程实现数独随机矩阵生成时,可以使用Python等语言,结合上述算法,结合随机数生成函数,编写代码生成数独矩阵。压缩包中的`sudu`文件可能是实现了上述算法的源代码,可以用于学习和理解数独生成的实现过程。通过...

    数独矩阵生成

    数独矩阵完成生成,显示,保存,功能,等功能,详情请见头文件内所有详细注释,当前版本不支持逆向计算,凡是正常生成的矩阵都是有具体参考,答案,由于可能根据你的设置不同,答案不唯一,但是会有个系统标准答案,...

    51-数独游戏-少儿编程scratch项目源代码文件案例素材.zip

    《数独游戏——少儿编程Scratch项目》是一个旨在教授儿童编程知识和逻辑思维能力的案例。这个项目通过创建一个互动的数独游戏,让孩子们在娱乐中学习编程基础。Scratch是麻省理工学院(MIT)媒体实验室“终身幼儿园...

    数独游戏-少儿编程scratch项目源代码文件案例素材.zip

    在少儿编程教育中,利用Scratch这样的图形化编程工具来实现数独游戏,可以帮助孩子们理解和运用编程思维,同时提升他们的逻辑推理能力。 Scratch是由麻省理工学院(MIT)的“终身幼儿园团队”开发的一款面向儿童的...

    数独-数独游戏-小程序-uniapp项目源码

    这是一个h5或小程序,是经典怀旧的数独游戏,是uniapp项目源码,用HBuilderX开发工具编写而成, 数独游戏逻辑非常简单,能训练大脑和观察能力,适合新手入门参考学习。 相关指导教程请看作者发表的文章 ...

    生成四种难度的数独生成器MATLAB程序

    在这个数独生成器中,MATLAB被用来创建算法,这些算法能够随机生成满足数独规则的填空矩阵。程序可能包含了初始化矩阵、生成随机解决方案、检查并消除重复解、以及根据难度调整空白数量等步骤。 首先,生成器会创建...

    数独-数独游戏-微信小程序-项目源码

    这是一个微信小程序项目源码,是经典怀旧的数独游戏, 数独游戏逻辑非常简单,能训练大脑和观察能力,适合新手入门参考学习。 相关指导教程请看作者发表的文章 ...

    数独游戏矩阵设计实现1

    数独游戏矩阵设计实现1是指通过算法生成一个合法的数独矩阵。数独矩阵是一个9x9的二维数组,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1...

    数独入门-儿童数独游戏第级-宫摒余法x.pdf

    数独是一种逻辑推理游戏,它的目标是在9x9的格子中填入数字1到9,使得每一行、每一列以及每一个3x3的小宫格(也称为九宫格)内的数字都恰好出现且只出现一次。对于儿童来说,数独游戏是训练逻辑思维和注意力的好方法...

    9套数独入门儿童数独游戏资料合集.zip

    【数独】入门练习题(四宫)-200道,pdf 六宫数独300题.pdf 数独《中级》练习题(九宫)含案-100道.pdf 数独《中级》练习题(九宫)含答案-100道.pdf 数独入门-儿童数独游戏第1级-唯一法4X4.pdf 数独入门-儿童数独游戏第1级...

    关于"数独--九宫格"的算法实现

    花了30块银子到当当网上买了编程之美&gt;&gt;找到其中的章节,看完之后大失所望.其中的算法实现藏头露尾,寥寥几行.让人看的云里雾里.连类定义都没有给全. 这里只好自己用基拙挖掘法实现了一个完整的算法,现共享之.其核心...

    python数独游戏-33-了解高阶函数.ev4.rar

    在Python编程领域,数独游戏是一种常见的练习项目,它能帮助开发者提高逻辑思维和问题解决能力。本资源“python数独游戏-33-了解高阶函数.ev4.rar”聚焦于利用Python实现数独游戏,并重点讲解了高阶函数的概念及其在...

    java数独题库高效生成算法代码

    总的来说,Java数独题库高效生成算法是一种结合了数学、逻辑和编程技巧的解决方案,它能够生成各种难度级别的数独谜题,并且在性能上进行了优化,适合大规模的数独题库生成需求。通过学习和理解这样的算法,不仅可以...

    sd.rar_c++数独_c++生成数独_数独_生成数独_随机生成数独

    数组可以简单地映射9x9的矩阵,而类可以封装数独的属性和操作,提高代码的可读性和可维护性。 在数独生成方面,程序可能采用了两种常见的方法:回溯法和深度优先搜索(DFS)。这两种方法都是通过尝试填入数字,如果...

    matlab数独游戏-shudu.m

    matlab数独游戏-shudu.m 各位大师们 帮帮忙啊 怎么用matlab编一个九宫格的游戏啊 也就是数独游戏啊 急着用啊 做什么课程设计,小妹很不幸抽到这个题啦 有会的或者有现成的拜托发到邮箱啊 谢谢啊 835111816@...

    数独游戏生成数独谜题生成数独谜题

    - **算法选择**:回溯法是生成数独的有效方法之一。 - **原理**:从第一个空位开始填充数字(1-9),每次尝试填充一个数字后递归检查是否符合数独规则;如果不符合,则回溯至上一步重新选择数字。 - **代码实现**...

    matlab数独游戏-sudoku.m

    matlab数独游戏-sudoku.m 各位大师们 帮帮忙啊 怎么用matlab编一个九宫格的游戏啊 也就是数独游戏啊 急着用啊 做什么课程设计,小妹很不幸抽到这个题啦 有会的或者有现成的拜托发到邮箱啊 谢谢啊 835111816@...

Global site tag (gtag.js) - Google Analytics