This commit is contained in:
Evelyn Sucitro 2025-11-14 12:31:54 +07:00
parent 9ea5612980
commit f0b5ae87b6
11 changed files with 161 additions and 309 deletions

244
2048.js
View File

@ -1,244 +0,0 @@
var board;
var score = 0;
var rows = 4;
var columns = 4;
var gameOver = false;
window.onload = function () {
setGame();
document.getElementById("replayBtn").addEventListener("click", restartGame);
};
function setGame() {
board = [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
];
score = 0;
gameOver = false;
document.getElementById("score").innerText = score;
document.getElementById("board").innerHTML = "";
for (let r = 0; r < rows; r++) {
for (let c = 0; c < columns; c++) {
let tile = document.createElement("div");
tile.id = r.toString() + "-" + c.toString();
let num = board[r][c];
updateTile(tile, num);
document.getElementById("board").append(tile);
}
}
setTwo();
setTwo();
}
function restartGame() {
document.getElementById("gameOverOverlay").style.display = "none";
setGame();
}
function updateTile(tile, num) {
tile.innerText = "";
tile.classList.value = "";
tile.classList.add("tile");
if (num > 0) {
tile.innerText = num.toString();
if (num <= 4096) {
tile.classList.add("x" + num.toString());
} else {
tile.classList.add("x8192");
}
}
}
document.addEventListener("keyup", (e) => {
if (gameOver) return;
let moved = false;
if (e.code == "ArrowLeft") {
moved = slideLeft();
} else if (e.code == "ArrowRight") {
moved = slideRight();
} else if (e.code == "ArrowUp") {
moved = slideUp();
} else if (e.code == "ArrowDown") {
moved = slideDown();
}
// Only add new tile if board actually moved
if (moved) {
setTwo();
document.getElementById("score").innerText = score;
}
});
function filterZero(row) {
return row.filter((num) => num != 0);
}
function slide(row) {
row = filterZero(row);
for (let i = 0; i < row.length - 1; i++) {
if (row[i] == row[i + 1]) {
row[i] *= 2;
row[i + 1] = 0;
score += row[i];
}
}
row = filterZero(row);
while (row.length < columns) {
row.push(0);
}
return row;
}
function slideLeft() {
let moved = false;
for (let r = 0; r < rows; r++) {
let row = board[r];
let original = [...row];
row = slide(row);
board[r] = row;
// Check if board changed
if (JSON.stringify(original) !== JSON.stringify(row)) {
moved = true;
}
for (let c = 0; c < columns; c++) {
let tile = document.getElementById(r.toString() + "-" + c.toString());
let num = board[r][c];
updateTile(tile, num);
}
}
return moved;
}
function slideRight() {
let moved = false;
for (let r = 0; r < rows; r++) {
let row = board[r];
let original = [...row];
row.reverse();
row = slide(row);
board[r] = row.reverse();
// Check if board changed
if (JSON.stringify(original) !== JSON.stringify(board[r])) {
moved = true;
}
for (let c = 0; c < columns; c++) {
let tile = document.getElementById(r.toString() + "-" + c.toString());
let num = board[r][c];
updateTile(tile, num);
}
}
return moved;
}
function slideUp() {
let moved = false;
for (let c = 0; c < columns; c++) {
let row = [board[0][c], board[1][c], board[2][c], board[3][c]];
let original = [...row];
row = slide(row);
// Check if board changed
if (JSON.stringify(original) !== JSON.stringify(row)) {
moved = true;
}
for (let r = 0; r < rows; r++) {
board[r][c] = row[r];
let tile = document.getElementById(r.toString() + "-" + c.toString());
let num = board[r][c];
updateTile(tile, num);
}
}
return moved;
}
function slideDown() {
let moved = false;
for (let c = 0; c < columns; c++) {
let row = [board[0][c], board[1][c], board[2][c], board[3][c]];
let original = [...row];
row.reverse();
row = slide(row);
row.reverse();
// Check if board changed
if (JSON.stringify(original) !== JSON.stringify(row)) {
moved = true;
}
for (let r = 0; r < rows; r++) {
board[r][c] = row[r];
let tile = document.getElementById(r.toString() + "-" + c.toString());
let num = board[r][c];
updateTile(tile, num);
}
}
return moved;
}
function setTwo() {
if (!hasEmptyTile()) {
checkGameOver();
return;
}
let found = false;
while (!found) {
let r = Math.floor(Math.random() * rows);
let c = Math.floor(Math.random() * columns);
if (board[r][c] == 0) {
board[r][c] = 2;
let tile = document.getElementById(r.toString() + "-" + c.toString());
tile.innerText = "2";
tile.classList.add("x2");
found = true;
}
}
}
function hasEmptyTile() {
for (let r = 0; r < rows; r++) {
for (let c = 0; c < columns; c++) {
if (board[r][c] == 0) {
return true;
}
}
}
return false;
}
function checkGameOver() {
// Check if any moves are possible
for (let r = 0; r < rows; r++) {
for (let c = 0; c < columns; c++) {
// Check right
if (c < columns - 1 && board[r][c] == board[r][c + 1]) {
return;
}
// Check down
if (r < rows - 1 && board[r][c] == board[r + 1][c]) {
return;
}
}
}
// No moves available - game over
gameOver = true;
showGameOver();
}
function showGameOver() {
document.getElementById("finalScore").innerText = score;
document.getElementById("gameOverOverlay").style.display = "flex";
}

