1. 程式人生 > >android 數獨小遊戲

android 數獨小遊戲

偶然想起來寫一個數獨的小遊戲自己沒事的時候玩一玩,鍛鍊鍛鍊思路。

先上效果截圖

         

數獨生成的演算法,參見部落格:數獨生成演算法

數獨遊戲的最基礎的在於生成數獨,由於生成數獨的演算法運算問題,為了簡化,本次數獨的生成使用了 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 數獨