HTML、JavaScript 、Vue之【數獨解密】(續上一篇)

一、頁面展示

(1)頁面中的空格爲input,方便輸入數據,數據通過使用Vue實現雙向動態綁定

(2)任意填入數據

(3)點擊【解密】,即解出數獨答案(當然我這裏是讓程序計算出一種結果便結束的

二、代碼展示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>數獨</title>
    <script type="text/javascript" src="../Import/vue.js"></script> <!--在上-->
    <link rel="stylesheet" href="../Import/element-ui-index.css">
    <script type="text/javascript" src="../Import/element-ui-index.js"></script>
    <style>
        li {
            list-style: none;
        }
        .el-input__inner {
            border-radius: 0;
        }
    </style>
</head>
<body>
<div id="app">
    <ul>
        <h2 style="margin-left: 155px">數獨解密</h2>
        <li v-for="(value,i) in items.length">
            <span v-for="(item,j) in items[i]" @click="changeNum(i,j)">
                <el-input class="ano" v-model="items[i][j]" maxlength="1"
                          style="width: 45px;font-size: 20px;text-align: center;cursor: pointer"></el-input>
            </span>
        </li>
    </ul>
    <el-button size="medium" style="margin-left: 300px" @click="reset">重置</el-button>
    <el-button size="medium" type="primary" @click="decode">解密</el-button>
</div>
</body>
<script>
    new Vue({
        el: '#app',
        data() {
            return {
                items: [["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""],
                    ["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""],
                    ["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""]],
                sign: false,
            }
        },
        mounted() {
            let all_div = document.querySelectorAll('.ano');
            for (let i = 0; i < 9; i++) {
                all_div[i * 9].style.borderLeft = "1px solid black";
                all_div[i * 9 + 2].style.borderRight = "1px solid black";
                all_div[i * 9 + 5].style.borderRight = "1px solid black";
                all_div[i * 9 + 8].style.borderRight = "1px solid black";
                all_div[i].style.borderTop = "1px solid black";
                all_div[i + 9 * 3].style.borderTop = "1px solid black";
                all_div[i + 9 * 6].style.borderTop = "1px solid black";
                all_div[i + 9 * 8].style.borderBottom = "1px solid black";
            }
        },
        methods: {
            changeNum(i, j) {
                console.log(i, j);
                console.log(typeof this.items[i][j]);
            },

            reset() {
                this.sign = false;
                for (let i = 0;i < 9;i++){
                    for (let j = 0;j < 9;j++){
                        this.items[i].splice(j, 1, ""); //刪除第行第j 個元素,再賦值""
                    }
                }
            },

            //一行裏面1-9
            //一列裏面1-9
            //一個九宮格里面1-9
            check(n, key) { // 判斷key填入n格時是否滿足條件,n代表第幾個格子
                for (let ii = 0; ii < 9; ii++) { // j爲n豎座標 判斷n所在行是否合法
                    let jj = parseInt(n / 9);
                    if (this.items[jj][ii] == key)
                        return false;
                }
                for (let ii = 0; ii < 9; ii++) { // j爲n橫座標 判斷n所在列是否合法
                    let jj = n % 9;
                    if (this.items[ii][jj] == key)
                        return false;
                }
                let y = parseInt(parseInt(n / 9) / 3) * 3;
                let x = parseInt((n % 9) / 3) * 3;
                for (let ii = y; ii < y + 3; ii++)//判斷n所在的小九宮格是否合法
                    for (let jj = x; jj < x + 3; jj++)
                        if (this.items[ii][jj] == key)
                            return false;
                return true;
            },

            dfs(n) { // 所有的都符合,退出搜索,n代表格子數,共81個格子,0~80
                if (n > 80) {
                    this.sign = true;
                    return;
                }
                if (this.items[parseInt(n / 9)][n % 9] != "")
                    this.dfs(n + 1);
                else { // 否則對當前位一次填入1~9進行測試
                    for (let ii = 1; ii <= 9; ii++) {
                        if (this.check(n, ii)) {
                            this.items[parseInt(n / 9)].splice([n % 9],1,ii);
                            this.dfs(n + 1);
                            if (this.sign)// 返回時如果構造成功,則直接退出
                                return;
                            // 繼續搜索,後續位也填1~9測試,直到最後一位,通過的話置true
                            // 如果構造不成功,還原當前位
                            this.items[parseInt(n / 9)].splice([n % 9],1,"");
                            //this.items[parseInt(n / 9)][n % 9] = "";
                        }
                    }
                }
            },

            decode() {
                console.log(this.items);
                console.log("解密");
                this.dfs(0); //從第0格開始填
                console.log(this.items);
                this.items = JSON.parse(JSON.stringify(this.items));
            }
        }
    })
</script>
</html>

三、爬坑

(1)在頁面中直接通過input輸入的數據類型爲String

 

 

原因:

我一開始寫匹配的時候,寫的 === 便成了第一個坑,因爲我實際上往數組裏面存的數據是Number型,而 === 判斷 1 != "1"。

check(n, key) { 
      for (let ii = 0; ii < 9; ii++) { 
          let jj = parseInt(n / 9);
          if (this.items[jj][ii] == key)  /*這個位置 here*/
               return false;
      }
      for (let ii = 0; ii < 9; ii++) { 
          let jj = n % 9;
          if (this.items[ii][jj] == key)  /*這個位置 here*/
                return false;
      }
      let y = parseInt(parseInt(n / 9) / 3) * 3;
      let x = parseInt((n % 9) / 3) * 3;
      for (let ii = y; ii < y + 3; ii++)
          for (let jj = x; jj < x + 3; jj++)
               if (this.items[ii][jj] == key)  /*這個位置 here*/
                    return false;
                return true;
},

 

(2)Vue數組中數值變化頁面不渲染問題

解出數獨值之後,數組雖然已發生變化,但是頁面未發生渲染 數據動態綁定竟然失效!

原因:

由於JavaScript的限制,Vue不能檢測以下變動的數組:

1. 利用索引值直接設置一個項時,如vm.items[indexOfItem] = newValue;

this.items[parseInt(n / 9)][n % 9] = ii; //本代碼中出問題的地方
this.items[parseInt(n / 9)][n % 9] = "";

2. 修改數組的長度時,如vm.items.lenngth = newLength; 

爲了解決第一類問題,以下兩種方式都可以實現和 vm.items[indexOfItem] = newValue 相同的效果,同時也將觸發狀態更新:

// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice
example1.items.splice(indexOfItem, 1, newValue)

爲了解決第二類問題,你可以使用 splice

example1.items.splice(newLength)

其他相關Vue無法渲染的問題參考如下:Vue數組中對象屬性變化頁面不渲染問題

解決方法1:

 decode() {
     console.log(this.items);
     console.log("解密");
     this.dfs(0); 
     console.log(this.items);
     this.items = JSON.parse(JSON.stringify(this.items));  //解決方法:直接重新賦值 
}

解決方法2:使用splice方法

this.items[parseInt(n / 9)].splice(n % 9, 1, ii);  //將出現問題的兩句代碼替換爲splice
this.items[parseInt(n / 9)].splice(n % 9, 1, "");

 

(3)JavaScript 除法 會保留小數點

解決:

爬坑長經驗!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章