Tetris played by AI. fullscreen on iPhone. Use only shapes, no images.
Tetris AI Game
<html>
<head>
<title>Tetris AI Game</title>
<style>
body {
background-color: black;
}
#game-board {
width: 100vw;
height: 100vh;
display: flex;
flex-wrap: wrap;
border: 2px solid grey;
background-color: #212121;
}
.grid {
width: calc(10vw);
height: calc(10vw);
border: 1px solid grey;
}
.game-over {
font-family: Arial, sans-serif;
font-size: 50px;
color: red;
margin-top: 30vh;
text-align: center;
}
</style>
</head>
<body>
<div id="game-board"></div>
<script>
// Game Board
const BOARD_WIDTH = 20;
const BOARD_HEIGHT = 30;
const GRID_SIZE = 10;
const shapes = [
{ color: "red", cells: [[0,0], [0,1], [1,1], [1,0]] }, // square
{ color: "green", cells: [[0,0], [1,0], [2,0], [3,0]] }, // line
{ color: "yellow", cells: [[0,0], [1,0], [2,0], [2,1]] }, // l-shape
{ color: "blue", cells: [[0,1], [1,1], [2,1], [2,0]] }, // j-shape
{ color: "purple", cells: [[0,1], [1,0], [1,1], [2,1]] }, // z-shape
{ color: "orange", cells: [[0,0], [1,0], [1,1], [2,1]] }, // s-shape
{ color: "grey", cells: [[0,0], [1,0], [2,0], [1,1]] } // t-shape
];
// Game Board Initialization
const board = new Array(BOARD_HEIGHT).fill().map(() => new Array(BOARD_WIDTH).fill(0));
let currentShape = getRandomShape();
let gameInterval = setInterval(() => { moveShape(1, 0) }, 500);
let isGameOver = false;
const gameBoard = document.getElementById("game-board");
for (let row = 0; row < BOARD_HEIGHT; row++) {
for (let col = 0; col < BOARD_WIDTH; col++) {
const grid = document.createElement("div");
grid.classList.add("grid");
gameBoard.appendChild(grid);
}
}
renderBoard();
renderShape(currentShape);
// Movement Functions
function moveShape(rowOffset, colOffset) {
if (isGameOver || !canMove(rowOffset, colOffset)) return;
clearShape(currentShape);
currentShape.row += rowOffset;
currentShape.col += colOffset;
renderShape(currentShape);
if (!canMove(1, 0)) {
stopShape();
const fullRows = getFullRows();
if (fullRows.length > 0) {
removeRows(fullRows);
}
currentShape = getRandomShape();
if (!canMove(0, 0)) {
gameover();
}
renderShape(currentShape);
}
}
// Shape Functions
function getRandomShape() {
const shape = shapes[Math.floor(Math.random() * shapes.length)];
return {
row: 0,
col: Math.floor(BOARD_WIDTH / 2) - 1,
...shape
};
}
function renderShape(shape) {
shape.cells.forEach(([row, col]) => {
const grid = getGrid(shape.row + row, shape.col + col);
if (grid) {
grid.style.backgroundColor = shape.color;
}
});
}
function clearShape(shape) {
shape.cells.forEach(([row, col]) => {
const grid = getGrid(shape.row + row, shape.col + col);
if (grid) {
grid.style.backgroundColor = null;
}
});
}
function stopShape() {
currentShape.cells.forEach(([row, col]) => {
const grid = getGrid(currentShape.row + row, currentShape.col + col);
if (grid) {
grid.classList.add("locked");
}
});
}
function getFullRows() {
const fullRows = [];
for (let row = 0; row < BOARD_HEIGHT; row++) {
if (board[row].every(cell => cell === 1)) {
fullRows.push(row);
}
}
return fullRows;
}
function removeRows(fullRows) {
for (let row of fullRows) {
board.splice(row, 1);
board.unshift(new Array(BOARD_WIDTH).fill(0));
}
renderBoard();
}
function canMove(rowOffset, colOffset) {
return currentShape.cells.every(([row, col]) => {
const newRow = currentShape.row + row + rowOffset;
const newCol = currentShape.col + col + colOffset;
return newRow >= 0 && newRow < BOARD_HEIGHT &&
newCol >= 0 && newCol < BOARD_WIDTH &&
board[newRow][newCol] === 0;
});
}
// Board Functions
function getGrid(row, col) {
if (row >= 0 && row < BOARD_HEIGHT && col >= 0 && col < BOARD_WIDTH) {
return gameBoard.children[row * BOARD_WIDTH + col];
}
return null;
}
function renderBoard() {
for (let row = 0; row < BOARD_HEIGHT; row++) {
for (let col = 0; col < BOARD_WIDTH; col++) {
const grid = getGrid(row, col);
if (board[row][col] === 0) {
grid.style.backgroundColor = null;
grid.classList.remove("locked");
} else {
grid.style.backgroundColor = "grey";
grid.classList.add("locked");
}
}
}
}
function gameover() {
clearInterval(gameInterval);
isGameOver = true;
const gameOverText = document.createElement("div");
gameOverText.innerText = "Game Over! AI was outsmarted!";
gameOverText.classList.add("game-over");
gameBoard.appendChild(gameOverText);
}
document.addEventListener("keydown", event => {
if (event.key === "ArrowLeft") {
moveShape(0, -1);
} else if (event.key === "ArrowRight") {
moveShape(0, 1);
} else if (event.key === "ArrowDown") {
moveShape(1, 0);
} else if (event.key === "ArrowUp") {
currentShape.cells = [...currentShape.cells.map(([row, col]) => [-col, row])];
if (!canMove(0, 0)) {
currentShape.cells = [...currentShape.cells.map(([row, col]) => [col, -row])];
}
clearShape(currentShape);
renderShape(currentShape);
}
});
</script>
</body>
</html>
<!-- Why did the computer go to the dentist? To get its byte checked! -->