剛寫過一篇《20多行js代碼寫一個最簡單的3×3拼圖遊戲》,受zswang的啟發下改進瞭代碼,現在做瞭一個任意M行N列(M,N大於等於2)的拼圖,js代碼30多行。
先上圖:
玩法:方向鍵,不用解釋瞭。
直接體驗就輕輕點擊這裡。
保證拼圖有解的方法主要有2種:
1.從結局開始移動若幹次,淺顯易懂,但是空格不在末尾瞭,如果要把空格移回末尾,還要多兩個循環;
2.用算法檢測隨機開局是否有解,如果無解則調整為有解或重新開局。
本篇采用瞭方法2,使用的算法叫做“逆序和”,保證有解、且空格在末尾。
關於開局的生成方法有3種:
1.數組隨機排序。
2.模擬洗牌算法。
3.從結局開始進行若幹次隨機方向的移動。
本篇使用算法2,《20多行js代碼寫一個最簡單的3×3拼圖遊戲》使用的是算法1,zswang的拼圖使用算法3。
數組隨機排序的效率可能不好,所以改成模擬洗牌算法,循環隨機交換。
另外,我加上瞭很方便的layout()和replay()函數,可以立即重新開始、立即切換佈局。
<p id="t1" style="border:1px solid black; padding:5px; display:inline-block;"></p>
<script>
var t1=document.getElementById("t1");
function layout(M,N){
R=M; C=N; r=R-1; c=C-1; D=[]; n=R*C-1;
w = (n+'').length;
rgx = new RegExp('(.{'+(w*C+c-1)+'}),','g');
space = new Array(w+1).join('_');
zero = new Array(w).join(0);
replay();
}
function replay(){
i=n;
while(i–){
D[i]=(zero+(i+1)).slice(-w);
}
D[n] = space;
ok = D+'';
while(++i<n){
j=D[rnd = Math.random()*(n-1)|0];
D[rnd]=D[i];
D[i]=j;
}
for(i=0,k=0;i<n;i++)
for(j=i+1;j<n;j++)
D[i]>D[j] && (k=1-k);
k && (i=D[n-2]) && (D[n-2]=D[n-1]) && (D[n-1]=i);
t1.innerHTML = (D+'').replace(rgx,'$1<br>');
}
function move(dir){
if (dir>=0&&dir<4) {
k = [[0,1],[1,0],[0,-1],[-1,0]][dir], rr2 = r+k[0], cc2 = c+k[1];
if (r2+1 && r2<R && c2+1 && c2<C)
return D[r*C+c] = D[r2*C+c2],
D[(r=r2)*C+(c=c2)] = space,
t1.innerHTML = (D+'').replace(rgx,'$1<br>');
}
}
document.onkeyup = function (e){
if(move((e||window.event).keyCode-37) && (D+'')==ok && alert('YOU WIN !'));
}
layout(4,4);
</script>
摘自 無心的專欄