溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

利用vue開發(fā)一個所謂的數(shù)獨方法實例

發(fā)布時間:2020-08-23 20:42:13 來源:腳本之家 閱讀:316 作者:守候 欄目:web開發(fā)

1.前言

最近工作中遇到一個問題,因為后臺管理系統(tǒng)頁面功能暫時沒有新的需求,就在想首頁放什么東西,最近我想到的就是放個所謂的數(shù)獨,為什么是所謂的數(shù)獨,因為規(guī)則不同于標準的數(shù)獨,只要求每一行每一列數(shù)字不一樣就可以了!這個實例也是基于vue的,代碼分享給大家。給大家代碼,并不是要讓大家直接拷貝代碼,而是希望能讓大家當做是一個練手的項目,或者學習到知識。如果大家覺得我哪里寫得不好,寫錯了,歡迎指出,讓大家交流意見,一起進步。

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

2.運行效果

利用vue開發(fā)一個所謂的數(shù)獨方法實例

3.實現(xiàn)步驟

實現(xiàn)步驟,感覺說得有點繞,建議大家邊寫邊看文章,這樣不會懵?;蛘咧苯尤タ丛创a(sudoku),把源碼看懂!這個項目也不復雜!

3-1.準備數(shù)據(jù)和排版

排版的html+css代碼我不多說了,排版很簡單,這個相信都難不倒大家的。復雜一點的就是數(shù)據(jù)的交互!
下面開始第一步,把數(shù)獨的數(shù)據(jù)先準備好,數(shù)據(jù)是什么,大家都知道,就是像下面這樣的數(shù)據(jù)!

利用vue開發(fā)一個所謂的數(shù)獨方法實例

排版出來的效果就是下面這樣。

利用vue開發(fā)一個所謂的數(shù)獨方法實例

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);
 //刪除第一個數(shù)字并記錄下來
 rowCol = arr1.splice(0, 1)[0];
 //在最后面插入數(shù)字
 arr1.push(rowCol)
 }
}

大家也可以發(fā)現(xiàn),這個數(shù)據(jù),的每一行和每一列的數(shù)字都是不同樣的!

3-2.打亂行

之后就是隨機打亂順序了,打亂順序這個得保證一個前提,就是保證每一行每一列的數(shù)字都不一樣。這樣的話,我用了一個簡單粗暴的方法-以行或者列為單位,進行打亂。比如,第一行和第三行進行位置交互,第一列和第五列進行位置的交換。下面說下以行為單位的打亂順序!

行的打亂,很簡單,就是隨機打亂數(shù)組而已!一行代碼搞定!

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

利用vue開發(fā)一個所謂的數(shù)獨方法實例

3-3.打亂列

行打亂了,下面進行以列為單位的打亂,這個稍微復雜一點。

大家想下,比如第二列是第五列的值進行交換,那就是每一行的第二個格子的值和第五個格子的值進行交換,那么就需要遍歷每一行!來進行交換,至于前面說的第二列和第五列的這個列數(shù),可以用一個函數(shù)實現(xiàn)!

下面看代碼!

//隨機獲取兩列的索引
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;
 }
}

利用vue開發(fā)一個所謂的數(shù)獨方法實例

3-3.隨機掏空單元格

掏空單元格就是把一些格子隨機設(shè)空,然后讓玩數(shù)獨的人。把這些單元格給填上!

需求,我現(xiàn)在實現(xiàn)的就是,每一行有把兩個格子設(shè)空,這里我的做法是,把每一個格子的坐標先記錄下來,然后再從記錄的坐標里面隨機獲取坐標,用獲取到的坐標,進行設(shè)空!

首先,獲取所有點的坐標

//記錄所有坐標
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);

利用vue開發(fā)一個所謂的數(shù)獨方法實例

看到這個坐標,大家很容易的知道,數(shù)組的一個元素,就是第一行,‘0-0'就是第一行第一個格子。數(shù)組最后一個元素,就是最后一行,‘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]] = '';
 }
}

利用vue開發(fā)一個所謂的數(shù)獨方法實例

這樣相信大家都覺得奇怪,下面進行下樣式的該寫,就是把設(shè)空了的格子的樣式改一下!.no這個class對應(yīng)的樣式我在css那里寫好了,大家注意下。

<!--遍歷每一行-->
<div v-for="row,index in allNum" class="num-row chearfix">
 <!--遍歷行里面的每一列-->
 <!--
  no:被掏空數(shù)組的樣式
 -->
 <div v-for="num1,indexSub in row" :class="{'no':num1===''}" class="num-col">
  {{allNumText[index][indexSub]}}
 </div>
</div>

利用vue開發(fā)一個所謂的數(shù)獨方法實例

