Java數獨算法(原創)

import java.util.Scanner;

public class Shudu_sy {

	// shanshan是存儲上次
	static int[] shanshan = new int[81];
	static int[][] num_aa = new int[9][9];
	static int[][] num_bb = new int[9][9];
	static int[] num_all = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

	public static void main(String[] args) {
		scan_num(); // 輸入數組
		change_shan();// 初始化我們的統計數組shanshan
		change(0, 0); // 這個0,0 (這裏不是表情)是對應數組的第0行0列,這個功能主要是方便大家可以在這個代碼的基礎上修改
	}

	// 初始化該計數數組
	public static void change_shan() {
		for (int i = 0; i < shanshan.length; i++) {
			shanshan[i] = 0;
		}
	}

	// 這裏面的shanshan數組是用來記錄上次該爲存儲的是第幾個數據,shanshan的下邊對應該9*9數組中
	// 的行x*9+列y,即x*9+y

	// 採用遞歸調用,如果失敗則返回上一步
	public static void change(int x, int y) {
		int yy = y; // 這裏的yy是因爲我採用遞歸調用,改變這個雙層for循環的i和j的值
		a: for (int i = 0; i < 9; i++) {
			// 標籤a也是爲了返回上一步的跳轉做準備的
			for (int j = yy; j < 9; j++) {
				if (j == 8) {
					yy = 0;
				}
				// yy默認爲0,跳轉後指定位置後j每次開始的位置會發生改變,所以我選擇把他手動置0(從0開始)
				if (num_bb[i][j] == 0) {
					// num_bb是備份數組,用來測試這個位置是否本來是空
					int num = sy(i, j, i * 9 + j);
					if (num != -1) {// 有正確數據的時候
						num_aa[i][j] = num;// 我們在該位置填充該數據(num_aa中更新數據)
					} else if (num == -1) {// 如果沒有正確數據,我們執行返回上一步操作
						String[] aa = sys(num_bb, i, j).split(",");
						i = Integer.parseInt(aa[0]) - 1;// 對應i的位置,但是因爲i++,所以我們提前先-1
						yy = Integer.parseInt(aa[1]);// 直接對應j的位置,不需要-1
						continue a;
					}
				}
			}
		}
		for (int i = 0; i < 9; i++) {
			for (int j = 0; j < 9; j++) {
				System.out.print(num_aa[i][j] + ",");
			}
			System.out.println();
		}
		// 如果該數獨已經計算完畢,我們把該數獨輸出出來,大家也可以把這個輸出給美化一下
	}

	// 清空錯誤數據的緩存
	// 當然這一步和這一步後num_aa中的數據和shanshan中的緩存必須要被清空
	public static void clean(int x, int y) {
		int num = x * 9 + y;
		for (int i = num; i < 81; i++) {
			shanshan[i] = 0;
		}
		for (int i = 0; i < 9; i++) {
			for (int j = 0; j < 9; j++) {
				if (i * 9 + j >= num) {
					num_aa[i][j] = num_bb[i][j];
				}
			}
		}
	}

	// 進行返回上一步操作,同時把這一步後面的shanshan裏的數據清空。
	public static String sys(int[][] aa, int x, int y) {
		clean(x, y);
		for (int i = 8; i >= 0; i--) {
			for (int j = 8; j >= 0; j--) {
				if (num_bb[i][j] != num_aa[i][j] && i * 9 + j < x * 9 + y) {
					return i + "," + j;
				}
			}
		}
		return null;
		// 再清空數據之後,我們獲得上一個num_bb中爲0的數據的位置,以i,j的形式返回
	}

	// 輸出一個可能是正確的答案,如果不存在則輸出-1,同時更新shanshan裏面的數據
	public static int sy(int x, int y, int a) {
		if (shanshan[a] == 9) {
			return -1;
		}// 如果該位置的緩存爲9,表明該位置沒有正確數據
		for (int i = shanshan[a]; i < 9; i++) {// 從上一次正確位置之後開始
			if (testOne(num_all[i], x, y) == 0) { // 如果有一個正確的數據,即返回0的時候
				shanshan[a] = num_all[i];// 我們先把緩存更新
				return num_all[i];// 同時返回這個正確的數據
			}
		}
		return -1; // 如果沒有正確的數據我們就返回-1
	}

	// 這個sy函數是對該位置進行測試,看該位置是否存在一個正確的數據

	// 傳入要測試的數據,和該數據所在的行和列,看是否存在數據重複,無衝突輸出0,有衝突輸出-1
	public static int testOne(int num, int x, int y) {

		// 檢測該行該列是否有重複數字出現
		for (int i = 0; i < 9; i++) {
			if (num_aa[x][i] == num || num_aa[i][y] == num) {
				return -1;
			}
		}
		// num_aa是我們用來修改的數據數組

		// 檢測3*3的正方塊中是否有重複數字出現
		for (int i = x / 3 * 3; i < x / 3 * 3 + 3; i++) {
			for (int j = y / 3 * 3; j < y / 3 * 3 + 3; j++) {
				if (i == x && j == y) {
					break;
					// 如果是該空格自身則不用比較
				} else if (num_aa[i][j] == num) {
					return -1;
					// 如果該方格已存在該數據則返回-1
				}
			}
		}
		// 這裏x/3*3,y/3*3後會自定確定該該數據所對應的3*3小方格的左上角那個數據,然後再對該數據i和j進行++操作

		return 0;
		// 如果該方格不存在這個數據則返回0
	}

	// 輸入該9*9九宮格,用英文下的逗號隔開,如果爲空則輸入0
	public static void scan_num() {
		System.out.println("please input information");// 提示代碼
		Scanner scanner = new Scanner(System.in);
		for (int i = 0; i < 9; i++) {
			String a[] = scanner.nextLine().split(",");
			for (int j = 0; j < a.length; j++) {
				num_aa[i][j] = Integer.parseInt(a[j]);
				num_bb[i][j] = Integer.parseInt(a[j]);
				// 這裏採用兩個相同的數組,是因爲等會要對第一個數組num_aa進行操作,操作的時候和數組num_bb進行對比,來區分
				// 這個方格對應的數字是後來自己寫的,還是原本系統就有的
			}
		}

		// 直接兩個for循環輸入
		scanner.close();
		System.out.println("input end");
	}

	// 這是一段簡單的輸入程序
}


這個小程序採用的簡單的模塊處理機制,沒事寫着玩玩。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章