[mini game] TETRIS

mgkim·2025년 1월 5일
1

react

목록 보기
29/36

아 이건 아닌거 같은디

https://www.youtube.com/watch?v=qJ_epnBRerI

import React, { useState, useEffect } from "react";
import "./App.css";

const GRID_WIDTH = 10;
const GRID_HEIGHT = 20;

const SHAPES = [
  { shape: [[1, 1, 1, 1]], color: "#FF5733" }, // I 블록
  { shape: [[1, 1], [1, 1]], color: "#FFC300" }, // O 블록
  { shape: [[0, 1, 0], [1, 1, 1]], color: "#DAF7A6" }, // T 블록
  { shape: [[1, 0, 0], [1, 1, 1]], color: "#33FF57" }, // L 블록
  { shape: [[0, 0, 1], [1, 1, 1]], color: "#3357FF" }, // J 블록
  { shape: [[0, 1, 1], [1, 1, 0]], color: "#AF33FF" }, // Z 블록
  { shape: [[1, 1, 0], [0, 1, 1]], color: "#FF33A8" }, // S 블록
];

const createEmptyGrid = () =>
  Array.from({ length: GRID_HEIGHT }, () => Array(GRID_WIDTH).fill(0));

const createNewBlock = () => {
  const randomShape = SHAPES[Math.floor(Math.random() * SHAPES.length)];
  return {
    shape: randomShape.shape,
    color: randomShape.color,
    x: 4,
    y: 0,
  };
};

const App = () => {
  const [grid, setGrid] = useState(createEmptyGrid());
  const [activeBlock, setActiveBlock] = useState(createNewBlock());
  const [nextBlock, setNextBlock] = useState(createNewBlock());

  const moveBlockDown = () => {
    setActiveBlock((prev) => {
      const newY = prev.y + 1;
      if (isCollision(prev.shape, prev.x, newY)) {
        mergeBlockToGrid(prev);
        return nextBlock;
      }
      return { ...prev, y: newY };
    });
    setNextBlock(createNewBlock());
  };

  useEffect(() => {
    const interval = setInterval(() => {
      moveBlockDown();
    }, 500);
    return () => clearInterval(interval);
  }, [activeBlock]);

  const isCollision = (shape, x, y) => {
    return shape.some((row, dy) =>
      row.some(
        (cell, dx) =>
          cell &&
          (grid[y + dy] === undefined ||
            grid[y + dy][x + dx] === undefined ||
            grid[y + dy][x + dx] !== 0)
      )
    );
  };

  const mergeBlockToGrid = (block) => {
    setGrid((prevGrid) => {
      const newGrid = prevGrid.map((row) => [...row]);
      block.shape.forEach((row, dy) => {
        row.forEach((cell, dx) => {
          if (cell) {
            newGrid[block.y + dy][block.x + dx] = block.color;
          }
        });
      });
      return newGrid;
    });
  };

  const displayGrid = () => {
    const display = grid.map((row) => [...row]);
    activeBlock.shape.forEach((row, dy) => {
      row.forEach((cell, dx) => {
        if (cell) {
          display[activeBlock.y + dy][activeBlock.x + dx] = activeBlock.color;
        }
      });
    });
    return display;
  };

  const renderNextBlock = () => {
    const gridSize = 4; // 4x4 그리드로 보여줌
    const nextGrid = Array.from({ length: gridSize }, () =>
      Array(gridSize).fill(0)
    );

    nextBlock.shape.forEach((row, dy) => {
      row.forEach((cell, dx) => {
        if (cell) {
          nextGrid[dy][dx] = nextBlock.color;
        }
      });
    });

    return nextGrid;
  };

  return (
    <div className="App">
      <div className="game-container">
        <div className="grid">
          {displayGrid().map((row, y) =>
            row.map((cell, x) => (
              <div
                key={`${y}-${x}`}
                className="cell"
                style={{
                  backgroundColor: cell || "#111",
                  width: 20,
                  height: 20,
                }}
              ></div>
            ))
          )}
        </div>
        <div className="next-block">
          <h2>Next Block</h2>
          <div className="block-preview">
            {renderNextBlock().map((row, y) =>
              row.map((cell, x) => (
                <div
                  key={`${y}-${x}`}
                  className="cell"
                  style={{
                    backgroundColor: cell || "#111",
                    width: 20,
                    height: 20,
                  }}
                ></div>
              ))
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

export default App;
profile
@lala.love_garden.lala

0개의 댓글