3-4.顯示數(shù)字鍵盤

首先,我簡單的用一個流程圖說下邏輯,如下

利用vue開發(fā)一個所謂的數(shù)獨方法實例

然后關(guān)于數(shù)字鍵盤的位置,看下圖(數(shù)字鍵盤的樣式我不多說了,就是一個是相對定位,一個絕對定位的設(shè)置而已)

利用vue開發(fā)一個所謂的數(shù)獨方法實例

如上圖,我點擊的是第一行第三個格子,首先,我期待被點擊的格子的樣式有所改變,方便我區(qū)分,這個不難,用一個class改變樣式就可以了,這個可以看下面的代碼,我用一個.cur的class控制樣式。還有一個就是期待數(shù)字鍵盤在第二行,第四個格子那里出現(xiàn)。這樣的話,大家就知道,數(shù)字鍵盤的位置是怎么定位的了!數(shù)字鍵盤的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:被掏空數(shù)組的樣式
   cur:格子被點擊時觸發(fā),被點擊的格子樣式
  -->
  <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>
<!--數(shù)字鍵盤-->
<div class="num-check chearfix" :
  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 顯示數(shù)字鍵盤
 * @param i1
 * @param i2
 */
showCheck(i1, i2){
 //點擊的格子是否是被掏空的格子
 if (this.allNum[i1][i2] !== '') {
  return
 }
 //點擊的格子如果是上一次點擊的格子(當前格子)
 if (i1 === this.curRow && i2 === this.curCol) {
  //隱藏數(shù)字鍵盤,curRow和curCol設(shè)空
  this.checkShow = false;
  this.curRow = '';
  this.curCol = '';
 }
 else {
  //隱藏數(shù)字鍵盤,curRow和curCol分別設(shè)置成當前的點
  this.checkShow = true;
  this.curRow = i1;
  this.curCol = i2;
 }
},

運行效果

利用vue開發(fā)一個所謂的數(shù)獨方法實例

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

這一步很簡單,首先,高亮顯示行,大家都知道怎么做了,就是行對應(yīng)的div,設(shè)置一個:hover,然后對應(yīng)設(shè)置單元格的樣式而已!這個不多說!

利用vue開發(fā)一個所謂的數(shù)獨方法實例

然后,高亮顯示列,復雜一點,但是也很簡單,原理我想大家也知道,就是當鼠標進如格子的時候,在data里面,用一個變量儲存進入的格子的列的索引,然后加上判斷,如果格子的列的索引等于進入的格子的列的索引。就加上一個class,這里我用.cur-col。

代碼如下

<!--遍歷每一行-->
<div v-for="row,index in allNum" class="num-row clear">
 <!--遍歷行里面的每一列-->
 <!--
  no:被掏空數(shù)組的樣式
  cur:格子被點擊時觸發(fā),被點擊的格子樣式
  cur-col:鼠標進入的時候觸發(fā),和被點擊格子同一列的格子的樣式
 -->
 <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>

運行效果

利用vue開發(fā)一個所謂的數(shù)獨方法實例

3-6.填寫操作和錯誤提示

這一步的操作函數(shù),我直接發(fā)代碼吧,看代碼比我說的會清晰些,畢竟說的有點繞

<!--遍歷每一行-->
<div v-for="row,index in allNum" class="num-row clear">
 <!--遍歷行里面的每一列-->
 <!--
  no:被掏空數(shù)組的樣式
  cur:格子被點擊時觸發(fā),被點擊的格子樣式
  cur-col:鼠標進入的時候觸發(fā),和被點擊格子同一列的格子的樣式
  err:填寫錯誤的時候觸發(fā)的樣式
 -->
 <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: '',
 }
 //*****************************檢查行
 //根據(jù)當前格子進行賦值
 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 = [];
 //首先把每一行的那一列的數(shù)值保存起來
 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,
   }
  }
 }
 //如果發(fā)現(xiàn)的同樣的
 if (this.isErr) {
  setTimeout(() => {
   this.isShake = false;
  }, 1000)
  return;
 }
 //如果數(shù)組去重后,長度小于9,就是行沒完成
 rowCheck = rowCheck.filter(item => item !== '');
 if (rowCheck.length !== 9) {
  //console.log('行沒完成')
  return;
 }
 let coloCheck = [];
 //如果數(shù)組去重后,長度小于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('挑戰(zhàn)成功,但是沒獎品');
 this.numShow = false;
}

利用vue開發(fā)一個所謂的數(shù)獨方法實例

上面的代碼邏輯,簡單說下

