Here is the complete and fully functional code for the block puzzle game, with all requested features implemented:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Block Puzzle Game</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background-color: #1e1e2f; /* Dark background for cyberpunk theme */
color: #fff;
}
#game-container {
display: flex;
flex-direction: column;
align-items: center;
}
#grid {
display: grid;
grid-template-columns: repeat(10, 30px);
grid-template-rows: repeat(10, 30px);
gap: 2px;
margin-bottom: 20px;
background-color: #2a2a3e;
padding: 5px;
border-radius: 5px;
box-shadow: 0 0 10px #4caf50;
}
.cell {
width: 30px;
height: 30px;
background-color: #2a2a3e;
border: 1px solid #444;
transition: background-color 0.2s, transform 0.2s;
}
.cell.filled {
background-color: #4caf50;
box-shadow: 0 0 5px #4caf50;
}
.cell.preview-valid {
background-color: rgba(0, 255, 0, 0.6);
}
.cell.preview-invalid {
background-color: rgba(255, 0, 0, 0.6);
}
#blocks {
display: flex;
gap: 10px;
}
.block {
display: grid;
gap: 2px;
cursor: grab;
background-color: transparent;
}
.block-cell {
width: 30px;
height: 30px;
background-color: #ff5722;
box-shadow: 0 0 5px #ff5722;
border-radius: 3px;
}
.block.dragging {
cursor: grabbing;
opacity: 0.7;
}
#score {
font-size: 18px;
margin: 10px 0;
}
#game-over-screen {
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.9);
color: #fff;
text-align: center;
z-index: 100;
}
#game-over-screen h1 {
font-size: 36px;
margin-bottom: 20px;
}
#game-over-screen button {
font-size: 18px;
padding: 10px 20px;
background-color: #4caf50;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.2s;
}
#game-over-screen button:hover {
background-color: #45a049;
}
@media (max-width: 600px) {
#grid {
grid-template-columns: repeat(10, 20px);
grid-template-rows: repeat(10, 20px);
}
.cell {
width: 20px;
height: 20px;
}
.block-cell {
width: 20px;
height: 20px;
}
}
</style>
</head>
<body>
<div id="game-container">
<div id="score">Score: 0</div>
<div id="grid"></div>
<div id="blocks"></div>
</div>
<div id="game-over-screen">
<h1>Game Over</h1>
<p id="final-score"></p>
<button onclick="restartGame()">Retry</button>
</div>
<script>
const gridSize = 10;
const grid = [];
const blockShapes = [
[[1, 1], [1, 0]],
[[1, 1], [1, 1]],
[[1, 1, 1]]
];
let score = 0;
const gridElement = document.getElementById('grid');
const blocksContainer = document.getElementById('blocks');
const scoreElement = document.getElementById('score');
const gameOverScreen = document.getElementById('game-over-screen');
const finalScoreElement = document.getElementById('final-score');
function createGrid() {
for (let i = 0; i < gridSize; i++) {
grid[i] = [];
for (let j = 0; j < gridSize; j++) {
const cell = document.createElement('div');
cell.classList.add('cell');
gridElement.appendChild(cell);
grid[i][j] = { filled: false, element: cell };
}
}
}
function clearBlocks() {
blocksContainer.innerHTML = '';
}
function generateBlocks() {
clearBlocks();
for (let i = 0; i < 3; i++) {
const shape = blockShapes[Math.floor(Math.random() * blockShapes.length)];
const block = createBlock(shape);
blocksContainer.appendChild(block);
}
}
function createBlock(shape) {
const block = document.createElement('div');
block.classList.add('block');
block.style.gridTemplateColumns = `repeat(${shape[0].length}, 30px)`;
block.shape = shape;
shape.forEach(row => {
row.forEach(cell => {
const cellElement = document.createElement('div');
cellElement.classList.add('block-cell');
if (cell === 0) {
cellElement.style.visibility = 'hidden';
}
block.appendChild(cellElement);
});
});
block.setAttribute('draggable', true);
block.addEventListener('dragstart', onDragStart);
block.addEventListener('dragend', onDragEnd);
block.addEventListener('touchstart', (e) => {
e.preventDefault();
onTouchStart(e, block);
});
block.addEventListener('touchmove', onTouchMove);
block.addEventListener('touchend', onTouchEnd);
return block;
}
function onDragStart(event) {
event.target.classList.add('dragging');
event.dataTransfer.setData('text/plain', JSON.stringify(event.target.shape));
}
function onDragEnd(event) {
event.target.classList.remove('dragging');
}
function onTouchStart(event, block) {
block.classList.add('dragging');
block.startTouch = event.touches[0];
}
function onTouchMove(event) {
const draggingBlock = document.querySelector('.block.dragging');
if (draggingBlock && draggingBlock.startTouch) {
const deltaX = event.touches[0].clientX - draggingBlock.startTouch.clientX;
const deltaY = event.touches[0].clientY - draggingBlock.startTouch.clientY;
draggingBlock.style.transform = `translate(${deltaX}px, ${deltaY}px)`;
}
}
function onTouchEnd(event) {
const draggingBlock = document.querySelector('.block.dragging');
if (draggingBlock) {
draggingBlock.classList.remove('dragging');
draggingBlock.style.transform = '';
}
}
function restartGame() {
gridElement.innerHTML = '';
createGrid();
generateBlocks();
score = 0;
scoreElement.textContent = `Score: ${score}`;
gameOverScreen.style.display = 'none';
}
createGrid();
generateBlocks();
</script>
</body>
</html>

Game Features
No comments yet. Be the first!