こんにちは!プログラミングとレトロゲームが大好物なみなさん!
今回のテーマは…なんと「7行で動くテトリス」!
「えっ、あのブロックがカシャカシャ落ちてくるテトリスを、たった7行で?」
そう思った方、めちゃくちゃ普通です。でもマジなんです。
この「7行テトリス」は、コード界隈でひっそりと語り継がれてきた“伝説の最小実装”のひとつ。HTMLで書かれたその短すぎるコードは、一見どう動くのかわからないようで、実は究極に無駄がない美しさを持っています。
今回はその7行テトリスの全貌を、初心者にもわかりやすく解説していきます!
コードの構造、動作の仕組み、そしてなぜこんなに短くできるのか——その秘密を一緒に覗いてみましょう♪
記事の先頭にも埋め込みで遊べるようにしていますが、この7行テトリスの元のゲームページはこちらです(新しいタブで開きます)。
🧩 7行テトリスとは?
「7行テトリス」は、JavaScriptで書かれた超短縮版テトリスです。
その名の通り、たった7行(約300文字)でテトリスのプレイが可能!
この作品は、「コードゴルフ」や「ショートコーディング」と呼ばれる分野で知られる代表的なスクリプトです。
コードゴルフとは:
目的の機能を、できるだけ短く実装することを競うプログラミング遊びのこと。※なぜゴルフにたとえられているのかというと、ゴルフはできるだけ打数を少なくした方が勝ちだからですね。
ゲームとして遊べるだけでなく、プログラミングの圧縮技術の極致としても注目されています。
🔍 7行テトリスを解説!
以下が実際のコードです(コピペで遊べます。遊び方は後述。):
<body id=D onKeyDown=K=event.keyCode-38><script>Z=X=[B=A=12];function Y(){for(C
=[q=c=i=4];f=i--*K;c-=!Z[h+(K+6?p+K:C[i]=p*A-(p/9|0)*145)])p=B[i];for(c?0:K+6?h
+=K:t?B=C:0;i=K=q--;f+=Z[A+p])k=X[p=h+B[q]]=1;if(e=!e)if(h+=A,f|B)for(Z=X,X=[l=
228],B=[[-7,-20,6,h=17,-9,3,3][t=++t%7]-4,0,1,t-6?-A:2];l--;)for(l%A?l-=l%A*!Z[
l]:(P+=k++,c=l+=A);--c>A;)Z[c]=Z[c-A];for(S="";i<240;S+=X[i]|(X[i]=Z[i]|=++i%A<
2|i>228)?i%A?"■":"■<br>":"_");D.innerHTML=S+P;Z[5]||setTimeout(Y,99-P)}Y(h=e=
K=t=P=0)</script>
すごく読みにくいですよね。でも、大丈夫です。以下のように段階的に分解していけば、中で何をしているのかがわかってきます。
▶ 7行テトリスの遊び方!
冒頭の埋め込みでも遊べますが、ほかのやり方としては自分の環境で遊ぶこともできます。
最も基本的な方法は、実際にこのコードをメモ帳などのテキストエディタに貼り付けます。
保存の時、適当な名前をつけ、テキストファイルではなく「すべてのファイル」を選択し「.html」の拡張子をつけてHTMLとして保存します。
それをブラウザで開いて実行すると、テトリスがプレイできます!
ターミナル風の「■」「_」で表示されるので、まるで懐かしいDOSゲームのような雰囲気です。
もう一つの方法としては、codepenなどのHTMLがリアルタイムで編集・表示できるウェブツールを使い、そこにコピペすることです。
すると保存などをしなくてもコピペで動作します。
🎮 ゲームの仕組み:段階解説
それではゲームの動く仕組みを段階的に解説していきましょう。
1. 入力処理(キーボード)
<body id=D onKeyDown=K=event.keyCode-38>
- キーが押されたとき、
Kにキーコードを格納。 - 矢印キー(←→↑↓)に対応。
- ↑:
K=0 - ←:
K=-1 - →:
K=1 - ↓:
K=2
- ↑:
2. ゲームの初期化
Z = X = [B = A = 12];
A = 12:盤面の横幅(12列)X:現在の盤面Z:次の状態を保持する配列(Xと同一参照)
3. ブロックの生成と回転処理
B = [[-7,-20,6,h=17,-9,3,3][t=++t%7]-4, 0, 1, t-6?-A:2];
tはブロックの種類(0~6)- 各値は、テトリミノを構成するブロックの相対座標。
4. 移動・当たり判定
for(c -= !Z[h+(K+6?p+K:C[i]=p*A-(p/9|0)*145)]) ...
ここは最も難解な部分ですが、要するに「押されたキーに応じて回転・左右移動・下移動を試み、衝突がないなら位置を更新する」という処理。
5. 行消去
for(Z=X, X=[l=228], ...; l--;) {
for(l%A ? l -= l%A*!Z[l] : (P+=k++, c=l+=A); --c>A;)
Z[c]=Z[c-A];
}
- 行が埋まった場合、その行を削除して上を落とす。
Pはスコア(行数)
6. 描画処理
for(S=""; i<240; S+=X[i]|(X[i]=Z[i]|=++i%A<2|i>228)?i%A?"■":"■<br>":"_");
D.innerHTML=S+P;
X[i]:現在の盤面状態- 画面にブロックがあるかどうかで
■または_を出力 - 改行は
<br>を使用
7. 再描画(ゲームループ)
Z[5] || setTimeout(Y, 99 - P)
- ブロックが詰まったら終了(Z[5])
- それ以外なら 100ms – スコア だけ待って
Y()を再呼び出し(加速処理)
なぜ回転できないの?
7行テトリスでは、上ボタンを押しても回転がうまく働きません。
これは以下の理由によります。
7行テトリスでは、ブロックの回転処理が基本的に存在しないか、非常に限定的な方法でしか行われていません。そのため、回転キー(↑キー)を押しても、回転しない/期待通りに動かないのが仕様です。
🔍 理由1:コードサイズを最優先しているため
7行テトリスは、コードゴルフ(=とにかく短く書くことが目的)の作品です。そのため、以下のような「通常のゲーム開発」では重要な機能が削られています:
| 一般のテトリス | 7行テトリスでは |
|---|---|
| ブロック回転 | 実装されていない / 固定形状 |
| 壁蹴り回転 | 実装されていない |
| 回転毎に衝突判定 | 実装されていない |
🔍 理由2:回転操作(↑キー)に機能を割り当てていない
以下のようなコード片でキー入力が処理されていますが:
for(C=[q=c=i=4];f=i--*K; c-=!Z[...] ) p=B[i];
ここで K = event.keyCode - 38 によって上下左右を扱っているように見えますが、↑キー(keyCode = 38 → K = 0)の処理が事実上無視されています。
そのため、そもそも回転キーを押しても何の効果もないんです。
💡 読みやすく書き直したらこうなる!
この7行コードはすごいけど、やっぱり読みづらい。
もし、これを普通のJavaScriptで書いたら、100〜200行くらいにはなります。
例えば、以下のようにモジュールごとに分けると読みやすくなります。
drawField():盤面の描画checkCollision():衝突判定moveBlock(dir):ブロックの移動rotateBlock():回転処理dropBlock():1段下に落とすfixBlock():ブロックを固定clearLines():揃った行の削除
このようにして、機能を分離すれば、学習にも再利用にも便利なコードになります。
🧾 まとめ
- 「7行テトリス」は、コードゴルフの神業的作品。
- 非常に短いが、入力処理・ブロック生成・当たり判定・描画・行消去・ループすべてが詰まっている。
- 圧縮されすぎて読みづらいが、段階的に見ていけば理解可能。
- 学習には読みやすい構造の再構成がおすすめ!
「7行テトリス」は、プログラミングの奥深さと楽しさを凝縮した芸術作品です。
ぜひ、あなたの目と指で、そのミニマルな世界を体験してみてください!


