ฉันสร้างอัลกอริธึม DFS แบบเรียกซ้ำเพื่อสร้าง/แก้ไขบอร์ดซูโดกุใน Java แต่จะใช้เวลานานกว่าจะยุติ และยินดีรับฟังคำอธิบาย/การปรับให้เหมาะสม ฉันจินตนาการไม่ออกเลยว่าการสร้างกระดานซูโดกุจะใช้เวลานานขนาดนี้ โดยเฉพาะอย่างยิ่งกับแอปทั้งหมดที่อยู่รอบๆ (แม้ว่าแอปเหล่านั้นอาจมีฐานข้อมูลก็ตาม)
โดยพื้นฐานแล้ว ฉันจะสำรวจเซลล์ทั้งหมดเพื่อดูว่ามี [1-9] ใดที่จะเป็นไปตามข้อจำกัดของซูโดกุ และย้อนรอยกิ่งก้านทางตันหรือไม่ เพื่ออนุรักษ์หน่วยความจำและหลีกเลี่ยงการคัดลอกอาเรย์ 2 มิติที่ทำหน้าที่เป็นบอร์ดพร้อมกับการเรียกใช้เมธอดแบบเรียกซ้ำแต่ละครั้ง (และอาจมี 81*9! เหลืออยู่ในแผนผังนั้น ถ้าจำไม่ผิด...) ฉันจึงสร้าง 2D เมทริกซ์ของสแต็กจำนวนเต็ม ซึ่งองค์ประกอบจะถูกผลักทุกครั้งที่สำรวจสาขา และแตกออกมาหากเป็นจุดสิ้นสุด
ด้านล่างนี้คือการดำเนินการ ยินดีให้คำแนะนำเรื่องการเร่งความเร็วครับ ฉันทำสิ่งนี้เป็นแบบฝึกหัดส่วนตัว และฉันสงสัยว่ามีอะไรที่ดีกว่าแบบไม่มีสัญญาณกำกับอยู่หรือไม่
หวังว่ามันจะไม่แย่มากอ่านด้านล่าง .. ขอบคุณ!
1) การใช้อัลกอริทึม: (โปรดทราบว่าค่าอยู่ในอาร์เรย์ "ที่สับสน" ของ [1-9] เพื่อสร้างบอร์ดที่ไม่ซ้ำใคร)
/**
* Provides one solution to a board with an initial configuration, or <code>null</code> if there is none.
* The search is randomized, s.t. the algorithm can serve to populate an empty board.
*
* @param initial The initial board given to solve.
* @return The fully solved board, or null if no solution found.
*/
public static int[][] solveBoard (int[][] initial){
return solveBoard(new StackedBoard(initial), 0, 0);
}
private static int[][] solveBoard (StackedBoard board, int xPos, int yPos){
// base case - success
int remaining = 81;
for (int x = 0; x < 9; x++){
for (int y = 0; y < 9; y++){
if (board.peekAt(x, y) != Board.EMPTY){
remaining--;
}
}
}
if (remaining == 0){
return board.flatView();// the only creation of an array.
}
// recursive case
for (int x = 0; x < 9; x++){
for (int y = 0; y < 9; y++){
if (board.peekAt(x, y) == Board.EMPTY){
for (int val : getJumbledRandomVals()){
if (isMoveLegal(board, x, y, val)){
board.pushAt(x, y, val);
int[][] leafBoard = solveBoard(board, x, y);
if (leafBoard != null) {
return leafBoard;
}
}
}
}
}
}
// base case - dead branch
board.popAt(xPos, yPos);
return null;
}
2) การใช้งาน StackedBoard:
/**
* Represents square boards with stacked int elements.
*/
class StackedBoard {
ArrayList<ArrayList<Stack<Integer>>> xaxis = new ArrayList<ArrayList<Stack<Integer>>>();
/**
*
* @param init A square array - both dimensions of equal length, or <code>null</code> if no initialization.
*/
public StackedBoard (int[][] init) {
for (int i = 0; i < 9; i++){
ArrayList<Stack<Integer>> yaxis = new ArrayList<Stack<Integer>>();
xaxis.add(yaxis);
for (int j = 0; j < 9; j++){
Stack<Integer> stack = new Stack<Integer>();
yaxis.add(stack);
}
}
if (init != null){
for (int x = 0; x < init.length; x++){
for (int y = 0; y < init.length; y++){
getStackAt(x, y).push(init[x][y]);
}
}
}
}
public Stack<Integer> getStackAt (int x, int y){
return xaxis.get(x).get(y);
}
public int peekAt (int x, int y){
return getStackAt(x, y).peek();
}
public void pushAt (int x, int y, int value){
getStackAt(x, y).push(value);
}
public Integer popAt (int x, int y){
try {
return getStackAt(x, y).pop();
} catch (EmptyStackException e){
// shhhhh!
return Board.EMPTY;
}
}
/**
* Flat view of the stacked-board; peek of the top elements.
*/
public int[][] flatView (){
int[][] view = new int[xaxis.size()][xaxis.size()];
for (int x = 0; x < xaxis.size(); x++){
for (int y = 0; y < xaxis.size(); y++){
view[x][y] = getStackAt(x, y).peek();
}
}
return view;
}
}
3) การใช้ฟังก์ชันข้อจำกัด:
/**
* Is the move legal on the suggested board?
*
* @param board The board.
* @param x The X coordinate, starts with 0.
* @param y The Y coordinate, starts with 0.
* @param value The value.
* @return <code>true</code> iff the move is legal.
*/
private static boolean isMoveLegal (StackedBoard board, int x, int y, int value){
// by value
if (1 > value || value > 9){
return false;
}
// by column
for (int i = 0; i < 9; i++){
if (board.peekAt(i, y) == value){
return false;
}
}
// by row
for (int i = 0; i < 9; i++){
if (board.peekAt(x, i) == value){
return false;
}
}
// by lil square
int lowerX = x < 3 ? 0 : (x < 6 ? 3 : 6);
int upperX = lowerX + 2;
int lowerY = y < 3 ? 0 : (y < 6 ? 3 : 6);
int upperY = lowerY + 2;
for (int i = lowerX; i <= upperX; i++){
for (int j = lowerY; j <= upperY; j++){
if (board.peekAt(i, j) == value){
return false;
}
}
}
return true;
}