30分で作る数字並べ:1から順に押す反応ゲーム
遊びをつくる執筆にClaudeを使用しています。

画面にばらばらに並んだ1から25までの数字を、小さい順に押していくだけのゲームです。ルールは数秒で説明できますが、遊ぶと「次の数字がどこにあるか」を探す時間と、見つけて押す時間が混ざって、意外と手が止まります。この記事は、その小さな遊びを1枚のHTMLファイルで作る手順です。 題名の「30分」は、作業を4つに分けたときの目安の配分です。ファイルを用意して盤面を出す、押す順番の判定を入れる、計測を付ける、調整して確認する、という順に進めます。進み具合には個人差があるので、30分で終わらなくても問題ありません。 このゲームの面白さの核は「計測」にあります。数字を並べるだけなら作業ですが、秒数とミス数が出ると「もう一回」が生まれます。そこで、計測の表示と、ミスの扱い方(罰則の付け方)を中心に組み立てます。外部ライブラリは使わず、ブラウザだけで動く最小構成にします。
この記事の目次
作るものと、先に決めておく3つのこと
最初に、遊びの仕様を3つだけ決めます。後から変えられますが、決めておくと手が止まりません。
- 盤面:5×5のマスに1〜25をランダムに配置します。
- 判定:いま押すべき数字(次の数字)だけが正解です。違う数字を押すとミスになります。
- 記録:クリアまでの秒数と、ミス数を表示します。ミス1回につき2秒を加えた値を最終スコアにします。
ミスに秒数を足す方式にするのは、「焦って連打する」遊び方と「慎重に探す」遊び方の釣り合いを取るためです。罰則がないと、ミスしても損がないので、当てずっぽうに押し続けるのが最善になってしまいます。何秒足すのがちょうどよいかは後半で自分の手で確かめます。
手順1:ファイルを作る(0〜5分)
- テキストエディタで新しいファイルを作り、名前を index.html にします。アソバースへ投稿するときも、入口のファイル名はこの名前にします。
- 下のコードをそのまま貼り付けて保存します。後の手順では、この中のどこが何を担当しているかを順に見ていきます。
- ファイルをブラウザで開き、「開始」を押して、数字の盤面が出れば最初の確認は完了です。
<!doctype html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>数字並べ</title>
<style>
body{font-family:sans-serif;text-align:center;margin:0;padding:12px}
#grid{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;max-width:400px;margin:12px auto}
button{font-size:1.4rem;padding:14px 0;border:2px solid #345;border-radius:8px;background:#fff;touch-action:manipulation}
button.done{visibility:hidden}
button.miss{background:#fcc}
</style>
<h1>数字並べ</h1>
<p id="info">開始を押すと1から順に押します</p>
<button id="start">開始</button>
<div id="grid"></div>
<script>
const N=25;
let next=1,t0=0,miss=0,best=null,timer=null;
const grid=document.getElementById('grid');
const info=document.getElementById('info');
function shuffle(a){for(let i=a.length-1;i>0;i--){const j=Math.floor(Math.random()*(i+1));[a[i],a[j]]=[a[j],a[i]];}return a;}
function start(){
next=1;miss=0;grid.innerHTML='';
const nums=shuffle(Array.from({length:N},(_,i)=>i+1));
nums.forEach(n=>{const b=document.createElement('button');b.textContent=n;b.onclick=()=>press(b,n);grid.appendChild(b);});
t0=performance.now();
clearInterval(timer);timer=setInterval(show,100);show();
}
function show(){
const s=((performance.now()-t0)/1000).toFixed(1);
info.textContent='次は '+next+' / '+s+'秒 / ミス '+miss;
}
function press(b,n){
if(n!==next){miss++;b.classList.add('miss');setTimeout(()=>b.classList.remove('miss'),200);show();return;}
b.classList.add('done');next++;
if(next>N)finish();
}
function finish(){
clearInterval(timer);
const t=(performance.now()-t0)/1000;
const score=t+miss*2;
if(best===null||score<best)best=score;
info.textContent='完了 '+t.toFixed(2)+'秒 + ミス'+miss+'×2秒 = '+score.toFixed(2)+'秒(ベスト '+best.toFixed(2)+')';
}
document.getElementById('start').onclick=start;
</script>手順2:盤面と判定の仕組みを読む(5〜15分)
貼り付けたコードを、3か所に分けて読み取ります。自分の好みに変えたいときの手がかりになります。
並べ替え(shuffle関数)
1〜25の配列を、後ろから順に「ランダムに選んだ位置の要素と入れ替える」ことで混ぜています。フィッシャー–イェーツ法と呼ばれる定番のやり方です。sort にランダムな比較関数を渡す書き方は手軽ですが、偏りが出やすいことが知られているため、この方法を使っています。
判定(press関数)
変数 next が「いま押すべき数字」です。押したボタンの数字が next と同じなら、そのボタンに done クラスを付けて見えなくし、next を1つ進めます。違えばミス数を増やし、0.2秒だけ赤くします。
ボタンを消すとき、display:none ではなく visibility:hidden にしています。前者だと残りのボタンが詰めて並び直され、数字の位置が毎回ずれて探しにくくなるからです。場所を保ったまま消えることで、「残りの数字を目で追う」遊びになります。
終了条件
next が25を超えた時点で finish を呼びます。「25個押した」ではなく「次の数字が範囲を超えた」で判定しているので、N を変えれば盤面の大きさを変えても動きます。ただし、盤面の列数は CSS の repeat(5,1fr) にも書かれているので、こちらも合わせて直します。
手順3:計測を整える(15〜22分)
このゲームの面白さを決めるのは、計測の見せ方です。コードでは次の3つを行っています。
- performance.now() で開始時刻を記録し、100ミリ秒ごとに経過秒数を画面に出します。Date.now() より細かく、システム時計の変更の影響を受けにくい時計です。
- ミスは回数として数え、最終スコアに「ミス数×2秒」を加えます。
- ベストスコアを変数 best に持ち、更新されたときだけ値を差し替えます。
ここで注意したいのは、best が「ページを開いている間だけ」の記録だという点です。再読み込みすると消えます。ブラウザの保存機能を使えば残せますが、アソバースにアップロードした作品内の localStorage や sessionStorage は、一時メモリーとして扱われる互換処理です。続けて遊んだときの記録は画面を開いている間だけ、と割り切るのが安全です。ログイン中のクラウドセーブをこのゲームで使えるかどうかは、現在の案内で確認してください。
手順4:自分の手で調整して確かめる(22〜30分)
ここからは、読者自身が計測して決める部分です。ミスの罰則や盤面の大きさは、設定ひとつで遊び心地が大きく変わります。次のように比べてみます。
比べる条件
- ミスの罰則:0秒、2秒、5秒の3通り(コードの miss*2 の数字を書き換えます)。
- 盤面の大きさ:4×4、5×5、6×6の3通り。
一度に両方を変えると原因が分からなくなるので、まず罰則だけを変え、次に盤面だけを変えます。
記録の取り方
- 1回のプレイを1行として、紙かメモに「条件、クリア秒数、ミス数」を書きます。
- 同じ条件を5回ずつ遊びます。最初の1〜2回は盤面に慣れる途中なので、集計では外すと決めておきます。
- 条件ごとに、秒数の最小値と最大値、ミス数の平均を並べます。
結果の読み方
- 罰則0秒でミスが多く、秒数が短いなら、当てずっぽうが有利になっています。罰則を重くする目安です。
- 罰則5秒でほぼ全員がミスを避けて遅くなるなら、重すぎて冒険しにくい状態です。
- 同じ条件でも秒数の差が大きいときは、盤面の運(数字の並び)の影響が大きいサインです。回数を増やすか、同じ配置を再挑戦できる仕組みを加えることを考えます。
- 慣れた後も秒数が縮み続けるなら、「もう一回」が続く遊びになっています。
自分ひとりの記録では偏りが出るので、家族や友人に遊んでもらえるなら、その人の最初の数回の動きも見ておきます。どこで手が止まるかが、盤面の設計への最大のヒントになります。
つまずきやすい点
- 数字を押しても反応しない:<script> が閉じられていない、またはコードの貼り付け漏れが多いです。ブラウザの開発者ツールのコンソールにエラーが出ていないかを見ます。
- スマホで拡大されてしまう:ボタンを素早く連続で押すと、ダブルタップで拡大されることがあります。コードの touch-action:manipulation がそれを抑えます。
- 押し心地を速くしたい:onclick を onpointerdown に変えると、指を離す前に反応するので少し速くなります。そのぶん、誤タップも増えます。罰則と合わせて、手順4と同じ方法で確かめます。
- 画面が小さくて押しにくい:max-width:400px と padding:14px 0 を調整します。盤面を大きくするほど、探す時間より押す時間が長くなります。
次の行動
まずコードを保存して、25個すべてを押し切るところまで遊んでみます。そのうえで、ミスの罰則を0秒・2秒・5秒に変えて、各5回ずつ記録を取ってみます。納得のいく遊び心地になったら、アソバースの投稿画面に index.html をアップロードします。入力、表示の確認、公開の3段階があり、公開にはメールアドレスの確認が必要です。ファイルは20MiB以内で、入口は直下の index.html にします。

