1. 程式人生 > >java數獨生成演算法(遞迴)

java數獨生成演算法(遞迴)

	.....
	ArrayList<JTextField> list = new ArrayList<JTextField>();   // 數獨的格子
	ArrayList<ArrayList<Integer>> insertArray = new ArrayList<ArrayList<Integer>>();
	/**
	 * <li> 生成一個隨機的填滿的數獨
	 * 		private void solution(int index, ArrayList<ArrayList<Integer>> insertArray)
	 * <p><p><P> 描述: 通過遞迴的方式生成一個隨機的填滿的數獨,實現原理是首先通過傳入的下標判斷當前位置是否有可以填入
	 * 的數字,如果有將當前數字填入,並將當前的可填入的數字的集合(出去已經填入的數字)儲存到方法的另一個引數ArrayList<ArrayList<Integer>> insertArray
	 * 中,再遞迴。否則嘗試修改前一個座標的下的填入的數字,如果前一個座標下的對應的ArrayList<ArrayList<Integer>> insertArray中的ArrayList<Integer>中還有可
	 * 插入的數字則修改前一個座標下的數字,再遞迴,否則將前一個位置中的內容置空,將遞迴起點指定到前一位置,然後遞迴。(其中,如果當前位置上的ArrayList<ArrayList<Integer>> insertArray
	 * 中包含了當前位置的可插入數字的集合,則表示本次遞迴為上次插入不成功導致的,所以將該數字的集合當做當前可插入的數字的集合,這樣一方面可以減少重複判斷的次數
	 * 提高程式碼效率,同時使程式碼邏輯合理)
	 * @param index list的下標
	 * @param insertArray 可插入數字的集合(已經去掉已插入的)的集合
	 */
	private void solution(int index, ArrayList<ArrayList<Integer>> insertArray) {
		if (index>80) return;
		else {
			ArrayList<Integer> insert = insertable(index/9, index%9);
			if (insertArray.size()>index) insert = insertArray.remove(index);  // 次步驟非常關鍵,
			if (insert.size()>0) {
				list.get(index).setText(insert.remove(0).toString());
				insertArray.add(insert);
				solution(++index, insertArray); // dg
			}
			else {
				--index;
				ArrayList<Integer> preInsert = insertArray.get(index);
				if (preInsert.size()>0) {
					list.get(index).setText(insertArray.get(index).remove(0).toString());
					solution(++index, insertArray); // dg
				}
				else {
					list.get(index).setText("");
					solution(index, insertArray); //dg
				}
			}
		}
	}
	
	/**
	 * description:隨機生成 from-to 的整數
	 * @param from 從哪個數字開始
	 * @param to 到哪個數字結束
	 * @return (int) 隨機數
	 */
	private int randomNum(int from, int to) {
		return  from + (int) (Math.random()*(to-from+1));
	}
	/**
	 * description: 獲取當前位置可填入的數字
	 * @param indexI	行座標
	 * @param indexJ	列座標
	 * @return base 可填入的數字的集合 
	 */
	private ArrayList<Integer> insertable(int indexI, int indexJ) {
		
		ArrayList<Integer> base = new ArrayList<Integer>();
		for (int i = 1; i <= 9; i++) base.add(i);
		Collections.shuffle(base);
		String str = null;
		// 判斷區填入
		int regionI = (indexI/3)*3;
		int regionJ = (indexJ/3)*3;
		for (int i = regionI; i < regionI+3; i++) {
			for (int j = regionJ; j < regionJ+3; j++) {
				str = list.get(i*9+j).getText();	
				// 之後base中只剩下該區中可填的數字
				if (str!=null&&!str.equals("")) { 
					if (base.contains(Integer.parseInt(str)))	
						base.remove(base.indexOf(Integer.parseInt(str)));	
				}
			}
		}
		// 判斷行填入
		for (int j = 0; j < 9; j++) {
			str = list.get(indexI*9+j).getText();
			// 之後base中只剩下行中可填入的數字
			if (str!=null&&!str.equals("")) { 
				if (base.contains(Integer.parseInt(str)))
					base.remove(base.indexOf(Integer.parseInt(str)));
			}
		}
		// 判斷列填入
		for (int i = 0; i < 9; i++) {
			str = list.get(i*9+indexJ).getText();
			 // 之後base中只剩下列中可填入的數字
			if (str!=null&&!str.equals("")) { 
				if (base.contains(Integer.parseInt(str)))
					base.remove(base.indexOf(Integer.parseInt(str)));
			}
		}
		base.trimToSize();
		return base;
	}