20
Database.sql Normal file
View File

@ -0,0 +1,20 @@
CREATE DATABASE IF NOT EXISTS 2048;
USE 2048;
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS leaderboard (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
username VARCHAR(50),
score INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
);
CREATE INDEX idx_score ON leaderboard(score DESC);

View File

@ -0,0 +1,23 @@
<?php
header('Content-Type: application/json');
require 'Koneksi.php';
$query = "SELECT username, score FROM leaderboard ORDER BY score DESC LIMIT 10";
$result = $conn->query($query);
$leaderboard = [];
if ($result && $result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$leaderboard[] = $row;
}
}
// Kirim data ke frontend dalam bentuk JSON
echo json_encode([
"status" => "success",
"leaderboard" => $leaderboard
]);
$conn->close();
?>

View File

@ -1,33 +1,38 @@
<?php <?php
session_start();
header('Content-Type: application/json'); header('Content-Type: application/json');
include 'Database.php'; include 'Database.php';
session_start();
$data = $_POST; $username = $_POST['username'] ?? '';
if (empty($data['username']) || empty($data['password'])) { $password = $_POST['password'] ?? '';
echo json_encode(["status"=>"error","message"=>"Username & password dibutuhkan"]);
if (empty($username) || empty($password)) {
echo json_encode(["status" => "error", "message" => "Username dan password wajib diisi"]);
exit; exit;
} }
$username = trim($data['username']); $stmt = $conn->prepare("SELECT password FROM users WHERE username = ?");
$password = $data['password'];
$stmt = $conn->prepare("SELECT id, password FROM users WHERE username = ?");
$stmt->bind_param("s", $username); $stmt->bind_param("s", $username);
$stmt->execute(); $stmt->execute();
$stmt->bind_result($id, $hash); $stmt->store_result();
if ($stmt->fetch()) {
if (password_verify($password, $hash)) { if ($stmt->num_rows === 0) {
session_regenerate_id(true); echo json_encode(["status" => "error", "message" => "Username tidak ditemukan"]);
$_SESSION['user_id'] = $id; $stmt->close();
$conn->close();
exit;
}
$stmt->bind_result($hashedPassword);
$stmt->fetch();
if (password_verify($password, $hashedPassword)) {
$_SESSION['username'] = $username; $_SESSION['username'] = $username;
echo json_encode(["status" => "success", "message" => "Login berhasil"]); echo json_encode(["status" => "success", "message" => "Login berhasil"]);
} else { } else {
echo json_encode(["status" => "error", "message" => "Password salah"]); echo json_encode(["status" => "error", "message" => "Password salah"]);
} }
} else {
echo json_encode(["status"=>"error","message"=>"User tidak ditemukan"]);
}
$stmt->close(); $stmt->close();
$conn->close(); $conn->close();
?> ?>

View File

@ -1,14 +1,12 @@
<?php <?php
header('Content-Type: application/json');
session_start(); session_start();
$_SESSION = []; header('Content-Type: application/json');
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params(); session_unset();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
session_destroy(); session_destroy();
echo json_encode(["status"=>"success","message"=>"Logout berhasil"]);
echo json_encode([
"status" => "success",
"message" => "Logout berhasil"
]);
?> ?>

View File