1..err 這個class是設(shè)置紅色字體所使用的,至于判斷,就是在inputText這個函數(shù)里面,有optionNow和 optionNowInRow和optionNowInCol。只要格子的坐標等于三者其中之一,就會添加這個class,就會變紅。

2..isShake這個class是控制,抖動的動畫,添加上了之后,在一秒后,要去掉這個class,不然下次添加沒有動畫效果。

3.在inputText這個函數(shù)里面,我操作的數(shù)獨列表,并不是之前,提到的allNum,而是利用allNum,深度拷貝生成出的allNumText(this.allNumText = JSON.parse(JSON.stringify(this.allNum));) 。主要就是為了避免下圖的情況!

利用vue開發(fā)一個所謂的數(shù)獨方法實例

這樣是為了往掏空的格子輸入數(shù)字的時候,然后那個格子就不能再改了,即使是填錯了,都不能改。樣式控制也不正確!正確的格式應(yīng)該是下面這樣,即使填入了,格子的樣式還是灰色的,這樣可以方便的知道哪個格子是當時被掏空的,填寫錯了,也是可以改的。

4.完整代碼

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>vue-所謂的數(shù)獨</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>所謂的數(shù)獨:規(guī)則</p>
  <p>1.每一行數(shù)字不重復</p>
  <p>2.每一列數(shù)字不重復</p>
 </div>
 <div class="num-table" @mouseleave="hoverCol=''" :class="{'shake':isShake}">
  <!--遍歷每一行-->
  <div v-for="row,index in allNum" class="num-row clear">
   <!--遍歷行里面的每一列-->
   <!--
    no:被掏空數(shù)組的樣式
    cur:格子被點擊時觸發(fā),被點擊的格子樣式
    cur-col:鼠標進入的時候觸發(fā),和被點擊格子同一列的格子的樣式
    err:填寫錯誤的時候觸發(fā)的樣式
   -->
   <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>
  <!--數(shù)字鍵盤-->
  <div class="num-check clear" :
    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: [],//數(shù)字排列
    answer: [],//所有答案的坐標點
    allNumText: [],//數(shù)字,包括輸入后的數(shù)字
    curRow: '',//當前格子所在的行的索引
    curCol: '',//當前格子所在的列的索引
    checkShow: false,//數(shù)字鍵盤的顯示
    hoverCol: '',//鼠標進去的當前列
    hoverRow: 0,//鼠標進入的當前行
    numShow: true,//數(shù)獨的顯示
    optionNow: {},//輸入后的格子的坐標
    optionNowInRow: {},//和輸入后的格子在同一行,并且同樣值的格子的坐標
    optionNowInCol: {},//和輸入后的格子在同一列,并且同樣值的格子的坐標
    isErr: false,//是否輸入錯誤后
    isShake: false//是否顯示震動的樣式
  },
  methods: {
   /**
    * @description 顯示數(shù)字鍵盤
    * @param i1
    * @param i2
    */
   showCheck(i1, i2){
    //點擊的格子是否是被掏空的格子
    if (this.allNum[i1][i2] !== '') {
     return
    }
    //點擊的格子如果是上一次點擊的格子(當前格子)
    if (i1 === this.curRow && i2 === this.curCol) {
     //隱藏數(shù)字鍵盤,curRow和curCol設(shè)空
     this.checkShow = false;
     this.curRow = '';
     this.curCol = '';
    }
    else {
     //隱藏數(shù)字鍵盤,curRow和curCol分別設(shè)置成當前的點
     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 = [];
    //首先把每一行的那一列的數(shù)值保存起來
    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
      }
     }
    }
    //如果發(fā)現(xiàn)的同樣的
    if (this.isErr) {
     setTimeout(() => {
      this.isShake = false;
     }, 1000)
     return;
    }
    //如果數(shù)組去重后,長度小于9,就是行沒完成
    rowCheck = rowCheck.filter(item => item !== '');
    if (rowCheck.length !== 9) {
     console.log('行沒完成')
     return;
    }
    let coloCheck = [];
    //如果數(shù)組去重后,長度小于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('挑戰(zhàn)成功,但是沒獎品');
    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]] = '';
    }
   }
   //深度拷貝數(shù)獨的數(shù)字
   this.allNumText = JSON.parse(JSON.stringify(this.allNum));
  }
 })
</script>
</html>

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

5.小結(jié)

好了,用vue做的所謂的數(shù)獨,就寫到這里了,主要就是邏輯有點繞,其它的問題相信都難不倒大家。這個實例比之前快速入門的三個小實例要麻煩一點,但是也很好理解!大家只要稍微看下估計都不難理解!最后,如果大家覺得文章寫得不好,哪里寫錯了,歡迎給建議或者指點下迷津。期待和大家交流意見,共同進步!

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI