スマレジエンジニアyushiのブログ

スマレジエンジニアのブログ

【テトリス #8】揃った行の削除

テトリスを作っています。

テトリス カテゴリーの記事一覧 - スマレジエンジニアyushiのブログ

技術スタックは下記の通りです。

  • TypeScript
  • React
  • SCSS
  • Create React App

今回は、揃った行を削除します。

データ構造の修正

最初にデータ構造を修正します。

過去の実装にて盤上ブロックをブロックの状態(4つのタイルで1セット)で保持していたのですが、
タイルが消えた時にブロックの一部だけ(4つの内2つだけなど)が残ることがあります。

そのため、盤上のブロックをタイル単位(1つのマス)で保持するようにします。

export type Tile = {
  x: number;
  y: number;
  type: BlockType;
};

座標(x, y)の他、表示時の色指定などのために、ブロック種別(BlockType)を保持します。

その他のロジックは既存のものを少しずつ改修するのみです。

揃った行の削除

揃った行があれば、その行番号を返すロジックを作成します。
行のブロック数と列数が一致していることを判定します。

export const getCompletedRows = (
  tiles: Tile[],
  boardWidth: number
): number[] => {
  return (
    Array.from(new Set(tiles.map(({ y }) => y)))
      // 行のブロック数 = 列数
      .filter((y) => tiles.filter((tile) => tile.y === y).length === boardWidth)
  );
};

行を削除するロジックです。
同時に、削除した分上の行を下に落とします。

export const deleteRows = (tiles: Tile[], rows: number[]): Tile[] => {
  return (
    tiles
      // 対象の行の削除
      .filter(({ y }) => !rows.includes(y))
      // 自身より下の行について、削除した分ブロックを下に落とす
      .map((tile) => ({
        ...tile,
        y: tile.y - rows.filter((row) => row < tile.y).length,
      }))
  );
};

hooksのnextStep関数に組み込みます。

let nextTiles = [...tiles, ...getTiles(fallingBlock)];

const completedRows = getCompletedRows(nextTiles, boardWidth);

if (completedRows.length) {
  nextTiles = deleteRows(nextTiles, completedRows);
}

setTiles(nextTiles);

Pull Request

あとがき

コロナにかかってとても大変でした。