android 數獨小遊戲
阿新 • • 發佈:2018-12-13
偶然想起來寫一個數獨的小遊戲自己沒事的時候玩一玩,鍛鍊鍛鍊思路。
先上效果截圖
數獨生成的演算法,參見部落格:數獨生成演算法
數獨遊戲的最基礎的在於生成數獨,由於生成數獨的演算法運算問題,為了簡化,本次數獨的生成使用了 10 個基類,每次生成數獨的時候隨機從是個基類中選取一個模板,在根據模板將對應的 a--i 的字母 隨機與 1--9 分別對應,然後生成一個數獨。
數獨模板基類
public class StandShudu { /** * 從10個基準陣列中抽取一個基準陣列 * 然後將 a-i 隨機分配 1-9 * 隨機賦予 a--i的值為不重複的 1--9 的值 生成一個數組 * 有多少種可能我也不會算,反正夠玩的了 */ public String[][] getStand(int index){ switch (index){ case 0: return stand0; case 1: return stand1; case 2: return stand2; case 3: return stand3; case 4: return stand4; case 5: return stand5; case 6: return stand6; case 7: return stand7; case 8: return stand8; case 9: return stand9; default: return stand0; } } private String[][] stand1=new String[][]{ {"c","h","e","b","i","a","g","f","d",}, {"f","b","d","g","e","c","h","a","i",}, {"g","i","a","d","f","h","c","e","b",}, {"h","g","i","e","d","b","a","c","f",}, {"a","d","f","c","g","i","b","h","e",}, {"e","c","b","h","a","f","i","d","g",}, {"b","e","c","f","h","g","d","i","a",}, {"i","f","g","a","c","d","e","b","h",}, {"d","a","h","i","b","e","f","g","c",} }; private String[][] stand2=new String[][]{ {"a","c","f","b","d","e","h","i","g",}, {"b","g","d","h","i","a","f","c","e",}, {"h","i","e","f","c","g","b","a","d",}, {"d","f","b","g","e","c","a","h","i",}, {"g","a","i","d","h","f","c","e","b",}, {"e","h","c","i","a","b","g","d","f",}, {"i","e","g","a","f","h","d","b","c",}, {"c","b","h","e","g","d","i","f","a",}, {"f","d","a","c","b","i","e","g","h",} }; private String[][] stand3=new String[][]{ {"f","g","h","e","i","d","b","a","c",}, {"e","b","c","f","a","g","i","h","d",}, {"d","a","i","c","h","b","f","e","g",}, {"i","f","d","a","g","e","c","b","h",}, {"b","h","a","i","d","c","g","f","e",}, {"c","e","g","b","f","h","a","d","i",}, {"h","c","b","g","e","f","d","i","a",}, {"a","d","f","h","c","i","e","g","b",}, {"g","i","e","d","b","a","h","c","f",} }; private String[][] stand4=new String[][]{ {"i","a","h","b","c","f","d","e","g",}, {"f","d","e","g","i","h","b","c","a",}, {"b","c","g","e","a","d","i","f","h",}, {"g","i","f","c","b","a","h","d","e",}, {"d","h","a","f","g","e","c","i","b",}, {"e","b","c","h","d","i","a","g","f",}, {"a","g","b","i","e","c","f","h","d",}, {"h","e","i","d","f","b","g","a","c",}, {"c","f","d","a","h","g","e","b","i",} }; private String[][] stand5=new String[][]{ {"h","e","d","b","f","g","a","c","i",}, {"c","i","a","d","e","h","b","g","f",}, {"f","b","g","a","i","c","e","h","d",}, {"a","f","i","e","g","d","h","b","c",}, {"d","g","h","c","b","f","i","a","e",}, {"e","c","b","h","a","i","d","f","g",}, {"g","d","e","f","h","b","c","i","a",}, {"b","a","f","i","c","e","g","d","h",}, {"i","h","c","g","d","a","f","e","b",} }; private String[][] stand6=new String[][]{ {"i","g","b","f","a","h","e","c","d",}, {"c","a","h","d","g","e","i","b","f",}, {"f","d","e","b","c","i","h","a","g",}, {"b","c","a","e","d","g","f","h","i",}, {"g","e","i","h","f","a","b","d","c",}, {"h","f","d","c","i","b","a","g","e",}, {"a","i","c","g","b","f","d","e","h",}, {"d","h","f","a","e","c","g","i","b",}, {"e","b","g","i","h","d","c","f","a",} }; private String[][] stand7=new String[][]{ {"d","g","c","i","e","f","b","h","a",}, {"f","e","h","a","b","c","g","i","d",}, {"a","b","i","d","g","h","c","f","e",}, {"e","a","g","f","d","b","i","c","h",}, {"i","c","d","e","h","g","f","a","b",}, {"b","h","f","c","i","a","e","d","g",}, {"h","d","b","g","f","i","a","e","c",}, {"c","f","e","b","a","d","h","g","i",}, {"g","i","a","h","c","e","d","b","f",} }; private String[][] stand8=new String[][]{ {"e","f","g","a","d","c","b","h","i",}, {"d","i","h","b","g","f","a","e","c",}, {"c","a","b","e","h","i","d","f","g",}, {"i","h","f","d","b","g","c","a","e",}, {"g","e","a","i","c","h","f","d","b",}, {"b","d","c","f","e","a","g","i","h",}, {"a","c","e","h","f","b","i","g","d",}, {"h","b","i","g","a","d","e","c","f",}, {"f","g","d","c","i","e","h","b","a",} }; private String[][] stand9=new String[][]{ {"d","a","g","e","f","c","h","i","b",}, {"f","b","i","g","d","h","e","a","c",}, {"e","c","h","i","b","a","g","d","f",}, {"h","d","f","c","a","e","b","g","i",}, {"i","g","a","b","h","f","c","e","d",}, {"c","e","b","d","i","g","f","h","a",}, {"a","f","c","h","e","i","d","b","g",}, {"g","h","d","a","c","b","i","f","e",}, {"b","i","e","f","g","d","a","c","h",} }; private String[][] stand0=new String[][]{ {"a","b","i","g","d","e","c","h","f",}, {"c","h","f","b","a","i","e","d","g",}, {"e","d","g","c","f","h","b","i","a",}, {"d","e","b","a","h","c","g","f","i",}, {"h","i","c","f","g","b","d","a","e",}, {"g","f","a","i","e","d","h","c","b",}, {"i","c","h","e","b","f","a","g","d",}, {"b","g","d","h","i","a","f","e","c",}, {"f","a","e","d","c","g","i","b","h",} };
獲取數獨的類 ,隨機獲取一個模板,然後用 1--9 填充
public class ShuduData { private int[][] number = new int[9][9]; private StandShudu standShudu=new StandShudu(); private Random random=new Random(); public int[][] generateShuDu(){ /*** 獲取隨機的模板 **/ String[][] stand=standShudu.getStand(random.nextInt(10)); /** 帶選擇數字列表 **/ ArrayList<Integer> data=new ArrayList<Integer>(); data.add(1); data.add(2); data.add(3); data.add(4); data.add(5); data.add(6); data.add(7); data.add(8); data.add(9); /*** 隨機儲存排序 **/ int[] s=new int[9]; int index=0; while (index<9){ int t=random.nextInt(data.size()); s[index]=data.get(t); data.remove(t); index++; } /** 根據模板按照獲取的隨機序列進行資料填充 **/ for(int i=0;i<9;i++){ for(int j=0;j<9;j++){ number[i][j]=s[getIndex(stand[i][j])-1]; } } return number; } private Integer getIndex(String s){ switch (s){ case "a": return 1; case "b": return 2; case "c": return 3; case "d": return 4; case "e": return 5; case "f": return 6; case "g": return 7; case "h": return 8; case "i": return 9; default: return 1; } }
使用此方法雖然不能 模擬出數獨的所有的可能,但是為了簡化演算法採用此方法。
根據獲取的數獨陣列初始化遊戲介面
/** * 初始化資料 */ private fun initSize(){ data= emptyArray() data= ShuduData().generateShuDu() val initData=Array(9) { IntArray(9) } for(i in 0 until 9){ for(j in 0 until smd){ val ranNum = random.nextInt(9) initData[i][ranNum]=data[i][ranNum] } } nv_01.number=initData }
smd 為數獨的難易程度(即每一列的提示資料的個數)
由於數獨的不確定性,當所有的數字被填滿時,並不能用最初獲取的數獨陣列與填完的陣列進行比對校驗(在陣列中部分資料的位置具有不確定性)。填玩的陣列需要根據數獨的校驗方法進行校驗(即橫豎不相同,所在的小的 3 * 3 的數組裡面也不能相同)。校驗的演算法如下:
//校驗
private void checkIsRight(){
boolean right=true;
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
int node=number[i][j];
//此位置尚未填寫
if(node==0){
listener.onResultIsTrue(false,-1);
return;
}
//橫向檢查是否有相同的項 ,檢查當前節點往後的節點
for(int sx=i+1;sx<9;sx++){
if(node==number[sx][j]){
right=false;
error[sx][j]=node;
error[i][j]=node;
}
}
//縱向檢查是否有相同的項 ,檢查當前節點往下的節點
for(int sy=j+1;sy<9;sy++){
if(node==number[i][sy]){
right=false;
error[i][sy]=node;
error[i][j]=node;
}
}
//根據下標判斷 當前節點所在的 3 X 3 的格子中數字是否重複
//已重複的數字放入 error 陣列對應的下標
int xi=i/3;
int yi=j/3;
for(int vx=0;vx<3;vx++){
for(int vy=0;vy<3;vy++){
if((3*xi+vx)!=i && (3*yi+vy)!=j){
if(node==number[3*xi+vx][3*yi+vy]){
right=false;
error[3*xi+vx][3*yi+vy]=node;
error[i][j]=node;
}
}
}
}
}
}
listener.onResultIsTrue(right,0);
}
此外本專案中還包括了 ShareSdk微信QQ的分享,以及bmob後端雲的簡單使用。詳情見專案原始碼。
碼雲中國 git 原始碼連結:Android 數獨