본문 바로가기
Develop

[AI] 프롬프트로 웹 테트리스 구현

by 너드나무 2024. 5. 28.
728x90
Start Game Pause Reset Score: 0 Controls: W (회전), A (왼쪽), S (내리기), D (오른쪽)

 

프롬프트 개발 코드 (단순 기능, 프롬프트 5회 사용)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Tetris Game</title>
  <style>
    game-body {
      padding: 20px 0;
      font-family: 'Arial', sans-serif;
      background-color: #f4f4f4;
      display: flex;
      flex-direction: column;
      align-items: center;
      margin: 0;
    }
    game-container {
      display: grid;
      grid-template-columns: repeat(10, 30px);
      grid-template-rows: repeat(21, 30px); /* Modified to 21 rows */
      gap: 1px;
      background-color: #222;
    }
    game-container > game-cell {
      width: 30px;
      height: 30px;
      background-color: #eee;
    }
    game-container > game-cell.taken {
      background-color: #333;
    }
    game-container > game-cell.tetromino {
      background-color: #007bff;
    }
    game-controls {
      margin-top: 20px;
      text-align: center;
    }
    game-controls > game-button {
      padding: 10px 20px;
      font-size: 16px;
      margin: 5px;
      cursor: pointer;
    }
    game-score {
      margin-top: 20px;
      font-size: 20px;
    }
    game-guide {
      margin-top: 10px;
      font-size: 16px;
    }
  </style>
</head>
<body>
<game-body>
  <game-container id="grid">
    <script>
      for (let i = 0; i < 210; i++) { /* Modified to 210 cells */
        document.write('<game-cell></game-cell>');
      }
    </script>
  </game-container>
  <game-controls>
    <game-button onclick="startGame()">Start Game</game-button>
    <game-button onclick="pauseGame()">Pause</game-button>
    <game-button onclick="resetGame()">Reset</game-button>
  </game-controls>
  <game-score>Score: <span id="score">0</span></game-score>
  <game-guide>Controls: W (회전), A (왼쪽), S (내리기), D (오른쪽)</game-guide>
</game-body>

