あかり描像のブログ

思ったことや学習記録を適当に書いていきます。お気軽にコメントください

テトリスを作ってみたけど JavaScript が訳わからなすぎてハゲそう

何だってんだよぉ~!!

概要

JavaScript の練習がてら、テトリスを作ってみようと思いました。

そういえば遥か昔に GitHub Pages を立ち上げたきり、何も出来ていないなぁと思っていたんですが、ふと GitHub Pages では JS が動くじゃん!と思って、とりあえず上げてみた次第です。

bakkyalo.github.io

↑ここからできます。(現状スマホからでは動かせません)

  • key config
    • w ... 即落下
    • a ... ←
    • s ... ↓
    • d ... →
    • k ... 反時計回り回転
    • m ... 時計回り回転

キーコンフィグは上のようになっています。
ユーザー設定できないので、後で設定できるようにしたいとは思っています。

github.com

ソースコードはこちら。
場所が分かりにくいですが、

がそれです。(git の push の時期によってはリンクは切れるかも)

イメージ

テトリスを管理するデータ構造とアルゴリズムの設計

実際にテトリスを作る際のデータ構造やアルゴリズムの設計に関しては他のサイトや動画にたくさんあるため、気が向いたら書くくらいのノリでいようかなと思います。

t-kihira さんのこの動画をかなり参考にしています。
www.nicovideo.jp

TODO

  • 自動で落ちるようにする (難しくなるからあんまりやりたくはない)
  • 即落ち機能の実装
  • どこに落ちるかの表示
  • 連鎖数の管理と表示
  • key config のユーザー設定実装
  • ゲーム開始画面や終了時の実装
  • txt 挿入に詳しくなる。fetch API の習得?
  • 毎回全盤面を drawImage() してるのでクソ重。画像を挿入する方法を調べて検討する
  • 中身がほとんど一緒な移動可能判定と実際の移動が分離した実装になっており、無駄がある。
  • ミノを操作するたび毎回毎回回転処理を書いているのがなんだかなぁだよね。

JavaScript Tips

以下、私が JS を書いている中で躓いた点の備忘録を残しておきます。

。。。しかし、今回の JS のほとんどは、ChatGPT くんに訊きながら書いたなぁ。Google 先生よりも欲しい情報がダイレクトに来るからなぁ。あんたすげぇよ。もうこんな記事の存在意義なんて無いに等しいじゃん。

二次元配列

一気に宣言する方法がない。ので for で定義する。

let array = [];
for(let i = 0; i < 20; i++) {
    array[i] = [];
}

…と思いきや、あるんだよなぁこれが。

let array = new Array(20).fill().map( () => new Array(10).fill(0) );

値渡しと参照渡し?

普通の数字とかは変数に変数を代入して片方の値を書き換えるともう片方は値が書き変わらないけど、配列の変数に配列の変数を代入して片方を書き換えるともう片方も変わってしまう。

let a = 3;
let b = a;
b = 99;
console.log(a); // 3        -- まぁ分かる。
console.log(b); // 99
let a = [1, 2, 3, 4, 5];
let b = a;
b[2] = 99;
console.log(a);  // [1, 2, 99, 4, 5]    -- !!?
console.log(b);  // [1, 2, 99, 4, 5]

そういう所謂参照を共有する行為をシャロ―コピー (shallow copy) と呼ぶ。
対して、実体をそのまま複製する行為はディープコピー (deep copy) と呼ばれる。

シャロ?

なので、配列を値渡ししたい場合は、Object.assign() を使用する。

let a = [1, 2, 3, 4, 5];
let b = Object.assign([], a);
b[2] = 99;
console.log(a);   // [1, 2, 3, 4, 5]    --  ok!
console.log(b);   // [1, 2, 99, 4, 5]

じゃあ、2 次元配列を値渡ししたい時は?

concat, slice, Object.assign() は 2 次元目以降の値渡しには使えない。カスがよ


それなりに安全で、それなりに市民権のある方法は、JSON.parse()JSON.stringify() を使う方法らしい。
javascript 多次元配列の複製(値渡し)

let a = [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12] ];
let b = JSON.parse(JSON.stringify(a));
b[1][2] = 99;
console.log(a);
console.log(b);

最近だと structuredClone() というものができたらしい。
developer.mozilla.org

let a = [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12] ];
let b = structuredClone(a);
b[1][2] = 99;
console.log(a);
console.log(b);

これが一番簡単そうですね。

ただ、めっちゃ新しい機能らしいので (ブラウザによっては 2022年の夏からとかという噂が...) 、古いブラウザからではちゃんと見えないかもしれない。

innerText, TextContent, value らへんの話

わかんにゃい

タイムフレーム

setTimeout, setInterval, requestAnimationFrame

txt の中身を相対パスで開いてそのまま表示する

XMLHttpRequest() を使う。(ただ、今これ非推奨らしいね)

let request = new XMLHttpRequest();
request.open('GET', "./akari.txt");    // html からの相対パス

request.onload = () => {
    let htmlStr = "<pre>" + request.responseText + "</pre>";
    document.getElementById("akari").innerHTML = htmlStr;    // html の方で id="akari" と振っておきます
}
request.send();