摘要:首先在二維數組第一行隨機填充個數字,然后將這個數字隨機分布到整個二維數組中,然后使用求解數獨的算法對此時的數組進行求解,得到一個完整的數獨,然后按照用戶輸入的提示數量進行隨機挖洞,得到最終的數獨題目。
思路 1.生成數獨
數獨的生成總體思路是挖洞法。
首先在二維數組第一行隨機填充1-9 9個數字,然后將這9個數字隨機分布到整個二維數組中,然后使用求解數獨的算法對此時的數組進行求解,得到一個完整的數獨,然后按照用戶輸入的提示數量進行隨機挖洞,得到最終的數獨題目。
這種方法理論上可以隨機生成(81!/72! = 9.5e+16)種不同的數獨題目,足夠人類玩上幾百年了。
求解數獨使用的是計算機最擅長的暴力搜索中的回溯法。并結合人求解數獨的思維過程增加了一點改進。
在每一層搜索中,首先計算每個格子可以填充的值的個數(我命名為不確定度),如果有格子不確定度為1,則直接填上數字就好,否則對不確定度最小的格子使用可能的數字逐個填充,并進入下一次遞歸。如果發現不確定度為0的格子,做說明之前的過程有問題,需要進行回溯。
package sudo; import java.util.Scanner; /** * @description 數獨生成和求解 * @limit 支持從1-80的數字提示數量 * @method 深度優先搜索/回溯法 * @author chnmagnus */ public class Sudo { private int[][] data = new int[9][9]; //muti_array private int lef; //the number of zero in array private int tip; //the number of nozero_digit in array /** * 構造函數 * 初始化變量 */ public Sudo(){ lef = 0; for(int i=0;i<9;++i){ for(int j=0;j<9;++j){ data[i][j] = 0; } } } /** * 生成數獨 * 方法:挖洞法 */ public void genSudo(){ System.out.println("Please input the number of digits provided:"); Scanner scan = new Scanner(System.in); tip = scan.nextInt(); scan.close(); /*將1-9 9個數字放在二維數組中隨機位置*/ lef = 81 - 9; for(int i=0;i<9;++i){ data[0][i] = i+1; } for(int i=0;i<9;++i){ int ta = (int)(Math.random()*10)%9; int tb = (int)(Math.random()*10)%9; int tem = data[0][ta]; data[0][ta] = data[0][tb]; data[0][tb] = tem; } for(int i=0;i<9;++i){ int ta = (int)(Math.random()*10)%9; int tb = (int)(Math.random()*10)%9; int tem = data[0][i]; data[0][i] = data[ta][tb]; data[ta][tb] = tem; } /*通過9個數字求出一個可行解*/ solveSudo(); lef = 81 - tip; for(int i=0;i0) System.out.print(data[i][j]+" "); else System.out.print("* "); } System.out.print(" "); } System.out.println("-----------------"); } /** * 計算某格子的可填數字個數,即不確定度 * @param r * @param c * @param mark * @return 不確定度 */ private int calcount(int r,int c,int[] mark){ for(int ti=0;ti<10;++ti) mark[ti] = 0; for(int i=0;i<9;++i){ mark[data[i][c]] = 1; mark[data[r][i]] = 1; } int rs = (r/3)*3; int cs = (c/3)*3; for(int i=0;i<3;++i){ for(int j=0;j<3;++j){ mark[data[rs+i][cs+j]] = 1; } } int count = 0; for(int i=1;i<=9;++i){ if(mark[i]==0) count++; } return count; } /** * 供solve調用的深度優先搜索 * @return 是否有解的boolean標識 */ private boolean dfs(){ if(lef==0) return true; int mincount = 10; int mini = 0,minj = 0; int[] mark = new int[10]; /*找到不確定度最小的格子*/ for(int i=0;i<9;++i){ for(int j=0;j<9;++j){ if(data[i][j]!=0) continue; int count = calcount(i,j,mark); if(count==0) return false; if(count 演示 以下四幅圖分別是輸出為0,20,60的程序運行結果。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/65647.html
摘要:可以針對筆者常用的數獨本文的實現都基于該,實現數獨的識別求解并把答案自動填入。專家級別的平均秒完成求解包括圖像數字提取,識別過程,完成全部操作。步驟四數獨求解,生成答案,并生成需要填充的數字序列。 1 序 ??數獨是源自18世紀瑞士的一種數學游戲。是一種運用紙、筆進行演算的邏輯游戲。玩家需要根據9×9盤面上的已知數字,推理出所有剩余空格的數字,并滿足每一行、每一列、每一個粗線宮(3*3...
摘要:數獨技巧直觀法候選數法相關二十格一個數字只與其所在行列及小九宮格的二十格相關我的思路精心設計了有效性判定函數,最多一次遍歷個小單元格就能做出方案的有效性判定。 看《算法的樂趣》,試著用非遞歸窮舉來解數獨,看效率如何! 數獨規則 數獨游戲,經典的為9×9=81個單元格組成的九宮格,同時也形成了3×3=9個小九宮格,要求在81個小單元格中填入數字1~9,并且數字在每行每列及每個小九宮格中都...
摘要:而此處針對進一步的搜索,有兩個問題需要考慮如何選取搜索起點方格確定哪種搜索策略深度優先搜索,廣度優先搜索關于第一個問題,無論選擇哪個方格起始搜索,對于能否解決問題來說并不存在差異。 Github倉庫地址 學習是為了尋找解決問題的答案,若脫離了問題只為知曉而進行的打call,那么隨時間流逝所沉淀下來的,估計就只有重在參與的虛幻存在感了,自學的人就更應善于發現可供解決的問題。為了入門AI,...
摘要:前言最近的后臺管理系統頁面,功能暫時沒有新的需求,就在想首頁放什么東西,最近我想到的就是放個所謂的數獨,為什么是所謂的數獨,因為規則不同于標準的數獨,只要求每一行每一列數字不一樣就可以了這個實例也是基于的,代碼分享給大家。 1.前言 最近的后臺管理系統頁面,功能暫時沒有新的需求,就在想首頁放什么東西,最近我想到的就是放個所謂的數獨,為什么是所謂的數獨,因為規則不同于標準的數獨,只要求每...
閱讀 855·2019-08-30 15:54
閱讀 3322·2019-08-29 15:33
閱讀 2707·2019-08-29 13:48
閱讀 1229·2019-08-26 18:26
閱讀 3339·2019-08-26 13:55
閱讀 1491·2019-08-26 10:45
閱讀 1173·2019-08-26 10:19
閱讀 312·2019-08-26 10:16