最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

使用vue如何開發(fā)數(shù)獨游戲

來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 19:36:29
文檔

使用vue如何開發(fā)數(shù)獨游戲

使用vue如何開發(fā)數(shù)獨游戲:數(shù)獨是源自18世紀(jì)瑞士的一種數(shù)學(xué)游戲,是一種運用紙、筆進(jìn)行演算的邏輯游戲。下面這篇文章主要給大家介紹了關(guān)于利用vue開發(fā)一個所謂的數(shù)獨的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。1.前言最近工作中遇到一個問題,因為后臺管理系
推薦度:
導(dǎo)讀使用vue如何開發(fā)數(shù)獨游戲:數(shù)獨是源自18世紀(jì)瑞士的一種數(shù)學(xué)游戲,是一種運用紙、筆進(jìn)行演算的邏輯游戲。下面這篇文章主要給大家介紹了關(guān)于利用vue開發(fā)一個所謂的數(shù)獨的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。1.前言最近工作中遇到一個問題,因為后臺管理系
數(shù)獨是源自18世紀(jì)瑞士的一種數(shù)學(xué)游戲,是一種運用紙、筆進(jìn)行演算的邏輯游戲。下面這篇文章主要給大家介紹了關(guān)于利用vue開發(fā)一個所謂的數(shù)獨的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。

1.前言

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

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

2.運行效果

3.實現(xiàn)步驟

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

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

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

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

html代碼如下

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

代碼也很簡單,如下

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ù)字都不一樣。這樣的話,我用了一個簡單粗暴的方法-以行或者列為單位,進(jìn)行打亂。比如,第一行和第三行進(jìn)行位置交互,第一列和第五列進(jìn)行位置的交換。下面說下以行為單位的打亂順序!

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

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

3-3.打亂列

行打亂了,下面進(jìn)行以列為單位的打亂,這個稍微復(fù)雜一點。

大家想下,比如第二列是第五列的值進(jìn)行交換,那就是每一行的第二個格子的值和第五個格子的值進(jìn)行交換,那么就需要遍歷每一行!來進(jìn)行交換,至于前面說的第二列和第五列的這個列數(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;
 }
}

3-3.隨機掏空單元格

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

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

首先,獲取所有點的坐標(biāo)

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

看到這個坐標(biāo),大家很容易的知道,數(shù)組的一個元素,就是第一行,‘0-0'就是第一行第一個格子。數(shù)組最后一個元素,就是最后一行,‘8-8'就是最后一行,最后一個格子,其他如此類推!

下面進(jìn)行隨機掏空,代碼也很簡單!

//隨機掏空
let nowItme = [], _option, nowOption = [];
for (let i = 0; i < 9; i++) {
 //抽取當(dāng)前行的所有坐標(biāo)
 nowItme = arrText[i].split(',');
 nowOption = [];
 //當(dāng)前行的隨機兩個坐標(biāo)掏空
 for (let j = 0; j < 2; j++) {
 //抽取當(dāng)前行的隨機一個坐標(biāo)
 _option = Math.floor(Math.random() * nowItme.length);
 //分割坐標(biāo)的x,y
 nowOption = nowItme.splice(_option,1)[0].split("-");
 this.allNum[nowOption[0]][nowOption[1]] = '';
 }
}

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

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

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

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

然后關(guān)于數(shù)字鍵盤的位置,看下圖(數(shù)字鍵盤的樣式我不多說了,就是一個是相對定位,一個絕對定位的設(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'。

代碼如下

<!--遍歷每一行-->
 <p v-for="row,index in allNum" class="num-row chearfix">
 <!--遍歷行里面的每一列-->
 <!--
 no:被掏空數(shù)組的樣式
 cur:格子被點擊時觸發(fā),被點擊的格子樣式
 -->
 <p v-for="num1,indexSub in row"
 :class="{'no':num1==='',
 'cur':curRow===index&&indexSub===curCol}"
 @click="showCheck(index,indexSub)" class="num-col">
 {{allNumText[index][indexSub]}}
 </p>
 </p>
<!--數(shù)字鍵盤-->
<p 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>
</p>

js代碼

/**
 * @description 顯示數(shù)字鍵盤
 * @param i1
 * @param i2
 */
showCheck(i1, i2){
 //點擊的格子是否是被掏空的格子
 if (this.allNum[i1][i2] !== '') {
 return
 }
 //點擊的格子如果是上一次點擊的格子(當(dāng)前格子)
 if (i1 === this.curRow && i2 === this.curCol) {
 //隱藏數(shù)字鍵盤,curRow和curCol設(shè)空
 this.checkShow = false;
 this.curRow = '';
 this.curCol = '';
 }
 else {
 //隱藏數(shù)字鍵盤,curRow和curCol分別設(shè)置成當(dāng)前的點
 this.checkShow = true;
 this.curRow = i1;
 this.curCol = i2;
 }
},

運行效果

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

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

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

代碼如下

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

運行效果

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

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

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

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ù)當(dāng)前格子進(jìn)行賦值
 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++) {
 //如果值一樣,但是坐標(biāo)不一樣,就是填寫錯誤
 if (_text === rowCheck[i] && _col !== i) {
 this.isErr = true;
 this.isShake = true;
 //記錄當(dāng)前格子的信息
 this.optionNow = {
 x: _row,
 y: _col,
 }
 //記錄和當(dāng)前格子同一行,以及同一個值的格子的坐標(biāo)
 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++) {
 //如果值一樣,但是坐標(biāo)不一樣,就是填寫錯誤
 if (_text === colCheck[i] && _row !== i) {
 this.isErr = true;
 this.isShake = true;
 //記錄和當(dāng)前格子同一列,以及同一個值的格子的坐標(biāo)
 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;
}

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

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

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

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

這樣是為了往掏空的格子輸入數(shù)字的時候,然后那個格子就不能再改了,即使是填錯了,都不能改。樣式控制也不正確!正確的格式應(yīng)該是下面這樣,即使填入了,格子的樣式還是灰色的,這樣可以方便的知道哪個格子是當(dā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>
<p class="num-box" v-show="numShow" id="num">
 <p class="num-tips">
 <p>所謂的數(shù)獨:規(guī)則</p>
 <p>1.每一行數(shù)字不重復(fù)</p>
 <p>2.每一列數(shù)字不重復(fù)</p>
 </p>
 <p class="num-table" @mouseleave="hoverCol=''" :class="{'shake':isShake}">
 <!--遍歷每一行-->
 <p v-for="row,index in allNum" class="num-row clear">
 <!--遍歷行里面的每一列-->
 <!--
 no:被掏空數(shù)組的樣式
 cur:格子被點擊時觸發(fā),被點擊的格子樣式
 cur-col:鼠標(biāo)進(jìn)入的時候觸發(fā),和被點擊格子同一列的格子的樣式
 err:填寫錯誤的時候觸發(fā)的樣式
 -->
 <p 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]}}
 </p>
 </p>
 <!--數(shù)字鍵盤-->
 <p 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>
 </p>
 </p>
