利用vue开发一个所谓的数独方法实例

1.前言

最近工作中遇到一个问题,因为后台管理系统页面功能暂时没有新的需求,就在想首页放什么东西,最近我想到的就是放个所谓的数独,为什么是所谓的数独,因为规则不同于标准的数独,只要求每一行每一列数字不一样就可以了!这个实例也是基于vue的,代码分享给大家。给大家代码,并不是要让大家直接拷贝代码,而是希望能让大家当做是一个练手的项目,或者学习到知识。如果大家觉得我哪里写得不好,写错了,欢迎指出,让大家交流意见,一起进步。

代码上传到github了:有需要的可以star一下!vue-demos

2.运行效果

3.实现步骤

实现步骤,感觉说得有点绕,建议大家边写边看文章,这样不会懵。或者直接去看源码(sudoku),把源码看懂!这个项目也不复杂!

3-1.准备数据和排版

排版的html+css代码我不多说了,排版很简单,这个相信都难不倒大家的。复杂一点的就是数据的交互!
下面开始第一步,把数独的数据先准备好,数据是什么,大家都知道,就是像下面这样的数据!

排版出来的效果就是下面这样。

html代码如下

<div class="num-table" @mouseleave="hoverCol=''" :class="{'shake':isShake}">
 <!--遍历每一行-->
 <div v-for="row,index in allNum" class="num-row chearfix">
 <!--遍历行里面的每一列-->
 <div v-for="num1,indexSub in row" class="num-col">
  {{allNumText[index][indexSub]}}
 </div>
 </div>
</div>

代码也很简单,如下

mounted(){
 let arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
 let row = [], rowCol = 0;
 for (let i = 0, len = arr1.length; i < len; i++) {
 row = Object.assign([], arr1);
 this.allNum.push(row);
 //删除第一个数字并记录下来
 rowCol = arr1.splice(0, 1)[0];
 //在最后面插入数字
 arr1.push(rowCol)
 }
}

大家也可以发现,这个数据,的每一行和每一列的数字都是不同样的!

3-2.打乱行

之后就是随机打乱顺序了,打乱顺序这个得保证一个前提,就是保证每一行每一列的数字都不一样。这样的话,我用了一个简单粗暴的方法-以行或者列为单位,进行打乱。比如,第一行和第三行进行位置交互,第一列和第五列进行位置的交换。下面说下以行为单位的打乱顺序!

行的打乱,很简单,就是随机打乱数组而已!一行代码搞定!

this.allNum.sort((n1, n2) => Math.random() - 0.5);

3-3.打乱列

行打乱了,下面进行以列为单位的打乱,这个稍微复杂一点。

大家想下,比如第二列是第五列的值进行交换,那就是每一行的第二个格子的值和第五个格子的值进行交换,那么就需要遍历每一行!来进行交换,至于前面说的第二列和第五列的这个列数,可以用一个函数实现!

下面看代码!

//随机获取两列的索引
function randomText() {
 let rondomIndex = 0, rondomIndexAfter = 0;
 //获取第一列的索引
 rondomIndex = Math.floor(Math.random() * 9);
 function randomDo() {
 rondomIndexAfter = Math.floor(Math.random() * 9);
 //如果第一列和第二列索引一样,第二列的索引再次重新随机获取
 if (rondomIndexAfter === rondomIndex) {
  randomDo();
 }
 }
 randomDo();
 //返回两列的索引
 return [rondomIndex, rondomIndexAfter]
}
//打乱列
let randomArr = [], nowValue = 0;
//同样遍历9次
for (let i = 0; i < 9; i++) {
 randomArr = Object.assign([], randomText());
 //遍历每一行,给每一行的随机两列交换值
 for (let j = 0, len = this.allNum.length; j < len; j++) {
 //随机两列交换值
 nowValue = this.allNum[j][randomArr[0]];
 this.allNum[j][randomArr[0]] = this.allNum[j][randomArr[1]];
 this.allNum[j][randomArr[1]] = nowValue;
 }
}

3-3.随机掏空单元格

