HTML
JavaScript
Twitter
遊び

1ツイートに収まる15パズル.html

イメージ

image.png

注意

  • 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>

閉じタグがなくても動きます。idhoge を設定することで、その要素を window.hoge で参照できます。クオーテーションは不要です。<pre> にしたのは、改行をそのまま出力するためです。


a=`①②③④
⑤⑥⑦⑧
⑨⑩⑪⑫
⑬⑭⑮ 
`.split``

r 行目 c 列目の要素に、a[r*5+c] でアクセス出来るようにします。
.split`` は「タグ付きテンプレートリテラル」と呼ばれるもので、JavaScript のコードゴルフでは splitjoin と組み合わされることで威力を発揮します。


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) として保持します。
移動方向 d0 1 2 3 のいずれかであると仮定して、それぞれ ← ↑ → ↓ を割り当てます。「d が奇数なら行番号を d - 2 減らし、偶数なら列番号を d - 1 減らす」という操作は、実際に追ってみると正しいことがわかります。
ここで、「d0 1 2 3 のいずれでもない場合」「R または C (変化した方が _RC に入る)が 0 1 2 3 のいずれでもなくなった場合」が考えられます(d については後述)。
これを (d | _RC) & -4 で、「d_RC の下位2ビット以外にビットが立っているかどうか」という判定をします。
hoge || fugaif (!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 == Aa は文字列に型変換され、初期状態と一致しているかが判定されます。


for(i=334;i--;)M(Math.random()*4|0)

Math.random()*4|00 1 2 3 のいずれかをランダムに返します。これで好きな回数だけ空白をかき混ぜます。


S(onkeyup=e=>S(M(e.keyCode-37)))

window.onkeyup 時に、キーコードを読み取って M し、S します。
← ↑ → ↓37 38 39 40 が割り当てられているため、37 を引いて M に渡せば、前述のようにバリデーションしてくれるというわけです。
最後に初期状態を S して終わりです。

最後に

Twitter の文字数制限が変更されて、いい感じにプログラムが収まる程度になったので、みなさんもいろいろ挑戦してみてください。