简单的回溯法生成数独游戏

这是一篇关于课程作业的博客,详细介绍了如何利用回溯法实现数独游戏的自动生成和人工设定功能。任务一包括回溯生成数独并随机隐藏部分区域,任务二涉及对用户设定的数独进行回溯检查。博客提到了回溯逻辑、随机数生成以及边界判断的重要性,并提到主程序的更新和未来计划。
摘要由CSDN通过智能技术生成

题目的原因:课程作业

这是一个课设的作业,对于理解回溯法很有用,所以把他码住。好久没敲这种代码了,边界居然调了半天,尴尬!

作业分析

作业描述:写个数独游戏,具有自动生成数独的功能和人工设定初始盘的功能,并且具有UI界面。

作业分析:
任务一:对于自动生成数独的功能,他的功能实现逻辑是:回溯生成一个数独,然后随机性让部分区域可视(对于玩家),当玩家选择提交时,再判断是否与生成的数独一致。
**任务二:**对于人工设定初始盘的功能,他和上面的自动生成有一些不同,当玩家选择手动生成数独并提交给后台之后,后台通过回溯法对提交的数组进行有解检查,如果无解返回“设定失败”,否则就找到所有的解,并保存全部。当玩家提交answer时,匹配每一种解。

任务一实现

回溯逻辑:对于一个用来保存生成的数组GAME,我们对其进行自上而下从左到右的填充,每次在当前位置(x,y)填充一个数字时,对该数字进行合法判断Iscorrect(x,y),如果不合法,进行回溯;合法进行下一次填充。

注:回溯法一定注意循环的逻辑,以及对continue一定要有充分的了解,不清楚的建议改为break,单步调试几次。特别注意,j=j-2而不是j=j-1!!!


private static int[][] game=new int [9][9];//储存数独
	
	

	private static int []ranNum= {1,2,3,4,5,6,7,8,9};//随机数生成数组
	private int[][] generateGame(){
		//初始化数独
		for(int i=0;i<9;i++)
			for(int j=0;j<9;j++)
				game[i][j]=0;
		
		
        //生成数独游戏的所有内容
		for(int i=0;i<9;i++) {
			int time=0;
			for(int j=0;j<9;j++) {
			   int tem=-1;
			   tem=getNum(time);
			   game[i][j]=tem;
			   if(tem==0) {
				   //说明已经不能再填充数字了
				   if(j>0) {
					   //当j不是第一列时,回溯上一列,由于j已经加了所以是j-2,而不是j--;特别注意
					  j=j-2;
					   continue;
				   }
				   else {
					  i--;
					  j=8;
					  continue;
				   }
				   
			   }
			   //如果可以获得数字,说明尝试的次数并没有用完
			   //对数字的合法性进行检查
			   if(Iscorrect(i,j)) {
				   time=0;
			   }
			   else {//填充失败,继续填充,应该
				   time++;
				   j--;
				   
			   }
				
				
			}
		
		}	
		
		return game;
	}

功能模块完善

1、自动生成随机数函数getNum(int time)
对于一个第一次,生成随机数的情况来说(time=0),我们初始化数组。
对于一个进行第九次挑选随机数的情况来说(time=9),我们已经没有数可以供他使用,所以返回不存在。
当进行数字生成时,我们只要保证生成随机数的下标是在MAX(未被使用的数字的下标),就可以实现,千万别忘了把已经使用过的数字和末位交换。
注:这个自己一定要写一下,我错了好几次!!


	//生成随机数独
	private int getNum(int time) {
   
		//第一次产生随机数
		
		Random r=new Random();
		if (time == 0) {
   
			for (int i = 0; i < 9; i++) {
   
				ranNum[i] = i + 1;
			}
		}
		// 第10次填充,表明该位置已经卡住,则返回0,由主程序处理退回
		if (time == 9) {
   
			return 0;
		}
		// 不是第一次填充
		// 生成随机数字,该数字是数组的下标,取数组num中该下标对应的数字为随机数字
//		int ranNum = (int) (Math.random() * (9 - time));//j2se
		int num=r.nextInt(9 - time);//j2me
		// 把数字放置在数组倒数第time个位置,
		int temp = ranNum[8 - time];
		ranNum[8 - time] = ranNum[num];
		ranNum[num] = temp;
		// 返回数字
		return ranNum[8-time];
	
	}

2.合法性判断(一定不要越界)
注:最好写个边界判断函数,我写代码时候越界了,没有输出就狠烦。

	private boolean Iscorrect(int i, int j) {
   
		// TODO Auto-generated method stub
		if(Checkline(i)&&CheckCol(j)&&CheckBox(i,j)) {
   
			return true;
		}
		
		else {
   
		
		return false;
	}
	}
	//检查3*3是否有重复
	private boolean CheckBox(int i, int j) {
   
	  //获取左上角进行遍历
		int sx=i/3*3;
		int sy=j/3*3;
		for(int m=0;m<8;m++) {
   
		//说明还没有填充
	    if(game[sx+m/3][sy+m%3]==0) {
   
	    	continue;
	    }
		for(int n=m+1;n<9;n++) {
   
			if(game[sx+m/3][sy+m%3]==game[sx+n/3][sy+n%3]) {
   
				//System.out.println("asdfasfa ");
				return false;
			}
				
		}
				
			
		}
		
		
		
		// TODO Auto-generated method stub
		return true;
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值