掏空单元格就是把一些格子随机设空,然后让玩数独的人。把这些单元格给填上!

需求,我现在实现的就是,每一行有把两个格子设空,这里我的做法是,把每一个格子的坐标先记录下来,然后再从记录的坐标里面随机获取坐标,用获取到的坐标,进行设空!

首先,获取所有点的坐标

//记录所有坐标
let rowText = '', arrText = []
for (let i = 0; i < 9; i++) {
 rowText = ''
 for (let j = 0; j < 9; j++) {
  rowText += i + '-' + j + ',';
 }
 arrText.push(rowText.substr(0, rowText.length - 1))
}
console.log(arrText);

看到这个坐标,大家很容易的知道,数组的一个元素,就是第一行,‘0-0'就是第一行第一个格子。数组最后一个元素,就是最后一行,‘8-8'就是最后一行,最后一个格子,其他如此类推!

下面进行随机掏空,代码也很简单!

//随机掏空
let nowItme = [], _option, nowOption = [];
for (let i = 0; i < 9; i++) {
 //抽取当前行的所有坐标
 nowItme = arrText[i].split(',');
 nowOption = [];
 //当前行的随机两个坐标掏空
 for (let j = 0; j < 2; j++) {
  //抽取当前行的随机一个坐标
  _option = Math.floor(Math.random() * nowItme.length);
  //分割坐标的x,y
  nowOption = nowItme.splice(_option,1)[0].split("-");
  this.allNum[nowOption[0]][nowOption[1]] = '';
 }
}

这样相信大家都觉得奇怪,下面进行下样式的该写,就是把设空了的格子的样式改一下!.no这个class对应的样式我在css那里写好了,大家注意下。

<!--遍历每一行-->
<div v-for="row,index in allNum" class="num-row chearfix">
 <!--遍历行里面的每一列-->
 <!--
  no:被掏空数组的样式
 -->
 <div v-for="num1,indexSub in row" :class="{'no':num1===''}" class="num-col">
  {{allNumText[index][indexSub]}}
 </div>
</div>

3-4.显示数字键盘

首先,我简单的用一个流程图说下逻辑,如下

然后关于数字键盘的位置,看下图(数字键盘的样式我不多说了,就是一个是相对定位,一个绝对定位的设置而已)

如上图,我点击的是第一行第三个格子,首先,我期待被点击的格子的样式有所改变,方便我区分,这个不难,用一个class改变样式就可以了,这个可以看下面的代码,我用一个.cur的class控制样式。还有一个就是期待数字键盘在第二行,第四个格子那里出现。这样的话,大家就知道,数字键盘的位置是怎么定位的了!数字键盘的top就是,被点击格子所在的行的索引+160(60是格子的宽高),left就是,被点击格子所在的列的索引+160(60是格子的宽高)。比如上图,第一行第三个格子,top=(0+1)*60+'px',left=(2+1)*60+'px'。

代码如下

<!--遍历每一行-->
 <div v-for="row,index in allNum" class="num-row chearfix">
  <!--遍历行里面的每一列-->
  <!--
   no:被掏空数组的样式
   cur:格子被点击时触发,被点击的格子样式
  -->
  <div v-for="num1,indexSub in row"
    :class="{'no':num1==='',
    'cur':curRow===index&&indexSub===curCol}"
    @click="showCheck(index,indexSub)" class="num-col">
   {{allNumText[index][indexSub]}}
  </div>
 </div>
<!--数字键盘-->
<div class="num-check chearfix" :style="{'top':(curRow+1)*60+'px','left':(curCol+1)*60+'px'}"
  v-show="checkShow">
 <ul>
  <li @click="inputText(1)">1</li>
  <li @click="inputText(2)">2</li>
  <li @click="inputText(3)">3</li>
  <li @click="inputText(4)">4</li>
  <li @click="inputText(5)">5</li>
  <li @click="inputText(6)">6</li>
  <li @click="inputText(7)">7</li>
  <li @click="inputText(8)">8</li>
  <li @click="inputText(9)">9</li>
 </ul>
</div>

js代码

