数独游戏破解

游戏规则:

1、每行都是 1~9

2、没列都是 1~9

3、每块都是 1~9

 

解答思路:

从坐标 [0][0] 开始,算出其允许填入的数字集合(每行允许数字集合、每列允许数字集合 和 每块允许数字集合 的交集)。

从左到右,从上到下依次尝试(即,递归),当无法向 [下一步] 进行时候,则回溯(恢复状态,再尝试另一个值)。

这样直到最后解答完成。

 

源代码:

package com.gq.algorithm;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class NumberOnly {
public static Set<Integer> NUMBER = new HashSet<Integer>();
static
{
for( int i=1 ; i<=9 ; i++ )
{
NUMBER.add(i);
}
}
/**
* 记录每行还未输入的数字
*/
private List<Set<Integer>> rowMissNumber = new ArrayList<Set<Integer>>();
/**
* 记录每列还未输入的数字
*/
private List<Set<Integer>> colMissNumber = new ArrayList<Set<Integer>>();
/**
* 记录每方块还未输入的数字
*/
private List<Set<Integer>> squareMissNumber = new ArrayList<Set<Integer>>();
{
for( int i=0 ; i<9 ; i++ )
{
rowMissNumber.add( null );
colMissNumber.add( null );
squareMissNumber.add( null );
}
}
/**
* 解答是否完成
*/
private boolean gameOver = false;
public static void main(String[] args) 
{
int[][] numbers = {
{0, 9, 3,  0, 0, 1,  5, 0, 6},
{0, 8, 0,  4, 3, 5,  1, 0, 0},
{0, 0, 7,  9, 0, 2,  0, 8, 4},
{0, 2, 0,  0, 7, 4,  8, 6, 0},
{3, 7, 0,  5, 9, 0,  2, 0, 0},
{9, 0, 4,  1, 0, 8,  7, 5, 0},
{0, 0, 0,  0, 5, 3,  6, 0, 2},
{8, 1, 0,  0, 0, 0,  0, 3, 5},
{6, 0, 0,  0, 1, 9,  0, 0, 8},
};
NumberOnly obj = new NumberOnly();
obj.init(numbers);
obj.solution(0, 0, numbers);
}
/**
* 递归破解
* @param x
* @param y
* @param numbers
*/
void solution( int x, int y, int[][] numbers)
{
if( numbers[x][y] == 0 )
{
Set<Integer> allowNums = possiableNumber(x, y);
for( Integer num : allowNums )
{
numbers[x][y] = num;
// 移除设定的值
rowMissNumber.get(x).remove( num );
colMissNumber.get(y).remove( num );
squareRemove( x,y,num );
// 结束
if( x == 8 && y == 8 )
{
gameOver = true;
print( numbers );
return;
}
// 下一步
int x1=x, y1=0;
if( y == 8 )
{
x1 = (x+1)%9;
}
y1 = (y+1)%9;
solution( x1, y1, numbers);
//如果已经计算完成就不需要再回溯,直接返回
if( gameOver )
{
return;
}
// 恢复
numbers[x][y] = 0;
rowMissNumber.get(x).add( num );
colMissNumber.get(y).add( num );
squareAdd( x, y, num );
}
}
else
{
// 结束
if( x == 8 && y == 8 )
{
gameOver = true;
print( numbers );
return;
}
// 下一步
int x1=x, y1=0;
if( y == 8 )
{
x1 = (x+1)%9;
}
y1 = (y+1)%9;
solution( x1, y1, numbers);
}
}
/**
* 打印结果
* @param numbers
*/
void print( int[][] numbers )
{
if( check(numbers) )
{
System.out.println( "计算数独成功。" );
}
else 
{
System.out.println( "计算数独失败。" );
}
for( int i=0 ; i<9 ; i++ )
{
for( int j=0 ; j<9 ; j++ )
{
System.out.print( numbers[i][j] + ", ");
}
System.out.println( );
}
}
/**
* 检查结果是否正确
* @param numbers
* @return
*/
boolean check( int[][] numbers )
{
// 验证每行
for( int i=0 ; i<9 ; i++ )
{
int sum = 0;
for( int j=0 ; j<9 ; j++ )
{
sum += numbers[i][j];
if( j==8 && sum != 45 )
{
return false;
}
}
}
// 验证每列
for( int i=0 ; i<9 ; i++ )
{
int sum = 0;
for( int j=0 ; j<9 ; j++ )
{
sum += numbers[j][i];
if( j==8 && sum != 45 )
{
return false;
}
}
}
// 验证每块
if( !checkSquare(0, 3, 0, 3, numbers))
{
return false;
}
if( !checkSquare(0, 3, 3, 6, numbers))
{
return false;
}
if( !checkSquare(0, 3, 6, 9, numbers))
{
return false;
}
if( !checkSquare(3, 6, 0, 3, numbers))
{
return false;
}
if( !checkSquare(3, 6, 3, 6, numbers))
{
return false;
}
if( !checkSquare(3, 6, 6, 9, numbers))
{
return false;
}
if( !checkSquare(6, 9, 0, 3, numbers))
{
return false;
}
if( !checkSquare(6, 9, 3, 6, numbers))
{
return false;
}
if( !checkSquare(6, 9, 6, 9, numbers))
{
return false;
}
return true;
}
/**
* 验证块
* @param x1
* @param x2
* @param y1
* @param y2
* @param numbers
* @return
*/
boolean checkSquare( int x1, int x2, int y1, int y2, int[][] numbers )
{
int sum =0;
for( int i=x1 ; i<x2 ; i++ )
{
for( int j=y1 ; j<y2 ; j++ )
{
sum += numbers[i][j];
}
}
if( sum != 45 )
{
return false;
}
return true;
}
void squareRemove( int x, int y, int num )
{
if( 0<=x && x <=2 )
{
if( 0<=y && y<=2 )
{
squareMissNumber.get(0).remove( num );
}
if( 3<=y && y<=5 )
{
squareMissNumber.get(1).remove( num );
}
if( 6<=y && y<=8 )
{
squareMissNumber.get(2).remove( num );
}
}
if( 3<=x && x <=5 )
{
if( 0<=y && y<=2 )
{
squareMissNumber.get(3).remove( num );
}
if( 3<=y && y<=5 )
{
squareMissNumber.get(4).remove( num );
}
if( 6<=y && y<=8 )
{
squareMissNumber.get(5).remove( num );
}
}
if( 6<=x && x <=8 )
{
if( 0<=y && y<=2 )
{
squareMissNumber.get(6).remove( num );
}
if( 3<=y && y<=5 )
{
squareMissNumber.get(7).remove( num );
}
if( 6<=y && y<=8 )
{
squareMissNumber.get(8).remove( num );
}
}
}
void squareAdd( int x, int y, int num )
{
if( 0<=x && x <=2 )
{
if( 0<=y && y<=2 )
{
squareMissNumber.get(0).add( num );
}
if( 3<=y && y<=5 )
{
squareMissNumber.get(1).add( num );
}
if( 6<=y && y<=8 )
{
squareMissNumber.get(2).add( num );
}
}
if( 3<=x && x <=5 )
{
if( 0<=y && y<=2 )
{
squareMissNumber.get(3).add( num );
}
if( 3<=y && y<=5 )
{
squareMissNumber.get(4).add( num );
}
if( 6<=y && y<=8 )
{
squareMissNumber.get(5).add( num );
}
}
if( 6<=x && x <=8 )
{
if( 0<=y && y<=2 )
{
squareMissNumber.get(6).add( num );
}
if( 3<=y && y<=5 )
{
squareMissNumber.get(7).add( num );
}
if( 6<=y && y<=8 )
{
squareMissNumber.get(8).add( num );
}
}
}
/**
* 计算出指定坐标可能输入的数字
* @return
*/
Set<Integer> possiableNumber( int x, int y )
{
Set<Integer> result = buildAllNumber();
result.retainAll( rowMissNumber.get(x) );
result.retainAll( colMissNumber.get(y) );
if( 0<=x && x <=2 )
{
if( 0<=y && y<=2 )
{
result.retainAll( squareMissNumber.get(0) );
}
if( 3<=y && y<=5 )
{
result.retainAll( squareMissNumber.get(1) );
}
if( 6<=y && y<=8 )
{
result.retainAll( squareMissNumber.get(2) );
}
}
if( 3<=x && x <=5 )
{
if( 0<=y && y<=2 )
{
result.retainAll( squareMissNumber.get(3) );
}
if( 3<=y && y<=5 )
{
result.retainAll( squareMissNumber.get(4) );
}
if( 6<=y && y<=8 )
{
result.retainAll( squareMissNumber.get(5) );
}
}
if( 6<=x && x <=8 )
{
if( 0<=y && y<=2 )
{
result.retainAll( squareMissNumber.get(6) );
}
if( 3<=y && y<=5 )
{
result.retainAll( squareMissNumber.get(7) );
}
if( 6<=y && y<=8 )
{
result.retainAll( squareMissNumber.get(8) );
}
}
return result;
}
/**
* 初始化
* @param numbers
*/
void init( int[][] numbers )
{
for( int i=0 ; i<9 ; i++ )
{
for( int j=0 ; j<9 ; j++ )
{
// 初始化行
if( rowMissNumber.get(i) == null )
{
rowMissNumber.set(i, buildAllNumber());
}
if( numbers[i][j] != 0 )
{
rowMissNumber.get(i).remove( numbers[i][j] );
}
// 初始化列
if( colMissNumber.get(j) == null )
{
colMissNumber.set(j, buildAllNumber());
}
if( numbers[i][j] != 0 )
{
colMissNumber.get(j).remove( numbers[i][j] );
}
// 初始化方块
//[0][0] ~ [2][2]
if( 0<=i && i <=2 )
{
if( 0<=j && j<=2 )
{
if( squareMissNumber.get(0) == null )
{
squareMissNumber.set(0, buildAllNumber());
}
if( numbers[i][j] != 0 )
{
squareMissNumber.get(0).remove( numbers[i][j] );
}
}
if( 3<=j && j<=5 )
{
if( squareMissNumber.get(1) == null )
{
squareMissNumber.set(1, buildAllNumber());
}
if( numbers[i][j] != 0 )
{
squareMissNumber.get(1).remove( numbers[i][j] );
}
}
if( 6<=j && j<=8 )
{
if( squareMissNumber.get(2) == null )
{
squareMissNumber.set(2, buildAllNumber());
}
if( numbers[i][j] != 0 )
{
squareMissNumber.get(2).remove( numbers[i][j] );
}
}
}
if( 3<=i && i <=5 )
{
if( 0<=j && j<=2 )
{
if( squareMissNumber.get(3) == null )
{
squareMissNumber.set(3, buildAllNumber());
}
if( numbers[i][j] != 0 )
{
squareMissNumber.get(3).remove( numbers[i][j] );
}
}
if( 3<=j && j<=5 )
{
if( squareMissNumber.get(4) == null )
{
squareMissNumber.set(4, buildAllNumber());
}
if( numbers[i][j] != 0 )
{
squareMissNumber.get(4).remove( numbers[i][j] );
}
}
if( 6<=j && j<=8 )
{
if( squareMissNumber.get(5) == null )
{
squareMissNumber.set(5, buildAllNumber());
}
if( numbers[i][j] != 0 )
{
squareMissNumber.get(5).remove( numbers[i][j] );
}
}
}
if( 6<=i && i <=8 )
{
if( 0<=j && j<=2 )
{
if( squareMissNumber.get(6) == null )
{
squareMissNumber.set(6, buildAllNumber());
}
if( numbers[i][j] != 0 )
{
squareMissNumber.get(6).remove( numbers[i][j] );
}
}
if( 3<=j && j<=5 )
{
if( squareMissNumber.get(7) == null )
{
squareMissNumber.set(7, buildAllNumber());
}
if( numbers[i][j] != 0 )
{
squareMissNumber.get(7).remove( numbers[i][j] );
}
}
if( 6<=j && j<=8 )
{
if( squareMissNumber.get(8) == null )
{
squareMissNumber.set(8, buildAllNumber());
}
if( numbers[i][j] != 0 )
{
squareMissNumber.get(8).remove( numbers[i][j] );
}
}
}
}
}
}
/**
* 构造一个集合,包含1~9
* @return
*/
Set<Integer> buildAllNumber()
{
Set<Integer> set = new HashSet<Integer>();
for( int i=1 ; i<=9 ; i++ )
{
set.add(i);
}
return set;
}
}
 

  int[][] numbers = { {5, 0, 6,  0, 0, 0,  0, 8, 0}, {0, 4, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 5,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  6, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 1,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  3, 0, 0}, {0, 0, 0,  0, 0, 0,  9, 0, 8} };

  int[][] numbers = { {4, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 1,  0, 0, 0,  0, 0, 0}, {0, 5, 0,  0, 0, 0,  0, 7, 0}, {0, 8, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 1, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 6,  0, 1, 0}, {0, 6, 0,  0, 0, 0,  0, 5, 0} };

  int[][] numbers = { {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, {0, 0, 0,  0, 0, 0,  0, 0, 0}, };

 
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/497785.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能能否在对抗虚假新闻战争中完胜?

来源&#xff1a;亿欧概要&#xff1a;2017年&#xff0c;误导性和恶意的虚假在线内容是如此丰富多产&#xff0c;以至于人类无法让自己解脱困境。反而&#xff0c;这越发看来机器将不得不拯救我们。这可能是互联网历史上的第一个虚假新闻&#xff1a;1984年&#xff0c;有人在…

android gpu 视频编码,android – 编码器崩溃对Adreno GPU编码从Surface

我一直在努力解决这个问题超过一个星期&#xff0c;很可能是一个错误的Qualcomm GPU /硬件视频编码器。因为我们被迫发布应用程序&#xff0c;并且他们的开发人员论坛没有提供任何反馈&#xff0c;我也在这里发布它&#xff0c;希望有人能够提供一些线索&#xff0c;或更好&…

穷举法破解集合小游戏~

游戏网站&#xff1a;http://www.setgame.com/puzzle/set.htm 游戏规则&#xff1a; 1、三种颜色&#xff08;红、绿、紫&#xff09; 2、三种外形&#xff08;方形、椭圆形、花形&#xff09; 3、三种背景阴影&#xff08;实心、点、轮廓&#xff09; 4、三种个数&#x…

AI时代数据之争,我们需要什么样的“数据权”?

来源&#xff1a; 腾讯研究院作者&#xff1a;田小军 腾讯研究院高级研究员1、未来是AI云端的数据竞争时代“兵无常势&#xff0c;水无常形”&#xff0c;今年11月4日&#xff0c;我国《反不正当竞争法》历时24年后首次修订&#xff0c;专设“互联网专条”用以规制互联网行业竞…

android点击通知后消失,通知栏点击后消失解决方法

通知栏点击后消失怎么使通知栏点击后消失啊&#xff1f;以下为我的代码&#xff0c;能实现将信息放入通知栏&#xff0c;但是点击后不消除。。。private void showNotification(String temp) {// 创建一个NotificationManager的引用NotificationManager notificationManager (…

Struts2 的Action 命名重复检测

原因&#xff1a;在实际项目中发现 <action /> 的 name 重复时候&#xff0c;Struts2 并不会报错而是随意找一个去执行&#xff01; 为了避免重复的情况发生&#xff0c;特地写了一个检测的程序&#xff1a; package barcode;import java.io.IOException; import java.i…

预测性智能的力量:AI 和机器学习将如何改变美国政府决策?

来源&#xff1a;36Kr在每个联邦机构中&#xff0c;重要的见解都隐藏在这些年来收集的大量数据集中。 但是由于美国联邦政府数据科学家的匮乏&#xff0c;如果真的要这么做的话&#xff0c;那么从这些数据中提取价值是非常耗时的。 然而&#xff0c;随着数据科学&#xff0c;人…

android 源码分析notification,# Notification 源码分析

引言notification.jpgNotification 在v7版本下从4.0后增加了Media Style. 今天我们分析下Notification在v7版本的源码。有助于我们针对不同版本的Notification做出合适样式选择。Notification使用流程现在我们使用Notification基本都是如下步骤:NotificationCompat.Builder bui…

广州签发全国首张微信身份证,AI成主要证明技术

来源&#xff1a;人工智能学家AItists概要&#xff1a;12月25日&#xff0c;广州市公安局南沙区分局、腾讯、建设银行等10余家单位发起的“微警云联盟”在广州南沙成立&#xff0c;现场签发了全国首张微信身份证“网证”。12月25日&#xff0c;广州市公安局南沙区分局、腾讯、建…

android底层设置相机帧率,Android Camera previewFrame 提高 fps

/*** http://my.oschina.net/lifj/blog/705104**/在做Camera预览的时候&#xff0c;通过PreviewFrame()方法获取数据&#xff0c;但是发现fps很低&#xff0c;一直在10~12fps徘徊。当然&#xff0c;有人推荐使用setPreviewCallbackWithBuffer。试了一下&#xff0c;fps没有明显…

android 视频做背景图片,视频后面怎么加背景图片?安卓手机给视频添加背景图片的方法...

狸窝是帮助用户解决问题 提供教程解决方案 在这个过程中有使用我们自己开发的软件 也有网上找的工具 只要帮助用户解决问题就好&#xff01;同意则往下继续了解学习 ...注意此教程方案是:『安卓手机端教程方案』。很多手机视频分享平台对视频参数都会有要求&#xff0c;手机上大…

MySQL中information_schema

来源&#xff1a;http://hi.baidu.com/starsw001/item/d151bd591cfb7f01e7c4a557 大家在安装或使用MYSQL时&#xff0c;会发现除了自己安装的数据库以外&#xff0c;还有一个information_schema数据库。 information_schema数据库是做什么用的呢&#xff0c;使用WordPress博客…

量子计算远没到可收割的时候

来源&#xff1a;风云之声概要&#xff1a;我们重视量子计算&#xff0c;是因为它的潜力&#xff0c;而不是它的现状。它确实有革命性的潜力&#xff0c;只是还需要艰苦的努力&#xff0c;绝不是一蹴而就的&#xff0c;更不是已经处在商业盈利的边缘&#xff0c;等着大家一哄而…

android 通知灯 测试,Android灯光系统通知灯【转】

标签&#xff1a;一、通知灯应用程序的编写1、首先实现一个按钮功能xmlns:tools"http://schemas.android.com/tools" android:layout_width"match_parent"android:layout_height"match_parent" android:paddingLeft"dimen/activity_horizon…

简评黑客利器——中国菜刀

来源&#xff1a;http://edu2b.sinaapp.com/?p236&replytocom17 作者&#xff1a;XXX 我是一个玩黑很多年的人&#xff0c;入侵了大大小小的服务器无数&#xff0c;体验着入侵快感的同时&#xff0c;自己的技术和经验也不断提高&#xff0c;在渗透过程中收集了大大小小的…

2017,AI偏见为何如此受关注?

来源&#xff1a;亿欧概要&#xff1a;从荒谬到令人不寒而栗&#xff0c;算法偏见在社会中产生越来越大的影响&#xff0c;而且这一问题已经暴露多年。但直到2017年&#xff0c;人们对AI算法偏见的公众意识似乎才达到了一个临界点。佛罗里达州的一项犯罪预测算法错误地将黑人罪…

android aidl工具,【Android】AIDL介绍和实例讲解

前言为使应用程序之间能够彼此通信&#xff0c;Android提供了IPC (Inter Process Communication&#xff0c;进程间通信)的一种独特实现&#xff1a; AIDL (Android Interface Definition Language&#xff0c; Android接口定义语言)。网上看了几篇关于AIDL的文章&#xff0c;写…

MySQL新建用户,授权,删除用户,修改密码

来源&#xff1a;http://www.cnblogs.com/analyzer/articles/1045072.html 首先要声明一下&#xff1a;一般情况下&#xff0c;修改MySQL密码&#xff0c;授权&#xff0c;是需要有mysql里的root权限的。 注&#xff1a;本操作是在WIN命令提示符下&#xff0c;phpMyAdmin同样…

机器学习 TOP 10 必读论文 | 资源

来源&#xff1a;AI科技大本营编辑 | DonnaMedium上的机器学习深度爱好者必关注的账号Mybridge照例对11月发表的学术论文进行了排名&#xff0c;整理出了10篇必读论文&#xff0c;建议收藏深读。1. Alpha Zero&#xff1a;用强化学习算法对中国象棋和国际象棋进行自我修炼&…

爱奇艺首页底部导航按钮android,仿爱奇艺/腾讯视频ViewPager导航条实现

仿爱奇艺/腾讯视频ViewPager导航条实现&#xff0c;支持自定义导航条高度&#xff0c;宽度&#xff0c;颜色变化&#xff0c;字体大小变化。支持多种滚动模式&#xff0c;支持自定义每个TabView的样式。项目地址&#xff1a;https://github.com/KCrason/DynamicPagerIndicatord…