イメージ
注意
- Chrome でのみ動作確認
- 矢印キーで操作
- 文字が小さいので、拡大はセルフサービス
v2
<pre id=p><script>a=`①②③④
⑤⑥⑦⑧
⑨⑩⑪⑫
⑬⑭⑮
`.split``
q=18
M=d=>!a[Q=q-(d&1?d*5-9:d)+1]||Q%5>3||d&-4||(a[q]=a[Q],a[q=Q]=` `)
A=a+``
S=_=>p.innerHTML=a.join``+(a==A)
for(i=334;i--;)M(Math.random()*4|0)
for(i=6;i--;)M(i&1)
S(onkeydown=e=>S(M(e.keyCode-37)))</script>
- 操作性のため
onkeyup
->onkeydown
に - 座標を1つにまとめた
- 初期位置を右下にする余裕ができた
v1
<pre id=p><script>
a=`①②③④
⑤⑥⑦⑧
⑨⑩⑪⑫
⑬⑭⑮
`.split``
r=c=3
M=d=>(d|(R=r,C=c,d&1?R-=d-2:(C-=d-1)))&-4||(a[r*5+c]=a[R*5+C],a[(r=R)*5+(c=C)]=" ")
A=a+""
S=_=>p.innerHTML=a.join``+(a==A)
for(i=334;i--;)M(Math.random()*4|0)
S(onkeyup=e=>S(M(e.keyCode-37)))
</script>
<pre id=p>
閉じタグがなくても動きます。id
に hoge
を設定することで、その要素を window.hoge
で参照できます。クオーテーションは不要です。<pre>
にしたのは、改行をそのまま出力するためです。
a=`①②③④
⑤⑥⑦⑧
⑨⑩⑪⑫
⑬⑭⑮
`.split``
r
行目 c
列目の要素に、a[r*5+c]
でアクセス出来るようにします。
.split``
は「タグ付きテンプレートリテラル」と呼ばれるもので、JavaScript のコードゴルフでは split
や join
と組み合わされることで威力を発揮します。
r=c=3
空白部分の座標です。
M=d=>(d|(R=r,C=c,d&1?R-=d-2:(C-=d-1)))&-4||(a[r*5+c]=a[R*5+C],a[(r=R)*5+(c=C)]=" ")
これはわかりづらいので、優先順位などを考慮して見やすくすると
M = d => {
R = r;
C = c;
_RC = (d & 1) ? (
R -= d - 2
) : (
C -= d - 1
);
(d | _RC) & -4 || (
a[r*5+c]=a[R*5+C],
a[(r=R)*5+(c=C)]=" "
);
};
M
は移動のための関数です。
まず (r, c)
を (R, C)
として保持します。
移動方向 d
は 0 1 2 3
のいずれかであると仮定して、それぞれ ← ↑ → ↓
を割り当てます。「d
が奇数なら行番号を d - 2
減らし、偶数なら列番号を d - 1
減らす」という操作は、実際に追ってみると正しいことがわかります。
ここで、「d
が 0 1 2 3
のいずれでもない場合」「R
または C
(変化した方が _RC
に入る)が 0 1 2 3
のいずれでもなくなった場合」が考えられます(d
については後述)。
これを (d | _RC) & -4
で、「d
か _RC
の下位2ビット以外にビットが立っているかどうか」という判定をします。
hoge || fuga
は if (!hoge) { fuga }
のようなものです。つまり、「d
か _RC
の下位2ビット以外にビットが立っていなければ」⇔「d
か _RC
が両方とも 0 1 2 3
に収まっていれば」、次を実行します。
この条件次第で、(r, c)
(遷移前)と (R, C)
(遷移後)の入れ替え操作が行われます。
A=a+""
S=_=>p.innerHTML=a.join``+(a==A)
a
を文字列化したものを A
に保存しておきます。
S
は表示のための関数です。==
はゆるい比較演算子なので、a == A
で a
は文字列に型変換され、初期状態と一致しているかが判定されます。
for(i=334;i--;)M(Math.random()*4|0)
Math.random()*4|0
は 0 1 2 3
のいずれかをランダムに返します。これで好きな回数だけ空白をかき混ぜます。
S(onkeyup=e=>S(M(e.keyCode-37)))
window.onkeyup
時に、キーコードを読み取って M
し、S
します。
← ↑ → ↓
に 37 38 39 40
が割り当てられているため、37
を引いて M
に渡せば、前述のようにバリデーションしてくれるというわけです。
最後に初期状態を S
して終わりです。
最後に
Twitter の文字数制限が変更されて、いい感じにプログラムが収まる程度になったので、みなさんもいろいろ挑戦してみてください。