數(shù)獨(dú)游戲是一種很受歡迎的智力游戲,在網(wǎng)上也有很多相關(guān)的小游戲或者教程,其中javascript是一個很常用的實(shí)現(xiàn)方式。下面我們就來看一下如何用javascript實(shí)現(xiàn)數(shù)獨(dú)游戲。
首先,我們需要確定游戲的基本框架。一個數(shù)獨(dú)游戲一般有81個小格子,每個小格子有一個數(shù)字,最終要保證每個數(shù)字在每一行、每一列、每一個九宮格都出現(xiàn)過一次,并且不能重復(fù)。具體實(shí)現(xiàn)中,我們可以用一個9×9的二維數(shù)組來儲存這些數(shù)字,其中0代表沒有填寫。
var sudoku = [ [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0] ];
接著,我們需要用javascript生成一個可交互的網(wǎng)頁界面。一種常用的方法是,將每個格子都用一個input標(biāo)簽表示,用CSS控制大小和樣式,并通過javascript獲取用戶輸入的數(shù)字。在代碼中可以通過for循環(huán)和document.createElement()來實(shí)現(xiàn)這個過程。
for (var row = 0; row< 9; row++) { for (var col = 0; col< 9; col++) { var input = document.createElement('input'); input.type = 'number'; input.min = '1'; input.max = '9'; input.className = 'sudoku-box'; input.id = 'cell-' + row + '-' + col; input.oninput = function() { var cell = this.id.split('-'); sudoku[cell[1]][cell[2]] = Number(this.value); }; document.getElementById('sudoku-board').appendChild(input); } }
在這段代碼中,我們先用兩個for循環(huán)遍歷每個格子,為它們動態(tài)生成了一個input標(biāo)簽,并且對于每一個標(biāo)簽,都設(shè)置了一個唯一的id,并為它們綁定了一個oninput事件,當(dāng)用戶輸入數(shù)字時,就可以把這個數(shù)字存儲到二維數(shù)組中。
接下來,我們需要實(shí)現(xiàn)一個函數(shù),用來檢查當(dāng)前填寫的數(shù)字是否符合游戲規(guī)則。一個簡單的思路是,利用數(shù)組的索引和值來判斷是否有重復(fù)數(shù)字。比如,對于每一行,只需要檢查這一行的每一個數(shù)字是否在這個數(shù)組中出現(xiàn)過,如果是,則說明已經(jīng)重復(fù)。
function checkRow(row) { var nums = []; for (var i = 0; i< 9; i++) { var num = sudoku[row][i]; if (num !== 0 && nums.includes(num)) { return false; } nums.push(num); } return true; }
這段代碼中,我們首先創(chuàng)建了一個空的數(shù)組nums,然后遍歷這一行的每個數(shù)字,檢查它是否已經(jīng)在數(shù)組中出現(xiàn)過,如果是則返回false,否則將它添加到數(shù)組中繼續(xù)往下遍歷,最終返回true。利用類似的方法,我們也可以實(shí)現(xiàn)檢查每一列和每一個九宮格的函數(shù)。
最后,我們需要用一個遞歸函數(shù)來實(shí)現(xiàn)數(shù)獨(dú)游戲的求解。基本思路是,從左上角的格子開始依次遍歷每一個格子,如果它是空的,則嘗試填寫1-9中的任意一個數(shù)字,填寫后再檢查這一行、這一列和這一個九宮格是否符合游戲規(guī)則,如果符合則繼續(xù)往下遍歷,直到填滿整個數(shù)獨(dú)數(shù)組。
function solveSudoku(row, col) { if (row == 9) { return true; } if (col == 9) { return solveSudoku(row + 1, 0); } if (sudoku[row][col] !== 0) { return solveSudoku(row, col + 1); } for (var num = 1; num<= 9; num++) { sudoku[row][col] = num; if (checkRow(row) && checkCol(col) && checkBox(row, col) && solveSudoku(row, col + 1)) { return true; } sudoku[row][col] = 0; } return false; }
在這段代碼中,我們首先檢查當(dāng)前的行數(shù)和列數(shù)是否已經(jīng)超過了9,如果已經(jīng)超過,則說明已經(jīng)填滿了整個數(shù)獨(dú),直接返回true。否則,我們檢查當(dāng)前格子是否已經(jīng)填寫了數(shù)字,如果是,則直接往下遍歷。如果不是,則依次嘗試填寫1-9中的每個數(shù)字,檢查是否符合游戲規(guī)則,如果符合,則繼續(xù)往下遍歷,最終返回true。如果一直嘗試完9個數(shù)字后都無法滿足游戲規(guī)則,則需要將當(dāng)前格子的值重置為0,返回false。
綜上所述,我們可以用javascript實(shí)現(xiàn)一個完整的數(shù)獨(dú)游戲,在用戶填寫數(shù)字的同時,也可以通過遞歸函數(shù)自動求解。由于數(shù)獨(dú)游戲的難度不一,每個人心中都有自己的評價標(biāo)準(zhǔn),因此,我們可以通過調(diào)整遞歸函數(shù)的實(shí)現(xiàn)方式,讓它更加具有針對性和可調(diào)節(jié)性。