Free friday assigment 5/22/2026

Hello, so today i Use some Ai and I made a block blast.

here is the index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Block Blast Clone</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>

  <h1>Block Blast Clone</h1>

  <div id="info">
    Score: <span id="score">0</span>
  </div>

  <div id="game">
    <div id="board"></div>

    <div>
      <div id="pieces"></div>
      <button id="newPiecesBtn">New Pieces</button>
    </div>
  </div>

  <script>
    const BOARD_SIZE = 10;
    const boardEl = document.getElementById('board');
    const piecesEl = document.getElementById('pieces');
    const scoreEl = document.getElementById('score');
    const newPiecesBtn = document.getElementById('newPiecesBtn');

    let board = [];
    let score = 0;
    let currentPieces = [];
    let draggedPiece = null;

    const SHAPES = [
      [[0,0]],
      [[0,0],[0,1]],
      [[0,0],[1,0]],
      [[0,0],[0,1],[0,2]],
      [[0,0],[1,0],[2,0]],
      [[0,0],[0,1],[1,0],[1,1]],
      [[0,0],[1,0],[1,1]],
      [[0,1],[1,0],[1,1],[1,2]]
    ];

    function initBoard() {
      board = [];
      boardEl.innerHTML = '';
      for (let r = 0; r < BOARD_SIZE; r++) {
        const row = [];
        for (let c = 0; c < BOARD_SIZE; c++) {
          row.push(0);
          const cell = document.createElement('div');
          cell.className = 'cell';
          cell.dataset.row = r;
          cell.dataset.col = c;

          // Allow dropping
          cell.addEventListener('dragover', e => e.preventDefault());
          cell.addEventListener('drop', e => handleDrop(r, c));

          boardEl.appendChild(cell);
        }
        board.push(row);
      }
      updateBoardUI();
    }

    function updateBoardUI() {
      const cells = boardEl.querySelectorAll('.cell');
      cells.forEach(cell => {
        const r = parseInt(cell.dataset.row, 10);
        const c = parseInt(cell.dataset.col, 10);
        cell.classList.toggle('filled', board[r][c] === 1);
      });
      scoreEl.textContent = score;
    }

    function randomPiece() {
      const shape = SHAPES[Math.floor(Math.random() * SHAPES.length)];
      return { shape };
    }

    function generatePieces() {
      currentPieces = [randomPiece(), randomPiece(), randomPiece()];
      renderPieces();
    }

    function renderPieces() {
      piecesEl.innerHTML = '';
      currentPieces.forEach((piece, index) => {
        if (!piece) return;

        const { shape } = piece;
        const rows = Math.max(...shape.map(p => p[0])) + 1;
        const cols = Math.max(...shape.map(p => p[1])) + 1;

        const pieceDiv = document.createElement('div');
        pieceDiv.className = 'piece';
        pieceDiv.style.gridTemplateColumns = `repeat(${cols}, 20px)`;
        pieceDiv.style.gridTemplateRows = `repeat(${rows}, 20px)`;

        // Enable dragging
        pieceDiv.draggable = true;
        pieceDiv.addEventListener('dragstart', () => {
          draggedPiece = { piece, index };
        });

        for (let r = 0; r < rows; r++) {
          for (let c = 0; c < cols; c++) {
            const cellDiv = document.createElement('div');
            const isFilled = shape.some(p => p[0] === r && p[1] === c);
            if (isFilled) {
              cellDiv.className = 'piece-cell';
            } else {
              cellDiv.style.width = '20px';
              cellDiv.style.height = '20px';
            }
            pieceDiv.appendChild(cellDiv);
          }
        }

        piecesEl.appendChild(pieceDiv);
      });
    }

    function canPlacePiece(piece, baseRow, baseCol) {
      for (const [dr, dc] of piece.shape) {
        const r = baseRow + dr;
        const c = baseCol + dc;
        if (r < 0 || r >= BOARD_SIZE || c < 0 || c >= BOARD_SIZE) return false;
        if (board[r][c] === 1) return false;
      }
      return true;
    }

    function placePiece(piece, baseRow, baseCol) {
      for (const [dr, dc] of piece.shape) {
        const r = baseRow + dr;
        const c = baseCol + dc;
        board[r][c] = 1;
      }
      clearLines();
      score += piece.shape.length;
      updateBoardUI();
    }

    function clearLines() {
      let cleared = 0;

      for (let r = 0; r < BOARD_SIZE; r++) {
        if (board[r].every(cell => cell === 1)) {
          cleared++;
          for (let c = 0; c < BOARD_SIZE; c++) board[r][c] = 0;
        }
      }

      for (let c = 0; c < BOARD_SIZE; c++) {
        let full = true;
        for (let r = 0; r < BOARD_SIZE; r++) {
          if (board[r][c] === 0) full = false;
        }
        if (full) {
          cleared++;
          for (let r = 0; r < BOARD_SIZE; r++) board[r][c] = 0;
        }
      }

      if (cleared > 0) score += cleared * 10;
    }

    function handleDrop(row, col) {
      if (!draggedPiece) return;

      const { piece, index } = draggedPiece;

      if (canPlacePiece(piece, row, col)) {
        placePiece(piece, row, col);
        currentPieces[index] = null;
        renderPieces();
      }

      draggedPiece = null;
    }

    newPiecesBtn.addEventListener('click', () => {
      generatePieces();
    });

    initBoard();
    generatePieces();
  </script>

