通俗易懂的數(shù)獨算法(java版)

數(shù)獨算法

一 知識背景


二 緒言

? ? ? ? 偶爾玩下休閑益智小游戲板乙,一方面可以舒解下心情笙以,另一方面刺激下大腦皮層。百度了一下數(shù)獨 的起源和概念缩搅。說了那么多越败,看著就累。精簡一下就是數(shù)字(0-9)填充游戲硼瓣。不明白的來一張大圖究飞。看到了吧巨双,就這樣子滴~噪猾,先有個直觀印象吧霉祸。

數(shù)獨圖片

三 規(guī)則

? ? ? ?往簡單點說就3條:

? ? ? ?1.每個橫列需要1~9數(shù)值填充筑累,不能重復(fù)。

? ? ? ?2.每個縱列需要1~9數(shù)值填充丝蹭,不能重復(fù)慢宗。

? ? ? ?3.每個小的九方格里面需要1~9數(shù)值填充,不能重復(fù)奔穿。


橫镜沽,縱,小九方格 說明

四 算法分析

? ? ? ? 首先要寫出這個算法贱田,需要清楚里面的規(guī)則缅茉。數(shù)值可以用9*9的坐標(biāo)來表示,x,y坐標(biāo)在編程語言里面可以用對象男摧,數(shù)組等來表示蔬墩。我在這里選用的數(shù)據(jù)結(jié)構(gòu)有數(shù)組译打,棧。將算法分解一下拇颅,可以得到如下幾塊:

1.用數(shù)組[0][0],[8][8]來表示大的九宮格奏司,空白區(qū)域代表數(shù)值0。



2 小九宮格與九個坐標(biāo)的關(guān)系3n~3n+2樟插,橫縱都是如此韵洋。

_0_0 (n=0)代表第一個 ,里面有九個坐標(biāo):

? ? ? ? ?(0,0)(0,1)(0,2)

? ? ? ? ?(1,0)(1,1)(1,2)

? ? ? ? ?(2,0)(2,1)(2黄锤,2)

_0_1 (n=1)代表第二個 搪缨,里面有九個小坐標(biāo)

? ? ? ?(0,3)(0,4)(0,5)

? ? ? (1,3)(1,4)(1,5)

? ? ?(2,3)(2,4)(2,5)

? ? ? ? ? ? ? ? ? ? ? 猜扮。

? ? ? ? ? ? ? ? ? ? ? 勉吻。

? ? ? ? ? ? ? ? ? ? ? 。

? ? ? ? ? ? ? 其他類推.



3.規(guī)則

????????橫旅赢,縱齿桃,小方格,數(shù)值1~9值都填滿煮盼,不重復(fù)短纵。



4.判斷算法執(zhí)行完成

數(shù)組里面的值加起來為 9*(1+2+3+4+5+6+7+8+9) = 405 即可。



5. 根據(jù)3規(guī)則得到每個空點(也就是數(shù)值為0的)坐標(biāo)有幾個僵控,然后依次遞歸調(diào)用香到,直到使數(shù)組最后的值為405退出。


五.部分代碼參考

//橫縱坐標(biāo)校驗規(guī)則

public static booleanXYRule(intx, inty, int[][] a, intresult) {

? ? ? ? ? ?if(x >8|| x <0) {

? ? ? ? ? ? ? ? ? ? return false;

? ? ? ? ? ?}

? ? ? ? ? if(y <0|| y >8) {

? ? ?????????????return false;

????????}

? ? ? ? ?for(inti =0;i <9;i++) {//橫坐標(biāo)校驗

????????????if(a[x][i] == result) {

? ? ? ? ? ? ? ? ? return false;

????????????}

????????}

????????for(inti =0;i <9;i++) {//縱坐標(biāo)校驗

????????????if(a[i][y] == result) {

????????????????return false;

????????????}

????????}

????????return true;

}


//小九宮格校驗

public static booleanlitterBoxRule(intx, inty, int[][] a, intresult,Map> map) {

????????????List enumValues =getCoordinateEnumValue(x,y,map);

????????????for(Coordinate coordinate : enumValues) {

????????????????if(a[coordinate.getX()][coordinate.getY()] == result) {

????????????????????return false;

? ? ? ? ? ? ?????}

????????????}

????????????return true;

}


//判斷是否完成

public static booleanfinish(inta[][]) {

????????int ? sum =0;

????????for(inti =0;i <9;i++) {

????????????for(intj =0;j <9;j++) {

????????????????????sum += a[i][j];

????????????}

????????}

????????if(sum ==405) {

????????????return true;

????????}

????????return false;

}


//得到一個有效的坐標(biāo)點报破, 1.若果小九宮格已經(jīng)有八個了悠就,返回第九個坐標(biāo)點,2找到橫縱軸立面空白最少的返回

public staticCoordinatefindFirst(int[][] a,Map> map) {

????????????for(Map.Entry entry : map.entrySet()) {

????????????????int ?count =0;

????????????????Coordinate coordinate1 =newCoordinate();

????????????????for(Coordinate coordinate : (List) entry.getValue()) {

????????????????????if(a[coordinate.getX()][coordinate.getY()] !=0) {

????????????????????????count++;

????????????????????}else{

????????????????????????coordinate1 = coordinate;

????????????????}

????????????}

????????????if(count ==8) {

????????????return ?coordinate1;

????????????}

????????}

????????intx[] =new int[9];

????????inty[] =new int[9];

????????for(inti =0;i <9;i++) {

????????????for(intj =0;j <9;j++) {

????????????????if(a[i][j] !=0) {

????????????????????????x[i]++;

????????????????}

????????????????if(a[j][i] !=0) {

????????????????????????y[i]++;

????????????????}

????????????}

????????}

????????Coordinate maxA =findMax(x);

????????Coordinate maxB =findMax(y);

????????if(maxA.getX() < maxB.getX()) {

????????????intindexY = maxB.getY();

????????????for(inti =0;i <9;i++) {

????????????????????if(a[i][indexY] ==0) {

????????????????????????????Coordinate coordinate1 =newCoordinate(i,indexY);

????????????????????????????return coordinate1;

????????????????????}

????????????????}

? ? ? ? ? }else{

????????????????intindexX = maxA.getY();

????????????????for(inti =0;i <9;i++) {

? ? ? ? ? ? ? ? ? ? ? ? if(a[indexX][i] ==0) {

????????????????????????????????Coordinate coordinate1 =newCoordinate(indexX,i);

????????????????????????????????return ? ?coordinate1;

????????????????????????}

????????????????}

????????}

????????return null;//執(zhí)行到這說明數(shù)值已經(jīng)填充完了

}