/**
 * @description 显示数字键盘
 * @param i1
 * @param i2
 */
showCheck(i1, i2){
 //点击的格子是否是被掏空的格子
 if (this.allNum[i1][i2] !== '') {
  return
 }
 //点击的格子如果是上一次点击的格子(当前格子)
 if (i1 === this.curRow && i2 === this.curCol) {
  //隐藏数字键盘,curRow和curCol设空
  this.checkShow = false;
  this.curRow = '';
  this.curCol = '';
 }
 else {
  //隐藏数字键盘,curRow和curCol分别设置成当前的点
  this.checkShow = true;
  this.curRow = i1;
  this.curCol = i2;
 }
},

运行效果

3-5.高亮显示同行同列

这一步很简单,首先,高亮显示行,大家都知道怎么做了,就是行对应的div,设置一个:hover,然后对应设置单元格的样式而已!这个不多说!

然后,高亮显示列,复杂一点,但是也很简单,原理我想大家也知道,就是当鼠标进如格子的时候,在data里面,用一个变量储存进入的格子的列的索引,然后加上判断,如果格子的列的索引等于进入的格子的列的索引。就加上一个class,这里我用.cur-col。

代码如下

<!--遍历每一行-->
<div v-for="row,index in allNum" class="num-row clear">
 <!--遍历行里面的每一列-->
 <!--
  no:被掏空数组的样式
  cur:格子被点击时触发,被点击的格子样式
  cur-col:鼠标进入的时候触发,和被点击格子同一列的格子的样式
 -->
 <div v-for="num1,indexSub in row"
   :class="{'no':num1==='',
   'cur':curRow===index&&indexSub===curCol,
   'cur-col':hoverCol===indexSub}"
   @click="showCheck(index,indexSub)" @mouseenter="hoverCol=indexSub;" class="num-col">
  {{allNumText[index][indexSub]}}
 </div>
</div>

运行效果

3-6.填写操作和错误提示

这一步的操作函数,我直接发代码吧,看代码比我说的会清晰些,毕竟说的有点绕

<!--遍历每一行-->
<div v-for="row,index in allNum" class="num-row clear">
 <!--遍历行里面的每一列-->
 <!--
  no:被掏空数组的样式
  cur:格子被点击时触发,被点击的格子样式
  cur-col:鼠标进入的时候触发,和被点击格子同一列的格子的样式
  err:填写错误的时候触发的样式
 -->
 <div v-for="num1,indexSub in row"
   :class="{'no':num1==='',
   'cur':curRow===index&&indexSub===curCol,
   'cur-col':hoverCol===indexSub,
   'err':(optionNow.x===index&&optionNow.y===indexSub)||(optionNowInRow.x===index&&optionNowInRow.y===indexSub)||(optionNowInCol.x===index&&optionNowInCol.y===indexSub)}"
   @click="showCheck(index,indexSub)" @mouseenter="hoverCol=indexSub;" class="num-col">
  {{allNumText[index][indexSub]}}
 </div>
</div>

js代码

