摘要:前言最近的后臺(tái)管理系統(tǒng)頁面,功能暫時(shí)沒有新的需求,就在想首頁放什么東西,最近我想到的就是放個(gè)所謂的數(shù)獨(dú),為什么是所謂的數(shù)獨(dú),因?yàn)橐?guī)則不同于標(biāo)準(zhǔn)的數(shù)獨(dú),只要求每一行每一列數(shù)字不一樣就可以了這個(gè)實(shí)例也是基于的,代碼分享給大家。
1.前言
最近的后臺(tái)管理系統(tǒng)頁面,功能暫時(shí)沒有新的需求,就在想首頁放什么東西,最近我想到的就是放個(gè)所謂的數(shù)獨(dú),為什么是所謂的數(shù)獨(dú),因?yàn)橐?guī)則不同于標(biāo)準(zhǔn)的數(shù)獨(dú),只要求每一行每一列數(shù)字不一樣就可以了!這個(gè)實(shí)例也是基于vue的,代碼分享給大家。給大家代碼,并不是要讓大家直接拷貝代碼,而是希望能讓大家當(dāng)做是一個(gè)練手的項(xiàng)目,或者學(xué)習(xí)到知識(shí)。如果大家覺得我哪里寫得不好,寫錯(cuò)了,歡迎指出,讓大家交流意見,一起進(jìn)步。代碼上傳到github了:有需要的可以star一下!vue-demos
2.運(yùn)行效果 3.實(shí)現(xiàn)步驟實(shí)現(xiàn)步驟,感覺說得有點(diǎn)繞,建議大家邊寫邊看文章,這樣不會(huì)懵?;蛘咧苯尤タ丛创a(sudoku),把源碼看懂!這個(gè)項(xiàng)目也不復(fù)雜!3-1.準(zhǔn)備數(shù)據(jù)和排版
排版的html+css代碼我不多說了,排版很簡(jiǎn)單,這個(gè)相信都難不倒大家的。復(fù)雜一點(diǎn)的就是數(shù)據(jù)的交互!
下面開始第一步,把數(shù)獨(dú)的數(shù)據(jù)先準(zhǔn)備好,數(shù)據(jù)是什么,大家都知道,就是像下面這樣的數(shù)據(jù)!
排版出來的效果就是下面這樣。
html代碼如下
{{allNumText[index][indexSub]}}
代碼也很簡(jiǎn)單,如下
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); //刪除第一個(gè)數(shù)字并記錄下來 rowCol = arr1.splice(0, 1)[0]; //在最后面插入數(shù)字 arr1.push(rowCol) } }
大家也可以發(fā)現(xiàn),這個(gè)數(shù)據(jù),的每一行和每一列的數(shù)字都是不同樣的!
3-2.打亂行之后就是隨機(jī)打亂順序了,打亂順序這個(gè)得保證一個(gè)前提,就是保證每一行每一列的數(shù)字都不一樣。這樣的話,我用了一個(gè)簡(jiǎn)單粗暴的方法-以行或者列為單位,進(jìn)行打亂。比如,第一行和第三行進(jìn)行位置交互,第一列和第五列進(jìn)行位置的交換。下面說下以行為單位的打亂順序!
行的打亂,很簡(jiǎn)單,就是隨機(jī)打亂數(shù)組而已!一行代碼搞定!
this.allNum.sort((n1, n2) => Math.random() - 0.5);3-3.打亂列
行打亂了,下面進(jìn)行以列為單位的打亂,這個(gè)稍微復(fù)雜一點(diǎn)。
大家想下,比如第二列是第五列的值進(jìn)行交換,那就是每一行的第二個(gè)格子的值和第五個(gè)格子的值進(jìn)行交換,那么就需要遍歷每一行!來進(jìn)行交換,至于前面說的第二列和第五列的這個(gè)列數(shù),可以用一個(gè)函數(shù)實(shí)現(xiàn)!
下面看代碼!
//隨機(jī)獲取兩列的索引 function randomText() { let rondomIndex = 0, rondomIndexAfter = 0; //獲取第一列的索引 rondomIndex = Math.floor(Math.random() * 9); function randomDo() { rondomIndexAfter = Math.floor(Math.random() * 9); //如果第一列和第二列索引一樣,第二列的索引再次重新隨機(jī)獲取 if (rondomIndexAfter === rondomIndex) { randomDo(); } } randomDo(); //返回兩列的索引 return [rondomIndex, rondomIndexAfter] } //打亂列 let randomArr = [], nowValue = 0; //同樣遍歷9次 for (let i = 0; i < 9; i++) { randomArr = Object.assign([], randomText()); //遍歷每一行,給每一行的隨機(jī)兩列交換值 for (let j = 0, len = this.allNum.length; j < len; j++) { //隨機(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.隨機(jī)掏空單元格
掏空單元格就是把一些格子隨機(jī)設(shè)空,然后讓玩數(shù)獨(dú)的人。把這些單元格給填上!
需求,我現(xiàn)在實(shí)現(xiàn)的就是,每一行有把兩個(gè)格子設(shè)空,這里我的做法是,把每一個(gè)格子的坐標(biāo)先記錄下來,然后再從記錄的坐標(biāo)里面隨機(jī)獲取坐標(biāo),用獲取到的坐標(biāo),進(jìn)行設(shè)空!
首先,獲取所有點(diǎn)的坐標(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);
看到這個(gè)坐標(biāo),大家很容易的知道,數(shù)組的一個(gè)元素,就是第一行,‘0-0’就是第一行第一個(gè)格子。數(shù)組最后一個(gè)元素,就是最后一行,‘8-8’就是最后一行,最后一個(gè)格子,其他如此類推!
下面進(jìn)行隨機(jī)掏空,代碼也很簡(jiǎn)單!
//隨機(jī)掏空 let nowItme = [], _option, nowOption = []; for (let i = 0; i < 9; i++) { //抽取當(dāng)前行的所有坐標(biāo) nowItme = arrText[i].split(","); nowOption = []; //當(dāng)前行的隨機(jī)兩個(gè)坐標(biāo)掏空 for (let j = 0; j < 2; j++) { //抽取當(dāng)前行的隨機(jī)一個(gè)坐標(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這個(gè)class對(duì)應(yīng)的樣式我在css那里寫好了,大家注意下。
3-4.顯示數(shù)字鍵盤{{allNumText[index][indexSub]}}
首先,我簡(jiǎn)單的用一個(gè)流程圖說下邏輯,如下
然后關(guān)于數(shù)字鍵盤的位置,看下圖(數(shù)字鍵盤的樣式我不多說了,就是一個(gè)是相對(duì)定位,一個(gè)絕對(duì)定位的設(shè)置而已)
如上圖,我點(diǎn)擊的是第一行第三個(gè)格子,首先,我期待被點(diǎn)擊的格子的樣式有所改變,方便我區(qū)分,這個(gè)不難,用一個(gè)class改變樣式就可以了,這個(gè)可以看下面的代碼,我用一個(gè).cur的class控制樣式。還有一個(gè)就是期待數(shù)字鍵盤在第二行,第四個(gè)格子那里出現(xiàn)。這樣的話,大家就知道,數(shù)字鍵盤的位置是怎么定位的了!數(shù)字鍵盤的top就是,被點(diǎn)擊格子所在的行的索引+160(60是格子的寬高),left就是,被點(diǎn)擊格子所在的列的索引+160(60是格子的寬高)。比如上圖,第一行第三個(gè)格子,top=(0+1)*60+"px",left=(2+1)*60+"px"。
代碼如下
{{allNumText[index][indexSub]}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
js代碼
/** * @description 顯示數(shù)字鍵盤 * @param i1 * @param i2 */ showCheck(i1, i2){ //點(diǎn)擊的格子是否是被掏空的格子 if (this.allNum[i1][i2] !== "") { return } //點(diǎn)擊的格子如果是上一次點(diǎn)擊的格子(當(dāng)前格子) if (i1 === this.curRow && i2 === this.curCol) { //隱藏?cái)?shù)字鍵盤,curRow和curCol設(shè)空 this.checkShow = false; this.curRow = ""; this.curCol = ""; } else { //隱藏?cái)?shù)字鍵盤,curRow和curCol分別設(shè)置成當(dāng)前的點(diǎn) this.checkShow = true; this.curRow = i1; this.curCol = i2; } },
運(yùn)行效果
3-5.高亮顯示同行同列這一步很簡(jiǎn)單,首先,高亮顯示行,大家都知道怎么做了,就是行對(duì)應(yīng)的div,設(shè)置一個(gè):hover,然后對(duì)應(yīng)設(shè)置單元格的樣式而已!這個(gè)不多說!
然后,高亮顯示列,復(fù)雜一點(diǎn),但是也很簡(jiǎn)單,原理我想大家也知道,就是當(dāng)鼠標(biāo)進(jìn)如格子的時(shí)候,在data里面,用一個(gè)變量?jī)?chǔ)存進(jìn)入的格子的列的索引,然后加上判斷,如果格子的列的索引等于進(jìn)入的格子的列的索引。就加上一個(gè)class,這里我用.cur-col。代碼如下
{{allNumText[index][indexSub]}}
運(yùn)行效果
3-6.填寫操作和錯(cuò)誤提示這一步的操作函數(shù),我直接發(fā)代碼吧,看代碼比我說的會(huì)清晰些,畢竟說的有點(diǎn)繞
{{allNumText[index][indexSub]}}
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)不一樣,就是填寫錯(cuò)誤 if (_text === rowCheck[i] && _col !== i) { this.isErr = true; this.isShake = true; //記錄當(dāng)前格子的信息 this.optionNow = { x: _row, y: _col, } //記錄和當(dāng)前格子同一行,以及同一個(gè)值的格子的坐標(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)不一樣,就是填寫錯(cuò)誤 if (_text === colCheck[i] && _row !== i) { this.isErr = true; this.isShake = true; //記錄和當(dāng)前格子同一列,以及同一個(gè)值的格子的坐標(biāo) this.optionNowInCol = { x: i, y: _col, } } } //如果發(fā)現(xiàn)的同樣的 if (this.isErr) { setTimeout(() => { this.isShake = false; }, 1000) return; } //如果數(shù)組去重后,長(zhǎng)度小于9,就是行沒完成 rowCheck = rowCheck.filter(item => item !== ""); if (rowCheck.length !== 9) { //console.log("行沒完成") return; } let coloCheck = []; //如果數(shù)組去重后,長(zhǎng)度小于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)成功,但是沒獎(jiǎng)品"); this.numShow = false; }
上面的代碼邏輯,簡(jiǎn)單說下
1..err 這個(gè)class是設(shè)置紅色字體所使用的,至于判斷,就是在inputText這個(gè)函數(shù)里面,有optionNow和 optionNowInRow和optionNowInCol。只要格子的坐標(biāo)等于三者其中之一,就會(huì)添加這個(gè)class,就會(huì)變紅。
2..isShake這個(gè)class是控制,抖動(dòng)的動(dòng)畫,添加上了之后,在一秒后,要去掉這個(gè)class,不然下次添加沒有動(dòng)畫效果。
3.在inputText這個(gè)函數(shù)里面,我操作的數(shù)獨(dú)列表,并不是之前,提到的allNum,而是利用allNum,深度拷貝生成出的allNumText(this.allNumText = JSON.parse(JSON.stringify(this.allNum));)。主要就是為了避免下圖的情況!
這樣是為了往掏空的格子輸入數(shù)字的時(shí)候,然后那個(gè)格子就不能再改了,即使是填錯(cuò)了,都不能改。樣式控制也不正確!正確的格式應(yīng)該是下面這樣,即使填入了,格子的樣式還是灰色的,這樣可以方便的知道哪個(gè)格子是當(dāng)時(shí)被掏空的,填寫錯(cuò)了,也是可以改的。
4.完整代碼vue-所謂的數(shù)獨(dú) 所謂的數(shù)獨(dú):規(guī)則
1.每一行數(shù)字不重復(fù)
2.每一列數(shù)字不重復(fù)
{{allNumText[index][indexSub]}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
reset.css和vue.min.js大家自行到github下載!
5.小結(jié)好了,用vue做的所謂的數(shù)獨(dú),就寫到這里了,主要就是邏輯有點(diǎn)繞,其它的問題相信都難不倒大家。這個(gè)實(shí)例比之前快速入門的三個(gè)小實(shí)例要麻煩一點(diǎn),但是也很好理解!大家只要稍微看下估計(jì)都不難理解!最后,如果大家覺得文章寫得不好,哪里寫錯(cuò)了,歡迎給建議或者指點(diǎn)下迷津。期待和大家交流意見,共同進(jìn)步!
-------------------------華麗的分割線--------------------
想了解更多,關(guān)注關(guān)注我的微信公眾號(hào):守候書閣
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/51611.html
摘要:前言最近的后臺(tái)管理系統(tǒng)頁面,功能暫時(shí)沒有新的需求,就在想首頁放什么東西,最近我想到的就是放個(gè)所謂的數(shù)獨(dú),為什么是所謂的數(shù)獨(dú),因?yàn)橐?guī)則不同于標(biāo)準(zhǔn)的數(shù)獨(dú),只要求每一行每一列數(shù)字不一樣就可以了這個(gè)實(shí)例也是基于的,代碼分享給大家。 1.前言 最近的后臺(tái)管理系統(tǒng)頁面,功能暫時(shí)沒有新的需求,就在想首頁放什么東西,最近我想到的就是放個(gè)所謂的數(shù)獨(dú),為什么是所謂的數(shù)獨(dú),因?yàn)橐?guī)則不同于標(biāo)準(zhǔn)的數(shù)獨(dú),只要求每...
摘要:題目描述有效的數(shù)獨(dú)判斷一個(gè)的數(shù)獨(dú)是否有效。上圖是一個(gè)部分填充的有效的數(shù)獨(dú)。數(shù)獨(dú)部分空格內(nèi)已填入了數(shù)字,空白格用表示。說明一個(gè)有效的數(shù)獨(dú)部分已被填充不一定是可解的。只需要根據(jù)以上規(guī)則,驗(yàn)證已經(jīng)填入的數(shù)字是否有效即可。 題目描述 有效的數(shù)獨(dú)判斷一個(gè) 9x9 的數(shù)獨(dú)是否有效。只需要根據(jù)以下規(guī)則,驗(yàn)證已經(jīng)填入的數(shù)字是否有效即可。 數(shù)字 1-9 在每一行只能出現(xiàn)一次。數(shù)字 1-9 在每一列只能出...
摘要:可以針對(duì)筆者常用的數(shù)獨(dú)本文的實(shí)現(xiàn)都基于該,實(shí)現(xiàn)數(shù)獨(dú)的識(shí)別求解并把答案自動(dòng)填入。專家級(jí)別的平均秒完成求解包括圖像數(shù)字提取,識(shí)別過程,完成全部操作。步驟四數(shù)獨(dú)求解,生成答案,并生成需要填充的數(shù)字序列。 1 序 ??數(shù)獨(dú)是源自18世紀(jì)瑞士的一種數(shù)學(xué)游戲。是一種運(yùn)用紙、筆進(jìn)行演算的邏輯游戲。玩家需要根據(jù)9×9盤面上的已知數(shù)字,推理出所有剩余空格的數(shù)字,并滿足每一行、每一列、每一個(gè)粗線宮(3*3...
摘要:上圖是一個(gè)部分填充的有效的數(shù)獨(dú)。數(shù)獨(dú)部分空格內(nèi)已填入了數(shù)字,空白格用表示。但由于位于左上角的宮內(nèi)有兩個(gè)存在因此這個(gè)數(shù)獨(dú)是無效的。說明一個(gè)有效的數(shù)獨(dú)部分已被填充不一定是可解的。只需要根據(jù)以上規(guī)則,驗(yàn)證已經(jīng)填入的數(shù)字是否有效即可。 判斷一個(gè) 9x9的數(shù)獨(dú)是否有效。只需要根據(jù)以下規(guī)則,驗(yàn)證已經(jīng)填入的數(shù)字是否有效即可。 數(shù)字 1-9 在每一行只能出現(xiàn)一次。 數(shù)字 1-9 在每一列只能出現(xiàn)一次...
閱讀 961·2021-11-24 09:39
閱讀 3383·2021-10-27 14:20
閱讀 2322·2019-08-30 14:08
閱讀 3361·2019-08-29 16:34
閱讀 2176·2019-08-26 12:14
閱讀 2104·2019-08-26 11:54
閱讀 2771·2019-08-26 11:44
閱讀 2474·2019-08-26 11:38