//遞歸調(diào)用充易,找到相應(yīng)的值進(jìn)行填充梗脾,用棧來保存每一步,就和迷宮問題(數(shù)據(jù)結(jié)構(gòu)一種案例)一樣

public static voidfindBestValue(Coordinate coordinate, int[][] a,Map> map,StackList stackList) {

????????????List list =findRightValue(coordinate,a,map);

????????????for(Integer s : list) {

????????????????????if(!stackList.empty()) {

????????????????????????if(finish(a)) { ?//執(zhí)行完成

????????????????????????????return;

????????????????????????}

????????????????????Coordinate peek =null;

????????????????????peek = (Coordinate) stackList.peek();

? ? ? ? ? ? ? ? ? ? if(peek.getX() != coordinate.getX() || peek.getY() != coordinate.getY()) {//沒有就填充進(jìn)去

????????????????????????????stackList.push(coordinate);

????????????????????}

????????????}

????????????if(stackList.empty()) {

????????????????stackList.push(coordinate);

????????????}

????????????a[coordinate.getX()][coordinate.getY()] = s;

????????????Coordinate coordinate1 = SudoKuUtils.findFirst(a,map);

????????????if(coordinate1 ==null) {

????????????????????return;

????????????}

????????????List list2 =findRightValue(coordinate1,a,map);

????????????if(list2.size() ==0) {

????????????????????if(!stackList.empty()) {

????????????????????????Coordinate coordinate2 = (Coordinate) stackList.peek();

????????????????????????a[coordinate2.getX()][coordinate2.getY()] =0;

????????????????????????coordinate = (Coordinate) stackList.pop();

????????????????}

????????????}else{

????????????findBestValue(coordinate1,a,map,stackList);

????????}

????}

????if(!stackList.empty()) {

????????????Coordinate coordinate2 = (Coordinate) stackList.peek();

????????????if(coordinate.getX() == coordinate2.getX() && coordinate.getY() == coordinate2.getY()) {

????????????????????stackList.pop();

????????????????????a[coordinate2.getX()][coordinate2.getY()] =0;

????????????}

? ? ? ?}

}

六 . 結(jié)果分析

如下是一個骨灰級別的數(shù)獨

0,0,0, ? 0,0,6, ? ?0,0,0

0,3,6, ? 8,0,2, ? ?0,9,0

0,0,0, ? 9,0,0, ? ?0,5,0

9,2,0, ? 0,0,0, ? ?8,6,0

0,0,0, ? 0,0,0, ? ?0,0,0

0,1,8, ? 0,0,0, ? ?0,3,7

0,4,0, ? 0,0,5, ? ?0,0,0

0,8,0, ? 7,0,9, ? ?6,2,0

0,0,0, ? 6,0,0, ? ?0,0,0

代碼執(zhí)行一遍盹靴,用時81毫秒炸茧。

195 476 283

436 852 791

872 931 456

923 517 864

764 398 512

518 264 937

649 125 378

381 749 625

257 683 149

時間:81ms


紙上得來終覺淺,絕知此事要躬行

項目地址?https://gitee.com/YiHaiFeng/ShuDu.git

注 這里只求了一個解稿静。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末梭冠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子改备,更是在濱河造成了極大的恐慌控漠,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悬钳,死亡現(xiàn)場離奇詭異盐捷,居然都是意外死亡柬脸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門毙驯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來倒堕,“玉大人,你說我怎么就攤上這事爆价】寻停” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵铭段,是天一觀的道長骤宣。 經(jīng)常有香客問我,道長序愚,這世上最難降的妖魔是什么憔披? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮爸吮,結(jié)果婚禮上芬膝,老公的妹妹穿的比我還像新娘。我一直安慰自己形娇,他們只是感情好锰霜,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著桐早,像睡著了一般癣缅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哄酝,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天友存,我揣著相機(jī)與錄音,去河邊找鬼陶衅。 笑死屡立,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的万哪。 我是一名探鬼主播侠驯,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼抡秆,長吁一口氣:“原來是場噩夢啊……” “哼奕巍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起儒士,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤的止,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后着撩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诅福,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡匾委,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了氓润。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赂乐。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖咖气,靈堂內(nèi)的尸體忽然破棺而出挨措,到底是詐尸還是另有隱情,我是刑警寧澤崩溪,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布浅役,位于F島的核電站,受9級特大地震影響伶唯,放射性物質(zhì)發(fā)生泄漏觉既。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一乳幸、第九天 我趴在偏房一處隱蔽的房頂上張望瞪讼。 院中可真熱鬧,春花似錦粹断、人聲如沸尝艘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽背亥。三九已至,卻和暖如春悬赏,著一層夾襖步出監(jiān)牢的瞬間狡汉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工闽颇, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留盾戴,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓兵多,卻偏偏與公主長得像尖啡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子剩膘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容