inputText(_text){
 //*****************************检查前的初始化
 let _row = this.curRow, _col = this.curCol;
 this.curRow = '';
 this.curCol = '';
 this.isErr = false;
 this.optionNow = {
  x: '',
  y: '',
 }
 this.optionNowInRow = {
  x: '',
  y: '',
 }
 this.optionNowInCol = {
  x: '',
  y: '',
 }
 //*****************************检查行
 //根据当前格子进行赋值
 this.allNumText[_row][_col] = _text;
 let rowCheck = Object.assign(this.allNumText[_row], []);
 this.checkShow = false;
 for (let i = 0, len = rowCheck.length; i < len; i++) {
  //如果值一样,但是坐标不一样,就是填写错误
  if (_text === rowCheck[i] && _col !== i) {
   this.isErr = true;
   this.isShake = true;
   //记录当前格子的信息
   this.optionNow = {
    x: _row,
    y: _col,
   }
   //记录和当前格子同一行,以及同一个值的格子的坐标
   this.optionNowInRow = {
    x: _row,
    y: i,
   }
  }
 }
 //*****************************检查列
 let colCheck = [];
 //首先把每一行的那一列的数值保存起来
 for (let i = 0, len = this.allNumText.length; i < len; i++) {
  colCheck.push(this.allNumText[i][_col]);
 }
 //遍历检查
 for (let i = 0, len = colCheck.length; i < len; i++) {
  //如果值一样,但是坐标不一样,就是填写错误
  if (_text === colCheck[i] && _row !== i) {
   this.isErr = true;
   this.isShake = true;
   //记录和当前格子同一列,以及同一个值的格子的坐标
   this.optionNowInCol = {
    x: i,
    y: _col,
   }
  }
 }
 //如果发现的同样的
 if (this.isErr) {
  setTimeout(() => {
   this.isShake = false;
  }, 1000)
  return;
 }
 //如果数组去重后,长度小于9,就是行没完成
 rowCheck = rowCheck.filter(item => item !== '');
 if (rowCheck.length !== 9) {
  //console.log('行没完成')
  return;
 }
 let coloCheck = [];
 //如果数组去重后,长度小于9,就是列没完成
 for (let i = 0, len = this.allNumText.length; i < len; i++) {
  coloCheck = [...new Set(this.allNumText[i])];
  coloCheck = coloCheck.filter(item => item !== '');
  if (coloCheck.length !== 9) {
   //console.log('没完成')
   return;
  }
 }
 alert('挑战成功,但是没奖品');
 this.numShow = false;
}

上面的代码逻辑,简单说下

1..err 这个class是设置红色字体所使用的,至于判断,就是在inputText这个函数里面,有optionNow和 optionNowInRow和optionNowInCol。只要格子的坐标等于三者其中之一,就会添加这个class,就会变红。

2..isShake这个class是控制,抖动的动画,添加上了之后,在一秒后,要去掉这个class,不然下次添加没有动画效果。

3.在inputText这个函数里面,我操作的数独列表,并不是之前,提到的allNum,而是利用allNum,深度拷贝生成出的allNumText(this.allNumText = JSON.parse(JSON.stringify(this.allNum));) 。主要就是为了避免下图的情况!

这样是为了往掏空的格子输入数字的时候,然后那个格子就不能再改了,即使是填错了,都不能改。样式控制也不正确!正确的格式应该是下面这样,即使填入了,格子的样式还是灰色的,这样可以方便的知道哪个格子是当时被掏空的,填写错了,也是可以改的。

4.完整代码

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>vue-所谓的数独</title>
 <link rel="stylesheet" href="../../reset.css" rel="external nofollow" >
 <style>
  li{
   list-style-type: none;
  }
  .shake {
   animation: shake-opacity 500ms 1 ease-in-out;
  }
  @keyframes shake-opacity {
   0% {
    transform: translate(0px, 0px) rotate(0deg);
    opacity: 0.6;
   }
   10% {
    transform: translate(-2px, -1px) rotate(-0.5deg);
    opacity: 0.5;
   }
   20% {
    transform: translate(-4px, 4px) rotate(1.5deg);
    opacity: 0.4;
   }
   30% {
    transform: translate(-4px, -1px) rotate(-1.5deg);
    opacity: 0.8;
   }
   40% {
    transform: translate(-2px, -1px) rotate(-2.5deg);
    opacity: 0.3;
   }
   50% {
    transform: translate(-4px, 1px) rotate(-2.5deg);
    opacity: 0.5;
   }
   60% {
    transform: translate(-2px, 4px) rotate(0.5deg);
    opacity: 0.1;
   }
   70% {
    transform: translate(-3px, 1px) rotate(-0.5deg);
    opacity: 0.4;
   }
   80% {
    transform: translate(0px, 0px) rotate(-0.5deg);
    opacity: 0.5;
   }
   90% {
    transform: translate(2px, -1px) rotate(-2.5deg);
    opacity: 0.8;
   }
  }
  .num-box {
   margin: 0 auto;
   width: 540px;
   position: relative;
  }
  .num-box .num-check {
   position: absolute;
   width: 180px;
   box-shadow: 0 0 10px 0 #000;
   left: 0;
   top: 0;
  }
  .num-box .num-check li {
   box-sizing: border-box;
   float: left;
   background: #fff;
   color: #58B7FF;
   width: 60px;
   height: 60px;
   text-align: center;
   line-height: 60px;
   font-size: 24px;
   border: 1px solid #58B7FF;
   cursor: pointer;
   transition: all .5s;
  }
  .num-box .num-check li:hover {
   color: #fff;
   background: #58B7FF;
   border: 1px solid #fff;
  }
  .num-tips{
   color: #333;
   line-height: 32px;
   font-size: 16px;
  }
  .num-table{
   position: relative;
  }
  .num-row {
   font-size: 0;
  }
  .num-row:hover .num-col, .num-row:hover .num-col.no, .num-row:hover .num-col.cur-col {
   background: #0068b7;
  }
  .num-row .num-col {
   width: 60px;
   height: 60px;
   line-height: 60px;
   float: left;
   box-sizing: border-box;
   text-align: center;
   background: #58B7FF;
   color: #fff;
   font-size: 24px;
   font-weight: bold;
   border: 1px solid #ccc;
  }
  .num-row .num-col.no {
   background: #ccc;
   border: 1px solid #fff;
  }
  .num-row .num-col.err {
   color: #ff4949;
  }
  .num-row .num-col.cur-col {
   background: #0068b7;
  }
  .num-row .num-col.cur {
   background: #fff !important;
  }
 </style>