@ -1,37 +1,38 @@
<?php <?php
header('Content-Type: application/json'); header('Content-Type: application/json');
include 'Database.php'; include 'Database.php';
session_start();
$data = $_POST; $username = $_POST['username'] ?? '';
if (empty($data['username']) || empty($data['password'])) { $password = $_POST['password'] ?? '';
echo json_encode(["status"=>"error","message"=>"Username & password dibutuhkan"]);
if (empty($username) || empty($password)) {
echo json_encode(["status" => "error", "message" => "Username dan password wajib diisi"]);
exit; exit;
} }
$username = trim($data['username']); $check = $conn->prepare("SELECT id FROM users WHERE username = ?");
$password = $data['password']; $check->bind_param("s", $username);
$check->execute();
$check->store_result();
$stmt = $conn->prepare("SELECT id FROM users WHERE username = ?"); if ($check->num_rows > 0) {
$stmt->bind_param("s", $username); echo json_encode(["status" => "error", "message" => "Username sudah digunakan"]);
$stmt->execute(); $check->close();
$stmt->store_result(); $conn->close();
if ($stmt->num_rows > 0) {
echo json_encode(["status"=>"error","message"=>"Username sudah terpakai"]);
exit; exit;
} }
$stmt->close();
$hash = password_hash($password, PASSWORD_DEFAULT); $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
$stmt = $conn->prepare("INSERT INTO users (username, password) VALUES (?, ?)"); $stmt = $conn->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
$stmt->bind_param("ss", $username, $hash); $stmt->bind_param("ss", $username, $hashedPassword);
if ($stmt->execute()) { if ($stmt->execute()) {
$_SESSION['user_id'] = $stmt->insert_id; echo json_encode(["status" => "success", "message" => "Pendaftaran berhasil"]);
$_SESSION['username'] = $username;
echo json_encode(["status"=>"success","message"=>"Register berhasil"]);
} else { } else {
echo json_encode(["status" => "error", "message" => "Gagal mendaftar"]); echo json_encode(["status" => "error", "message" => "Gagal mendaftar"]);
} }
$stmt->close(); $stmt->close();
$conn->close(); $conn->close();
?> ?>

View File

@ -1,16 +0,0 @@
<?php
include 'Database.php';
session_start();
if (isset($_SESSION['username'])) {
$username = $_SESSION['username'];
$score = $_POST['score'];
$query = "INSERT INTO leaderboard (username, score) VALUES ('$username', '$score')";
mysqli_query($conn, $query);
echo json_encode(["status" => "success"]);
} else {
echo json_encode(["status" => "error", "message" => "Not logged in"]);
}
?>

32
Save_Score.php Normal file
View File

@ -0,0 +1,32 @@
<?php
session_start();
header('Content-Type: application/json');
include 'Koneksi.php';
// Pastikan user sudah login
if (!isset($_SESSION['username'])) {
echo json_encode(["status" => "error", "message" => "Belum login"]);
exit;
}
$username = $_SESSION['username'];
$score = $_POST['score'] ?? 0;
if ($score <= 0) {
echo json_encode(["status" => "error", "message" => "Skor tidak valid"]);
exit;
}
// Simpan ke database
$stmt = $conn->prepare("INSERT INTO leaderboard (username, score) VALUES (?, ?)");
$stmt->bind_param("si", $username, $score);
if ($stmt->execute()) {
echo json_encode(["status" => "success", "message" => "Skor berhasil disimpan"]);
} else {
echo json_encode(["status" => "error", "message" => "Gagal menyimpan skor"]);
}
$stmt->close();
$conn->close();
?>

18
Score.js Normal file
View File

@ -0,0 +1,18 @@
function saveScore(score) {
fetch('Save_Score.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'score=' + encodeURIComponent(score)
})
.then(response => response.json())
.then(data => {
if (data.status === "success") {
console.log("Skor berhasil disimpan!");
} else {
console.log("Gagal menyimpan skor:", data.message);
}
})
.catch(error => console.error("Error API:", error));
}

15
Session_Check.php Normal file
View File

@ -0,0 +1,15 @@
<?php
session_start();
header('Content-Type: application/json');
if (isset($_SESSION['username'])) {
echo json_encode([
"status" => "logged_in",
"username" => $_SESSION['username']
]);
} else {
echo json_encode([
"status" => "not_logged_in"
]);
}
?>