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
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值