</head>
<body>
<div class="num-box" v-show="numShow" id="num">
 <div class="num-tips">
  <p>所谓的数独:规则</p>
  <p>1.每一行数字不重复</p>
  <p>2.每一列数字不重复</p>
 </div>
 <div class="num-table" @mouseleave="hoverCol=''" :class="{'shake':isShake}">
  <!--遍历每一行-->
  <div v-for="row,index in allNum" class="num-row clear">
   <!--遍历行里面的每一列-->
   <!--
    no:被掏空数组的样式
    cur:格子被点击时触发,被点击的格子样式
    cur-col:鼠标进入的时候触发,和被点击格子同一列的格子的样式
    err:填写错误的时候触发的样式
   -->
   <div v-for="num1,indexSub in row"
     :class="{'no':num1==='',
     'cur':curRow===index&&indexSub===curCol,
     'cur-col':hoverCol===indexSub,
     'err':(optionNow.x===index&&optionNow.y===indexSub)||(optionNowInRow.x===index&&optionNowInRow.y===indexSub)||(optionNowInCol.x===index&&optionNowInCol.y===indexSub)}"
     @click="showCheck(index,indexSub)" @mouseenter="hoverCol=indexSub;" class="num-col">
    {{allNumText[index][indexSub]}}
   </div>
  </div>
  <!--数字键盘-->
  <div class="num-check clear" :style="{'top':(curRow+1)*60+'px','left':(curCol+1)*60+'px'}"
    v-show="checkShow">
   <ul>
    <li @click="inputText(1)">1</li>
    <li @click="inputText(2)">2</li>
    <li @click="inputText(3)">3</li>
    <li @click="inputText(4)">4</li>
    <li @click="inputText(5)">5</li>
    <li @click="inputText(6)">6</li>
    <li @click="inputText(7)">7</li>
    <li @click="inputText(8)">8</li>
    <li @click="inputText(9)">9</li>
   </ul>
  </div>
 </div>