</p>
</body>
<script src="../vue.min.js"></script>
<script>
 new Vue({
 el:'#num',
 data:{
 name: 'welcome',
 testText: '歡迎來到',
 nowIndex: 0,
 allNum: [],//數(shù)字排列
 answer: [],//所有答案的坐標(biāo)點
 allNumText: [],//數(shù)字,包括輸入后的數(shù)字
 curRow: '',//當(dāng)前格子所在的行的索引
 curCol: '',//當(dāng)前格子所在的列的索引
 checkShow: false,//數(shù)字鍵盤的顯示
 hoverCol: '',//鼠標(biāo)進(jìn)去的當(dāng)前列
 hoverRow: 0,//鼠標(biāo)進(jìn)入的當(dāng)前行
 numShow: true,//數(shù)獨的顯示
 optionNow: {},//輸入后的格子的坐標(biāo)
 optionNowInRow: {},//和輸入后的格子在同一行,并且同樣值的格子的坐標(biāo)
 optionNowInCol: {},//和輸入后的格子在同一列,并且同樣值的格子的坐標(biāo)
 isErr: false,//是否輸入錯誤后
 isShake: false//是否顯示震動的樣式
 },
 methods: {
 /**
 * @description 顯示數(shù)字鍵盤
 * @param i1
 * @param i2
 */
 showCheck(i1, i2){
 //點擊的格子是否是被掏空的格子
 if (this.allNum[i1][i2] !== '') {
 return
 }
 //點擊的格子如果是上一次點擊的格子(當(dāng)前格子)
 if (i1 === this.curRow && i2 === this.curCol) {
 //隱藏數(shù)字鍵盤,curRow和curCol設(shè)空
 this.checkShow = false;
 this.curRow = '';
 this.curCol = '';
 }
 else {
 //隱藏數(shù)字鍵盤,curRow和curCol分別設(shè)置成當(dāng)前的點
 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: '',
 }
 //*****************************檢查行
 //保存當(dāng)前格子的值
 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++) {
 //如果值一樣,但是坐標(biāo)不一樣,就是填寫錯誤
 if (_text === rowCheck[i] && _col !== i) {
 this.isErr = true;
 this.isShake = true;
 //記錄當(dāng)前格子的信息
 this.optionNow = {
 x: _row,
 y: _col
 }
 //記錄和當(dāng)前格子同一行,以及同一個值的格子的坐標(biāo)
 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++) {
 //如果值一樣,但是坐標(biāo)不一樣,就是填寫錯誤
 if (_text === colCheck[i] && _row !== i) {
 this.isErr = true;
 this.isShake = true;
 //記錄和當(dāng)前格子同一列,以及同一個值的格子的坐標(biāo)
 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;
 }
 }
 //記錄所有坐標(biāo)
 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++) {
 //抽取當(dāng)前行的所有坐標(biāo)
 nowItme = arrText[i].split(',');
 nowOption = [];
 //當(dāng)前行的隨機兩個坐標(biāo)掏空
 for (let j = 0; j < 2; j++) {
 //抽取當(dāng)前行的隨機一個坐標(biāo)
 _option = Math.floor(Math.random() * nowItme.length);
 //分割坐標(biāo)的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ù)獨,就寫到這里了,主要就是邏輯有點繞,其它的問題相信都難不倒大家。這個實例比之前快速入門的三個小實例要麻煩一點,但是也很好理解!大家只要稍微看下估計都不難理解!最后,如果大家覺得文章寫得不好,哪里寫錯了,歡迎給建議或者指點下迷津。期待和大家交流意見,共同進(jìn)步!

上面是我整理給大家的,希望今后會對大家有幫助。

相關(guān)文章:

使用js如何實現(xiàn)從新賦值

在js中如何將canvas生成圖片保存

在js中如何實現(xiàn)雙向綁定

詳細(xì)介紹webpack比較實用功能

使用jQuery如何實現(xiàn)菜單添加移除功能

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

使用vue如何開發(fā)數(shù)獨游戲

使用vue如何開發(fā)數(shù)獨游戲:數(shù)獨是源自18世紀(jì)瑞士的一種數(shù)學(xué)游戲,是一種運用紙、筆進(jìn)行演算的邏輯游戲。下面這篇文章主要給大家介紹了關(guān)于利用vue開發(fā)一個所謂的數(shù)獨的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。1.前言最近工作中遇到一個問題,因為后臺管理系
推薦度:
標(biāo)簽: VUE 游戲 開發(fā)
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top