使用es6制作简单数独游戏

最近心血来潮想制作一个数独游戏,说干咱就干。刚刚好前一阶段学习了es6,可以用这个项目来当做一个小练习。

    目前开发已经完成,由于只是基本功能,页面样式并不是很华丽,下面我们先开看看长什么样子。

alt

大概页面就长这个样子,页面有三个按钮,分别是检查,重玩,换题。

  1. 检查就是检查当你填满是否成功。
  2. 重玩就是放弃你所填的,重新开始本局游戏。
  3. 换题就是重新换个题目。

下面是游戏中截图。

alt;

alt;

最后这个图我比较偷懒。直接生成的,并没有自己填。

下面就来看看代码吧。

里面最重要的就数算法了吧。我使用是回溯法,废话不多说直接上代码。先来看一下生成数独的算法。大概就是把数独分成81格,从1-81分别生成,没生成一个格都要去判断一下每一行,每一列,每一宫是否满足规则。如果不满足则回溯。下面是生成数独的方法。

//生成数独
const makeArray=(arr, n)=>{

        if(n == 81) {
            return arr;
        }

        let x = Math.floor(n / 9);
        let y = n % 9;

        if(arr[x][y] == 0) {

            let index = 0;

            let arrn = makeRandomArray(9);
            for(let i = 0; i < arrn.length; i++) {

                arr[x][y] = arrn[i];
                if(checkArrayByIndex(arr, x, y)) {
                    let endArr = makeArray(arr, n + 1);
                    if(!checkArrayHasZero(arr)) return endArr;
                }

            }

            arr[x][y] = 0; //回溯

        } else {
            makeArray(arr, n + 1);
        }

        return arr;
    }

当生成完数组之后,就可以生成游戏所用的数独,其实则是隐藏其中的格子。

//对二维数组进行随机n位置0
const resetZeroByArray=(arr,n)=>{

    let k=0;

    while(k<n){

        let ranNum=randomNumber(81);

        let x = Math.floor((ranNum-1) / 9);

        let y = ranNum % 9;

        if(arr[x][y]!=0){
            arr[x][y]=0;
            k++;
        }    
    }

    return arr;

}

最后则是当玩家填完数组之后再去验证这个数独是否满足规则。

//判断二维数组是否是完整数独
    checkSudoArray(arr){                

        let sign=true;

        //检查数组中是否含有0,如果有0立刻返回false
        if(checkArrayHasZero(arr))return false;

        //对每一行每一列每一宫进行检查
        for(let i=0;i<9;i++){

            let rowSign=checkedRow(arr,i);
            let colSign=checkedCol(arr,i);
            let gongSign=checkedGongByNum(arr,i+1);
            if(!(rowSign&&colSign&&gongSign)){
                sign=false;
            };

        }

        return sign;

    }


//根据坐标检查九宫格
const checkArrayByIndex = (arr, x, y) => {

    let signRow = false;

    let signCol = false;

    let signGong = false;

    //检查行                                
    signRow = checkedRow(arr, x);

    //检查列
    signCol = checkedCol(arr, y);

    //检查宫
    signGong = checkedGongByIndex(arr, x, y);

    if(signRow && signCol && signGong) {
        return true;
    } else {
        return false;
    }

}

这样算法大概就介绍完了。接下来来看看页面。页面我是把二维数组直接放在父模板中,然后先去初始化然后根据这个数组去生成grid。

<div class="sudoMain" >
              <Row class="numRow" type="flex" v-for="(row,i) in arr" justify="center">            
                <i-col class="numCol" v-for="(cell,j) in row" :data-x='i'  :data-y='j'><div class="spanDiv" @click="cellClick($event,i,j)">{{arr[i][j]==0?"":arr[i][j]}}</div></i-col>           
            </Row>    
</div>

一定要记得把每个坐标赋值到元素上,这样可以进行接下来的操作都很方便。接来下用户选择的数字面板单独写出来,通过点击事件进行隐藏或者显示。

selectClick(e,i,j){
            this.showSelectPop=false;
            this.arr[this.selectX][this.selectY]=(i-1)*3+j;                    
        }

介绍的大体差不多了,代码已经上传到github,如果想看源码的话可以直接上github下载。地址是:https://github.com/like2372/sudoVue.git

原文地址:https://www.cnblogs.com/like2372/p/8329835.html