Game Susun Angka Informatika
<html>
<head>
<title>Materi Coding Game Informatika</title>
<style>
body {
margin: 0 auto;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
color: #444;
}
.container {
width: 100%;
height: 100vh;
background-color: #55e0c0;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.grid-container {
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
height: 100%;
margin: 0 2rem;
}
.grid-container h1 {
color: #444444;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 3px;
}
.grid {
width: 320px;
height: 320px;
overflow: auto;
background-color: #6aceb7;
border-radius: 0.5rem;
position: relative;
}
.cell {
width: 80px;
height: 80px;
position: absolute;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
transition: all ease 0.3s;
border-radius: 0.5rem;
margin: 8px;
background-color: #ffffff;
font-size: 2rem;
font-weight: 600;
color: #666666;
box-shadow: 2px 2px 5px 0px #16735e;
user-select: none;
}
.cell:hover {
color: #222222;
}
.empty-cell {
background-color: #33bf9f;
pointer-events: none;
}
.empty-cell:hover {
background-color: #0ca985;
}
.error-cell {
background-color: red;
}
.left-container,
.right-container {
height: 100%;
flex: 1;
}
.overlay-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.8);
z-index: 100;
display: flex;
justify-content: center;
align-items: center;
}
.overlay-content {
min-width: 300px;
width: 90%;
max-width: 450px;
background-color: #22d2a9;
color: #055241;
border-radius: 5px;
padding: 1rem;
text-align: center;
}
.overlay-content .title {
font-size: 1.6rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 2px;
}
.overlay-content .subtitle {
font-size: 1.1rem;
font-weight: 500;
letter-spacing: 1px;
}
.moves {
margin: 1rem auto;
text-align: center;
}
.move {
margin: 1em 0.8rem;
padding: 0.7rem 1.6rem;
border-radius: 0.5rem;
outline: none;
border: 2px solid transparent;
background-color: rgba(0, 0, 0, 0);
color: #16735e;
font-size: 1.2rem;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.move:hover,
.move:active {
border-color: #33bf9f;
}
.move-selected {
border-color: #16735e !important;
color: #055241;
}
.game-btn {
border: none;
outline: none;
margin: 1rem 0;
padding: 0.6rem 1.5rem;
border-radius: 0.5rem;
background-color: #e5e5e5;
color: #015240;
cursor: pointer;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 2px;
font-size: 1.2rem;
box-shadow: 3px 3px 0px 0px #16735e, 0px 0px 5px 0px #00000042;
}
.game-btn:hover {
background-color: #ffffff;
}
.game-btn:active {
box-shadow: 0px 0px 0px 0px #16735e;
transform: translateY(4px);
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div class="container">
<div class="left-container">
<!-- TODO: Undo, redo, new game feature -->
</div>
<div class="grid-container">
<h5> Informatika MAN Kapuas Susun Angka </h1>
<div class="grid start" id="gridStart"> </div>
<!-- TODO: Add diffucilty level -->
</div>
<div class="right-container">
<!-- TODO: show move log -->
</div>
<!-- Popup for new game -->
<div class="overlay-container hidden" id="newGameContainer">
<div id="new-game" class="overlay-content">
<div class="title"> Permainan Baru </div>
<div class="subtitle">Pilih Ukuran Kotak</div>
<div class="moves">
<button class="move move-selected" value="3"> 3 x 3</button>
<button class="move" value="4"> 4 x 4 </button>
<button class="move" value="5"> 5 x 5 </button>
</div>
<button class="game-btn" id="startGameBtn">Main</button>
</div>
</div>
<div class="overlay-container hidden" id="gameOverContainer">
<div class="overlay-content">
<div class="title"> Selamat Kamu Menang </div>
<div class="subtitle"> Ingin Main Kembali? </div>
<div>
<!-- Show statistics here, like time, moves etc -->
</div>
<button class="game-btn" id="playAgainBtn">Main Lagi</button>
</div>
</div>
</div>
<script>
const CELL_SIZE = 80;
const GRID_HEIGHT = 4;
const GRID_WIDTH = 4;
let gridSize = 3;
let gridState = [
[1, 2, 3],
[4, 5, 6],
[7, 0, 8]
];
let winState = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 0]
];
isMoveAllowed = (cellPosition, emptyPosition) => {
const [cellX, cellY] = cellPosition;
const [emptyX, emptyY] = emptyPosition;
return (
(Math.abs(cellX - emptyX) === 1 && Math.abs(cellY - emptyY) === 0) ||
(Math.abs(cellX - emptyX) === 0 && Math.abs(cellY - emptyY) === 1)
);
};
checkForWin = (_) => {
const win = JSON.stringify(winState) === JSON.stringify(gridState);
if (win) {
showGameOverScreen();
}
};
showGameOverScreen = (_) => {
const gameOverContainer = document.getElementById("gameOverContainer");
gameOverContainer.classList.remove("hidden");
};
showNewGameScreen = (_) => {
const gameOverContainer = document.getElementById("gameOverContainer");
gameOverContainer.classList.add("hidden");
const newGameContainer = document.getElementById("newGameContainer");
newGameContainer.classList.remove("hidden");
};
moveTile = (event) => {
const emptyTile = document.querySelector(".empty-cell");
const [emptyX, emptyY] = emptyTile.getAttribute("data-pos").split(",");
const cellTile = event.target;
const [cellX, cellY] = cellTile.getAttribute("data-pos").split(",");
// Check if move is allowed
if (isMoveAllowed([cellX, cellY], [emptyX, emptyY])) {
cellTile.style.top = emptyX * CELL_SIZE + "px";
cellTile.style.left = emptyY * CELL_SIZE + "px";
cellTile.setAttribute("data-pos", `${emptyX},${emptyY}`);
gridState[cellX][cellY] = 0;
emptyTile.style.top = `${cellX * CELL_SIZE}px`;
emptyTile.style.left = `${cellY * CELL_SIZE}px`;
emptyTile.setAttribute("data-pos", `${cellX},${cellY}`);
gridState[emptyX][emptyY] = parseInt(cellTile.textContent);
checkForWin();
}
};
createGameState = (gridSize) => {
// Fill win state array
winState = [];
let k = 1;
for (let i = 0; i < gridSize; i++) {
winState[i] = [];
for (let j = 0; j < gridSize; j++) {
winState[i][j] = k;
k++;
}
}
winState[gridSize - 1][gridSize - 1] = 0;
console.log("wins state", winState);
// create an array
const valueArray = [];
for (let i = 1; i < gridSize * gridSize; i++) {
valueArray.push(i);
}
valueArray.push(0);
// create gridState array
let tempState = [];
for (let i = 0; i < gridSize; i++) {
tempState[i] = [];
for (j = 0; j < gridSize; j++) {
const randIndex = Math.floor(Math.random() * valueArray.length);
tempState[i][j] = valueArray[randIndex] ? valueArray[randIndex] : 0;
valueArray.splice(randIndex, 1);
}
}
gridState = [...tempState];
console.log("game state", gridState);
};
createGrid = (gridSize) => {
const gridStart = document.getElementById("gridStart");
gridStart.style.height = gridSize * CELL_SIZE + 8 + "px";
gridStart.style.width = gridSize * CELL_SIZE + 8 + "px";
gridStart.innerHTML = "";
for (let i = 0; i < gridSize; i++) {
for (let j = 0; j < gridSize; j++) {
const cell = document.createElement("div");
cell.className = gridState[i][j] ? "cell" : "cell empty-cell";
cell.textContent = gridState[i][j] ? gridState[i][j] : "";
cell.style.height = CELL_SIZE - 8 + "px";
cell.style.width = CELL_SIZE - 8 + "px";
cell.style.top = `${i * CELL_SIZE}px`;
cell.style.left = `${j * CELL_SIZE}px`;
cell.style.position = "absolute";
cell.setAttribute("data-pos", `${i},${j}`);
cell.addEventListener("click", moveTile);
gridStart.appendChild(cell);
}
}
};
startNewGame = (_) => {
createGameState(gridSize);
createGrid(gridSize);
const newGameContainer = document.getElementById("newGameContainer");
newGameContainer.classList.add("hidden");
};
((_) => {
const startGameBtn = document.getElementById("startGameBtn");
startGameBtn.addEventListener("click", startNewGame);
const playAgainBtn = document.getElementById("playAgainBtn");
playAgainBtn.addEventListener("click", showNewGameScreen);
const moves = document.querySelectorAll(".move");
moves.forEach((move) => {
move.addEventListener("click", () => {
gridSize = move.value;
document.querySelector(".move-selected").classList.remove("move-selected");
move.classList.add("move-selected");
});
});
// startNewGame();
createGrid(gridSize);
})();
</scrip>
</body>
</html>
0 komentar: