1. 程式人生 > >React-native數獨遊戲(一)數獨生成與校驗

React-native數獨遊戲(一)數獨生成與校驗

react-native還是蠻火的,前面用它做了一個火車票查詢的,感覺還可以,繼續研究,寫了這個數獨小遊戲,和大家分享一下。
github原始碼地址
這裡寫圖片描述
第一部分是關於數獨生成的部分,數獨規則很簡單,行列都沒有重複,每個九宮格也不能重複,演算法也是依照此規則去實現。先生成一張完整的數獨表,再去扣掉一些數字,最後變成題目。
我是先行後列去一格一格去放數字的,先放第一行,這個直接打亂順序放入就可以。然後從第二行開始一格一格試數字。
每行初始化一個9個數字的陣列,然後去比較前面和上面的數字,相同的從陣列中去除,然後再比較九宮格中已經放入的數字,從陣列中去除,最後取陣列中的第一個數字放入格子。
發現直接這麼處理經常會碰陣列空了,其實就是當前數獨不成立了,我的做法比較簡單粗暴,直接當前行重新計算,基本上沒碰到算不出來的,有興趣的可以繼續優化,效率最高的方法是一格一格倒退。

//計算完整數獨表
export function _calculateData() {
    _initMyFunc();
    let count = 0;
    let rootArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    //二維陣列存放數獨
    let Sudoku = new Array(9);
    for (let i = 0; i < 9; i++) {
        Sudoku[i] = new Array(9);
    }
    //打亂陣列後賦值給第一行
    _caosArray(rootArray);
    _caosArray(rootArray);
    Sudoku[0
] = rootArray.concat(); for (x = 1; x < 9; x++) { //每行賦值前先打亂陣列,保證與上一行不同 _caosArray(rootArray); let rowArray = rootArray.concat(); for (y = 0; y < 9; y++) { //刪除行內重複數字 tempNum = Sudoku[x][y - 1]; rowArray.remove(tempNum); _caosArray(rowArray); //刪除列內重複數字,複製一份行陣列,行內迴圈中,保持rowArray每次減一個重複數字
let tempRowArray = rowArray.concat(); for (let m = x - 1; m >= 0; m--) { tempNum = Sudoku[m][y]; tempRowArray.remove(tempNum); count++; } // console.log('before rowArray=>>>>' + rowArray); // console.log('before tempRowArray=>>>>' + tempRowArray); // console.log('before y=>>>>' + y); //刪除3X3中的重複數字,就是當前行上面兩行說有數字 //計算穿小格中的相對位置 let positionX = x % 3; let positionY = y % 3; for (positionX; positionX > 0; positionX--) { for (let a = 0; a < 3; a++) { if (a != positionY) { tempNum = Sudoku[x - positionX][y - positionY + a]; tempRowArray.remove(tempNum); // console.log("tempNum=>>>>>" + tempNum); count++; if (count > 2500) return -1; } } } if (tempRowArray.length > 0) { Sudoku[x][y] = tempRowArray[0]; } else { _caosArray(rootArray); rowArray = rootArray.concat(); y = -1; } // console.log("after tempRowArray=>>>>>" + tempRowArray); // console.log("after rowArray=>>>>>" + rowArray); // console.log("after y=>>>>>" + y); } } console.log(Sudoku); console.log('計算' + count + '次'); return Sudoku; } //打亂一個數組 export function _caosArray(array) { let temp; for (i = 0; i < array.length - 1; i++) { if (Math.random() > 0.5) { let index = Math.floor(Math.random() * array.length); temp = array[i]; array[i] = array[index]; array[index] = temp; } } }

數獨完成後,就要開始校驗,依然一樣,直接上程式碼

//校驗數獨
export function _checkSudoku(Sudoku) {
    let result = {code: 0}
    //檢查時候有空格
    for (let x = 0; x < 9; x++) {
        for (let y = 0; y < 9; y++) {
            if (Sudoku[x][y].num == 0) {
                result.msg = '請填滿所有空格'
                return result
            }
        }
    }
    for (let x = 0; x < 9; x++) {
        for (let y = 0; y < 9; y++) {
            //行是否有相同
            for (let z = 8 - y; z > 0; z--) {
                if (Sudoku[x][y].num == Sudoku[x][9 - z].num) {
                    result.msg = '錯誤,請檢查'
                    return result
                }
            }
            //列是否有相同
            for (let z = 8 - x; z > 0; z--) {
                if (Sudoku[x][y].num == Sudoku[9 - z][y].num) {
                    result.msg = '錯誤,請檢查'
                    return result
                }
            }
            //九宮格是否相同
            let positionX = x % 3;
            let positionY = y % 3;
            for (let m = positionX + 1; m < 3; m++) {
                for (let n = 0; n < 3; n++) {
                    if (n != positionY) {
                        if (Sudoku[x][y].num == Sudoku[x + m - positionX][y + n - positionY].num) {
                            console.log('(' + x + ',' + y + ')')
                            console.log('(' + (x + m) + ',' + (y + n) + ')')
                            result.msg = '錯誤,請檢查'
                            return result
                        }
                    }
                }
            }
        }
    }
    result.code = 1
    return result
}