</div>
</body>
<script src="../vue.min.js"></script>
<script>
 new Vue({
  el:'#num',
  data:{
    name: 'welcome',
    testText: '欢迎来到',
    nowIndex: 0,
    allNum: [],//数字排列
    answer: [],//所有答案的坐标点
    allNumText: [],//数字,包括输入后的数字
    curRow: '',//当前格子所在的行的索引
    curCol: '',//当前格子所在的列的索引
    checkShow: false,//数字键盘的显示
    hoverCol: '',//鼠标进去的当前列
    hoverRow: 0,//鼠标进入的当前行
    numShow: true,//数独的显示
    optionNow: {},//输入后的格子的坐标
    optionNowInRow: {},//和输入后的格子在同一行,并且同样值的格子的坐标
    optionNowInCol: {},//和输入后的格子在同一列,并且同样值的格子的坐标
    isErr: false,//是否输入错误后
    isShake: false//是否显示震动的样式
  },
  methods: {
   /**
    * @description 显示数字键盘
    * @param i1
    * @param i2
    */
   showCheck(i1, i2){
    //点击的格子是否是被掏空的格子
    if (this.allNum[i1][i2] !== '') {
     return
    }
    //点击的格子如果是上一次点击的格子(当前格子)
    if (i1 === this.curRow && i2 === this.curCol) {
     //隐藏数字键盘,curRow和curCol设空
     this.checkShow = false;
     this.curRow = '';
     this.curCol = '';
    }
    else {
     //隐藏数字键盘,curRow和curCol分别设置成当前的点
     this.checkShow = true;
     this.curRow = i1;
     this.curCol = i2;
    }
   },
   inputText(_text){
    //*****************************检查前的初始化
    let _row = this.curRow, _col = this.curCol;
    this.curRow = '';
    this.curCol = '';
    this.isErr = false;
    this.optionNow = {
     x: '',
     y: '',
    }
    this.optionNowInRow = {
     x: '',
     y: '',
    }
    this.optionNowInCol = {
     x: '',
     y: '',
    }
    //*****************************检查行
    //保存当前格子的值
    this.allNumText[_row][_col] = _text;
    let rowCheck = Object.assign(this.allNumText[_row], []);
    this.checkShow = false;
    for (let i = 0, len = rowCheck.length; i < len; i++) {
     //如果值一样,但是坐标不一样,就是填写错误
     if (_text === rowCheck[i] && _col !== i) {
      this.isErr = true;
      this.isShake = true;
      //记录当前格子的信息
      this.optionNow = {
       x: _row,
       y: _col
      }
      //记录和当前格子同一行,以及同一个值的格子的坐标
      this.optionNowInRow = {
       x: _row,
       y: i
      }
     }
    }
    //*****************************检查列
    let colCheck = [];
    //首先把每一行的那一列的数值保存起来
    for (let i = 0, len = this.allNumText.length; i < len; i++) {
     colCheck.push(this.allNumText[i][_col]);
    }
    //遍历检查
    for (let i = 0, len = colCheck.length; i < len; i++) {
     //如果值一样,但是坐标不一样,就是填写错误
     if (_text === colCheck[i] && _row !== i) {
      this.isErr = true;
      this.isShake = true;
      //记录和当前格子同一列,以及同一个值的格子的坐标
      this.optionNowInCol = {
       x: i,
       y: _col
      }
     }
    }
    //如果发现的同样的
    if (this.isErr) {
     setTimeout(() => {
      this.isShake = false;
     }, 1000)
     return;
    }
    //如果数组去重后,长度小于9,就是行没完成
    rowCheck = rowCheck.filter(item => item !== '');
    if (rowCheck.length !== 9) {
     console.log('行没完成')
     return;
    }
    let coloCheck = [];
    //如果数组去重后,长度小于9,就是列没完成
    for (let i = 0, len = this.allNumText.length; i < len; i++) {
     coloCheck = [...new Set(this.allNumText[i])];
     coloCheck = coloCheck.filter(item => item !== '');
     if (coloCheck.length !== 9) {
      console.log('没完成')
      return;
     }
    }
    alert('挑战成功,但是没奖品');
    this.numShow = false;
   }
  },
  mounted(){
   let arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
   let row = [], rowCol = 0;
   for (let i = 0, len = arr1.length; i < len; i++) {
    row = Object.assign([], arr1);
    this.allNum.push(row);
    rowCol = arr1.splice(0, 1)[0];
    arr1.push(rowCol)
   }
   //打乱行
   this.allNum.sort((n1, n2) => Math.random() - 0.5);
   //随机获取两列的索引
   function randomText() {
    let rondomIndex = 0, rondomIndexAfter = 0;
    //获取第一列的索引
    rondomIndex = Math.floor(Math.random() * 9);
    function randomDo() {
     rondomIndexAfter = Math.floor(Math.random() * 9);
     //如果第一列和第二列索引一样,第二列的索引再次重新获取
     if (rondomIndexAfter === rondomIndex) {
      randomDo();
     }
    }
    randomDo();
    //返回两列的索引
    return [rondomIndex, rondomIndexAfter]
   }
   //打乱列
   let randomArr = [], nowValue = 0;
   //同样遍历9次
   for (let i = 0; i < 9; i++) {
    randomArr = Object.assign([], randomText());
    //遍历每一行,给每一行的随机两列交换值
    for (let j = 0, len = this.allNum.length; j < len; j++) {
     //随机两列交换值
     nowValue = this.allNum[j][randomArr[0]];
     this.allNum[j][randomArr[0]] = this.allNum[j][randomArr[1]];
     this.allNum[j][randomArr[1]] = nowValue;
    }
   }
   //记录所有坐标
   let rowText = '', arrText = []
   for (let i = 0; i < 9; i++) {
    rowText = ''
    for (let j = 0; j < 9; j++) {
     rowText += i + '-' + j + ',';
    }
    arrText.push(rowText.substr(0, rowText.length - 1))
   }
   console.log(arrText);
   //随机掏空
   let nowItme = [], _option, nowOption = [];
   for (let i = 0; i < 9; i++) {
    //抽取当前行的所有坐标
    nowItme = arrText[i].split(',');
    nowOption = [];
    //当前行的随机两个坐标掏空
    for (let j = 0; j < 2; j++) {
     //抽取当前行的随机一个坐标
     _option = Math.floor(Math.random() * nowItme.length);
     //分割坐标的x,y
     nowOption = nowItme.splice(_option,1)[0].split("-");
     this.allNum[nowOption[0]][nowOption[1]] = '';
    }
   }
   //深度拷贝数独的数字
   this.allNumText = JSON.parse(JSON.stringify(this.allNum));
  }
 })