<script>
  document.addEventListener('DOMContentLoaded', () => {
    const grid = document.querySelector('#grid');
    let squares = Array.from(document.querySelectorAll('#grid game-cell'));
    const width = 10;
    let nextRandom = 0;
    let timerId;
    let score = 0;
    let dropSpeed = 1000;

    // The Tetrominoes
    const lTetromino = [
      [1, width + 1, width * 2 + 1, 2],
      [width, width + 1, width + 2, width * 2 + 2],
      [1, width + 1, width * 2 + 1, width * 2],
      [width, width * 2, width * 2 + 1, width * 2 + 2]
    ];

    const zTetromino = [
      [0, width, width + 1, width * 2 + 1],
      [width + 1, width + 2, width * 2, width * 2 + 1],
      [0, width, width + 1, width * 2 + 1],
      [width + 1, width + 2, width * 2, width * 2 + 1]
    ];

    const tTetromino = [
      [1, width, width + 1, width + 2],
      [1, width + 1, width + 2, width * 2 + 1],
      [width, width + 1, width + 2, width * 2 + 1],
      [1, width, width + 1, width * 2 + 1]
    ];

    const oTetromino = [
      [0, 1, width, width + 1],
      [0, 1, width, width + 1],
      [0, 1, width, width + 1],
      [0, 1, width, width + 1]
    ];

    const iTetromino = [
      [1, width + 1, width * 2 + 1, width * 3 + 1],
      [width, width + 1, width + 2, width + 3],
      [1, width + 1, width * 2 + 1, width * 3 + 1],
      [width, width + 1, width + 2, width + 3]
    ];

    const theTetrominoes = [lTetromino, zTetromino, tTetromino, oTetromino, iTetromino];

    let currentPosition = 4;
    let currentRotation = 0;

    // randomly select a Tetromino and its first rotation
    let random = Math.floor(Math.random() * theTetrominoes.length);
    let current = theTetrominoes[random][currentRotation];

    // draw the Tetromino
    function draw() {
      current.forEach(index => {
        if (squares[currentPosition + index]) {
          squares[currentPosition + index].classList.add('tetromino');
        }
      });
    }

    // undraw the Tetromino
    function undraw() {
      current.forEach(index => {
        if (squares[currentPosition + index]) {
          squares[currentPosition + index].classList.remove('tetromino');
        }
      });
    }

    // move down function
    function moveDown() {
      undraw();
      currentPosition += width;
      draw();
      freeze();
    }

    // freeze function
    function freeze() {
      if (current.some(index => (currentPosition + index + width) >= 210 || squares[currentPosition + index + width].classList.contains('taken'))) {
        current.forEach(index => squares[currentPosition + index].classList.add('taken'));
        // start a new Tetromino falling
        random = nextRandom;
        nextRandom = Math.floor(Math.random() * theTetrominoes.length);
        current = theTetrominoes[random][currentRotation];
        currentPosition = 4;
        draw();
        addScore();
        gameOver();
        increaseSpeed();
      }
    }

    // move the Tetromino left, unless is at the edge or there is a blockage
    function moveLeft() {
      undraw();
      const isAtLeftEdge = current.some(index => (currentPosition + index) % width === 0);
      if (!isAtLeftEdge) currentPosition -= 1;
      if (current.some(index => squares[currentPosition + index]?.classList.contains('taken'))) {
        currentPosition += 1;
      }
      draw();
    }

    // move the Tetromino right, unless is at the edge or there is a blockage
    function moveRight() {
      undraw();
      const isAtRightEdge = current.some(index => (currentPosition + index) % width === width - 1);
      if (!isAtRightEdge) currentPosition += 1;
      if (current.some(index => squares[currentPosition + index]?.classList.contains('taken'))) {
        currentPosition -= 1;
      }
      draw();
    }

    // rotate the Tetromino
    function rotate() {
      undraw();
      currentRotation++;
      if (currentRotation === current.length) { // if currentRotation gets to 4, make it go back to 0
        currentRotation = 0;
      }
      current = theTetrominoes[random][currentRotation];
      draw();
    }

    // move down quickly
    function moveDownQuickly() {
      undraw();
      while (!current.some(index => (currentPosition + index + width) >= 210 || squares[currentPosition + index + width].classList.contains('taken'))) {
        currentPosition += width;
      }
      draw();
      freeze();
    }

    // add functionality to the button
    document.addEventListener('keydown', control);

    function control(e) {
      if (e.key === 'a' || e.key === 'A') {
        moveLeft();
      } else if (e.key === 'w' || e.key === 'W') {
        rotate();
      } else if (e.key === 'd' || e.key === 'D') {
        moveRight();
      } else if (e.key === 's' || e.key === 'S') {
        moveDownQuickly();
      }
    }

    function startGame() {
      draw();
      timerId = setInterval(moveDown, dropSpeed);
      nextRandom = Math.floor(Math.random() * theTetrominoes.length);
    }

    function pauseGame() {
      if (timerId) {
        clearInterval(timerId);
        timerId = null;
      }
    }

    function resetGame() {
      pauseGame();
      squares.forEach(square => {
        square.classList.remove('tetromino');
        square.classList.remove('taken');
      });
      currentPosition = 4;
      currentRotation = 0;
      random = Math.floor(Math.random() * theTetrominoes.length);
      current = theTetrominoes[random][currentRotation];
      score = 0;
      dropSpeed = 1000;
      document.getElementById('score').innerText = score;
      draw();
      startGame();
    }

    function addScore() {
      for (let i = 0; i < 210; i += width) {
        const row = [i, i + 1, i + 2, i + 3, i + 4, i + 5, i + 6, i + 7, i + 8, i + 9];

        if (row.every(index => squares[index].classList.contains('taken'))) {
          score += 10;
          document.getElementById('score').innerText = score;
          row.forEach(index => {
            squares[index].classList.remove('taken');
            squares[index].classList.remove('tetromino');
          });
          const squaresRemoved = squares.splice(i, width);
          squares = squaresRemoved.concat(squares);
          squares.forEach(cell => grid.appendChild(cell));
        }
      }
    }

    function increaseSpeed() {
      if (score % 50 === 0) {
        dropSpeed *= 0.9;
        clearInterval(timerId);
        timerId = setInterval(moveDown, dropSpeed);
      }
    }

    function gameOver() {
      if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
        document.getElementById('score').innerText = 'Game Over';
        clearInterval(timerId);
      }
    }

    window.startGame = startGame;
    window.pauseGame = pauseGame;
    window.resetGame = resetGame;
  });
</script>
</body>
</html>
728x90
반응형