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

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>
      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/149.html