最近心血來潮想製作一個數獨游戲,說乾咱就乾。剛剛好前一階段學習了es6,可以用這個項目來當做一個小練習。 目前開發已經完成,由於只是基本功能,頁面樣式並不是很華麗,下麵我們先開看看長什麼樣子。 大概頁面就長這個樣子,頁面有三個按鈕,分別是檢查,重玩,換題。 下麵是游戲中截圖。 ; ; 最後這個圖我比 ...
最近心血來潮想製作一個數獨游戲,說乾咱就乾。剛剛好前一階段學習了es6,可以用這個項目來當做一個小練習。
目前開發已經完成,由於只是基本功能,頁面樣式並不是很華麗,下麵我們先開看看長什麼樣子。
大概頁面就長這個樣子,頁面有三個按鈕,分別是檢查,重玩,換題。
- 檢查就是檢查當你填滿是否成功。
- 重玩就是放棄你所填的,重新開始本局游戲。
- 換題就是重新換個題目。
下麵是游戲中截圖。
;
;
最後這個圖我比較偷懶。直接生成的,並沒有自己填。
下麵就來看看代碼吧。
裡面最重要的就數演算法了吧。我使用是回溯法,廢話不多說直接上代碼。先來看一下生成數獨的演算法。大概就是把數獨分成81格,從1-81分別生成,沒生成一個格都要去判斷一下每一行,每一列,每一宮是否滿足規則。如果不滿足則回溯。下麵是生成數獨的方法。
//生成數獨
const makeArray=(arr, n)=>{
if(n == 81) {
return arr;
}
let x = Math.floor(n / 9);
let y = n % 9;
if(arr[x][y] == 0) {
let index = 0;
let arrn = makeRandomArray(9);
for(let i = 0; i < arrn.length; i++) {
arr[x][y] = arrn[i];
if(checkArrayByIndex(arr, x, y)) {
let endArr = makeArray(arr, n + 1);
if(!checkArrayHasZero(arr)) return endArr;
}
}
arr[x][y] = 0; //回溯
} else {
makeArray(arr, n + 1);
}
return arr;
}
當生成完數組之後,就可以生成游戲所用的數獨,其實則是隱藏其中的格子。
//對二維數組進行隨機n位置0
const resetZeroByArray=(arr,n)=>{
let k=0;
while(k<n){
let ranNum=randomNumber(81);
let x = Math.floor((ranNum-1) / 9);
let y = ranNum % 9;
if(arr[x][y]!=0){
arr[x][y]=0;
k++;
}
}
return arr;
}
最後則是當玩家填完數組之後再去驗證這個數獨是否滿足規則。
//判斷二維數組是否是完整數獨
checkSudoArray(arr){
let sign=true;
//檢查數組中是否含有0,如果有0立刻返回false
if(checkArrayHasZero(arr))return false;
//對每一行每一列每一宮進行檢查
for(let i=0;i<9;i++){
let rowSign=checkedRow(arr,i);
let colSign=checkedCol(arr,i);
let gongSign=checkedGongByNum(arr,i+1);
if(!(rowSign&&colSign&&gongSign)){
sign=false;
};
}
return sign;
}
//根據坐標檢查九宮格
const checkArrayByIndex = (arr, x, y) => {
let signRow = false;
let signCol = false;
let signGong = false;
//檢查行
signRow = checkedRow(arr, x);
//檢查列
signCol = checkedCol(arr, y);
//檢查宮
signGong = checkedGongByIndex(arr, x, y);
if(signRow && signCol && signGong) {
return true;
} else {
return false;
}
}
這樣演算法大概就介紹完了。接下來來看看頁面。頁面我是把二維數組直接放在父模板中,然後先去初始化然後根據這個數組去生成grid。
<div class="sudoMain" > <Row class="numRow" type="flex" v-for="(row,i) in arr" justify="center"> <i-col class="numCol" v-for="(cell,j) in row" :data-x='i' :data-y='j'><div class="spanDiv" @click="cellClick($event,i,j)">{{arr[i][j]==0?"":arr[i][j]}}</div></i-col> </Row> </div>
一定要記得把每個坐標賦值到元素上,這樣可以進行接下來的操作都很方便。接來下用戶選擇的數字面板單獨寫出來,通過點擊事件進行隱藏或者顯示。
selectClick(e,i,j){
this.showSelectPop=false;
this.arr[this.selectX][this.selectY]=(i-1)*3+j;
}
介紹的大體差不多了,代碼已經上傳到github,如果想看源碼的話可以直接上github下載。地址是:https://github.com/like2372/sudoVue.git。