</body>
</html>

here is the style.css

/* ===== General Page Styling ===== */
body {
  font-family: "Fredoka One", Arial, sans-serif;
  background: linear-gradient(135deg, #ffecd2, #fcb69f);
  color: #333;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 0;
  padding: 20px;
}

h1 {
  font-size: 42px;
  color: #ff6f61;
  text-shadow: 3px 3px #ffffff;
  margin-bottom: 10px;
}

/* ===== Game Layout ===== */
#game {
  display: flex;
  gap: 30px;
  margin-top: 10px;
}

#info {
  margin-top: 10px;
  font-size: 22px;
  font-weight: bold;
  color: #ff6f61;
}

/* ===== Board Styling ===== */
#board {
  display: grid;
  grid-template-columns: repeat(10, 40px);
  grid-template-rows: repeat(10, 40px);
  gap: 4px;
  background: #ffe6d9;
  padding: 10px;
  border-radius: 20px;
  box-shadow: 0 8px 20px rgba(0,0,0,0.15);
}

.cell {
  width: 40px;
  height: 40px;
  background: #ffd1b3;
  border-radius: 10px;
  transition: background 0.2s, transform 0.2s;
}

.cell.filled {
  background: #ff8b3d;
  animation: pop 0.25s ease-out;
}

/* Ghost preview */
.cell.ghost {
  background: rgba(255, 255, 255, 0.5);
  border: 2px dashed #ff8b3d;
}

/* ===== Pieces Section ===== */
#pieces {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.piece {
  display: inline-grid;
  gap: 4px;
  background: #ffe6d9;
  padding: 10px;
  border-radius: 16px;
  cursor: grab;
  transition: transform 0.2s, box-shadow 0.2s;
  box-shadow: 0 6px 12px rgba(0,0,0,0.15);
}

.piece:hover {
  transform: scale(1.08);
}

.piece:active {
  transform: scale(1.15);
  box-shadow: 0 0 20px #ff8b3d;
}

.piece-cell {
  width: 28px;
  height: 28px;
  background: #ff6f61;
  border-radius: 8px;
  box-shadow: inset 0 4px 6px rgba(255,255,255,0.6),
              inset 0 -4px 6px rgba(0,0,0,0.15);
}

/* ===== Buttons ===== */
button {
  margin-top: 10px;
  padding: 10px 18px;
  border-radius: 12px;
  border: none;
  cursor: pointer;
  background: #ff6f61;
  color: #fff;
  font-weight: bold;
  font-size: 18px;
  box-shadow: 0 6px 12px rgba(0,0,0,0.15);
  transition: background 0.2s, transform 0.2s;
}

button:hover {
  background: #ff8b3d;
  transform: scale(1.05);
}

/* ===== Animations ===== */
@keyframes pop {
  0% { transform: scale(0.6); }
  60% { transform: scale(1.25); }
  100% { transform: scale(1); }
}

here u can see how its look like

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top