</script>
</html>

reset.css和vue.min.js大家自行到github下载!

5.小结

好了,用vue做的所谓的数独,就写到这里了,主要就是逻辑有点绕,其它的问题相信都难不倒大家。这个实例比之前快速入门的三个小实例要麻烦一点,但是也很好理解!大家只要稍微看下估计都不难理解!最后,如果大家觉得文章写得不好,哪里写错了,欢迎给建议或者指点下迷津。期待和大家交流意见,共同进步!

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • 利用vue开发一个所谓的数独方法实例

    1.前言 最近工作中遇到一个问题,因为后台管理系统页面功能暂时没有新的需求,就在想首页放什么东西,最近我想到的就是放个所谓的数独,为什么是所谓的数独,因为规则不同于标准的数独,只要求每一行每一列数字不一样就可以了!这个实例也是基于vue的,代码分享给大家.给大家代码,并不是要让大家直接拷贝代码,而是希望能让大家当做是一个练手的项目,或者学习到知识.如果大家觉得我哪里写得不好,写错了,欢迎指出,让大家交流意见,一起进步. 代码上传到github了:有需要的可以star一下!vue-demos 2.

  • 使用Vue开发一个实时性时间转换指令

    前言 最近有一个说法,如果你看见某个网站的某个功能,你就大概能猜出背后的业务逻辑是怎么样的,以及你能动手开发一个一毛一样的功能,那么你的前端技能算是进阶中高级水平了.比如咱们今天要聊的这个话题:如何用Vue开发一个实时性的时间转换指令? 接下来正文从这开始~ 如上图所示(我是截取的某技术社区首页的部分页面),大家看到用红色边框勾选中的时间文字了吧.很多网站发布动态的时候,都会有一个相对本机时间转换后的相对时间.那你知道这个功能实现的背后原理是什么吗?如果有兴趣的,请备好瓜子,茶水,继续往下读.

  • Go+Vue开发一个线上外卖应用的流程(用户名密码和图形验证码)

    图形化验证码生成和验证 功能介绍 在使用用户名和密码登录功能时,需要填写验证码,验证码是以图形化的方式进行获取和展示的. 验证码使用原理 验证码的使用流程和原理为:在服务器端负责生成图形化验证码,并以数据流的形式供前端访问获取,同时将生成的验证码存储到全局的缓存中,在本案例中,我们使用redis作为全局缓存,并设置缓存失效时间.当用户使用用户名和密码进行登录时,进行验证码验证.验证通过即可继续进行登录. 验证码库安装 借助开源的验证码工具库可以生成验证码. 首先,安装开源的验证码生成库: go

  • 利用 Python 开发一个 Python 解释器

    目录 1.标记(Token) 2.词法分析器(Lexer) 3.巴科斯-诺尔范式(Backus-Naur Form,BNF) 4.解析器(Parser) 前言: 计算机只能理解机器码.归根结底,编程语言只是一串文字,目的是为了让人类更容易编写他们想让计算机做的事情.真正的魔法是由编译器和解释器完成,它们弥合了两者之间的差距.解释器逐行读取代码并将其转换为机器码. 在本文中,我们将设计一个可以执行算术运算的解释器. 我们不会重新造轮子.文章将使用由 David M. Beazley 开发的词法解析

  • VUE开发一个图片轮播的组件示例代码

    本人刚学习vue,用vue做了个图片轮播,下面我来记录一下,有需要了解VUE开发一个图片轮播的组件的朋友可参考.希望此文章对各位有所帮助. 完成效果图如下: vue开发的思路主要是数据绑定,代码如下: <template> <div ref="root" style="user-select: none;-webkit-user-select: none;overflow: hidden"> <div class="slide

  • 利用express启动一个server服务的方法

    安装express $ npm install express --save 在node.js中,我们最常用的框架就是express Express 是一个基于 Node.js 平台的极简.灵活的 web 应用开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用. 第一步 我们要引用这个框架 let express=require('express'); 第二步 我们把这个框架挂载在一个变量上面,使我们后面调用express内置方法方便 let app=express() 第

  • 使用 Vue 实现一个虚拟列表的方法

    因为 DOM 性能瓶颈,大型列表存在难以克服的性能问题. 因此,就有了 "局部渲染" 的优化方案,这就是虚拟列表的核心思想. 虚拟列表的实现,需要重点关注的问题一有以下几点: 可视区域的计算方法 可视区域的 DOM 更新方案 事件的处理方案 下面逐一分解说明. 可视区域计算 可视区域的计算,就是使用当前视口的高度.当前滚动条滚过的距离,得到一个可视区域的坐标区间. 算出可视区域的坐标区间之后,在去过滤出落在该区间内的列表项,这个过程,列表项的坐标也是必须能算出的. 思考以下情况, 我们

  • Python利用heapq实现一个优先级队列的方法

    实现一个优先级队列,每次pop的元素要是优先级高的元素,由于heapq.heapify(list)默认构建一个小顶堆,因此要将priority变为相反数再push,代码如下: import heapq class PriorityQueue(object): """实现一个优先级队列,每次pop优先级最高的元素""" def __init__(self): self._queue = [] self._index = 0 def push(sel

  • Vue中遍历数组的新方法实例详解

    1.foreach foreach循环对不能使用return来停止循环 search(keyword){ var newList = [] this.urls.forEach(item =>{ if(item.name.indexOf(keyword) != -1){ newList.push(item) } }) return newList } 2.filter item对象就是遍历数组中的一个元素,includes是es6中的新方法,在search方法中直接返回新数组 search(key

  • Vue中使用webpack别名的方法实例详解

    在工作中,我们经常会写出这种代码: import MHeader from '../../components/m-header/m-header' @import "../../common/stylus/variable" @import "../../common/stylus/mixin" 即,需要引入公共文件,但是公共文件的文件路径里当前文件很远,那么就会形成上面示例中的那种路径很长的情况. 而因为文件目录是约定俗成的,不可轻易更改,无法修改相对路径.那么

随机推荐