Backend
This commit is contained in:
parent
9ea5612980
commit
f0b5ae87b6
244
2048.js
244
2048.js
@ -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
20
Database.sql
Normal 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);
|
||||
@ -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();
|
||||
?>
|
||||
45
Login.php
45
Login.php
@ -1,33 +1,38 @@
|
||||
<?php
|
||||
session_start();
|
||||
header('Content-Type: application/json');
|
||||
include 'Database.php';
|
||||
session_start();
|
||||
|
||||
$data = $_POST;
|
||||
if (empty($data['username']) || empty($data['password'])) {
|
||||
echo json_encode(["status"=>"error","message"=>"Username & password dibutuhkan"]);
|
||||
$username = $_POST['username'] ?? '';
|
||||
$password = $_POST['password'] ?? '';
|
||||
|
||||
if (empty($username) || empty($password)) {
|
||||
echo json_encode(["status" => "error", "message" => "Username dan password wajib diisi"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$username = trim($data['username']);
|
||||
$password = $data['password'];
|
||||
|
||||
$stmt = $conn->prepare("SELECT id, password FROM users WHERE username = ?");
|
||||
$stmt = $conn->prepare("SELECT password FROM users WHERE username = ?");
|
||||
$stmt->bind_param("s", $username);
|
||||
$stmt->execute();
|
||||
$stmt->bind_result($id, $hash);
|
||||
if ($stmt->fetch()) {
|
||||
if (password_verify($password, $hash)) {
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['user_id'] = $id;
|
||||
$_SESSION['username'] = $username;
|
||||
echo json_encode(["status"=>"success","message"=>"Login berhasil"]);
|
||||
} else {
|
||||
echo json_encode(["status"=>"error","message"=>"Password salah"]);
|
||||
}
|
||||
} else {
|
||||
echo json_encode(["status"=>"error","message"=>"User tidak ditemukan"]);
|
||||
$stmt->store_result();
|
||||
|
||||
if ($stmt->num_rows === 0) {
|
||||
echo json_encode(["status" => "error", "message" => "Username tidak ditemukan"]);
|
||||
$stmt->close();
|
||||
$conn->close();
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->bind_result($hashedPassword);
|
||||
$stmt->fetch();
|
||||
|
||||
if (password_verify($password, $hashedPassword)) {
|
||||
$_SESSION['username'] = $username;
|
||||
echo json_encode(["status" => "success", "message" => "Login berhasil"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Password salah"]);
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
$conn->close();
|
||||
?>
|
||||
18
Logout.php
18
Logout.php
@ -1,14 +1,12 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
session_start();
|
||||
$_SESSION = [];
|
||||
if (ini_get("session.use_cookies")) {
|
||||
$params = session_get_cookie_params();
|
||||
setcookie(session_name(), '', time() - 42000,
|
||||
$params["path"], $params["domain"],
|
||||
$params["secure"], $params["httponly"]
|
||||
);
|
||||
}
|
||||
header('Content-Type: application/json');
|
||||
|
||||
session_unset();
|
||||
session_destroy();
|
||||
echo json_encode(["status"=>"success","message"=>"Logout berhasil"]);
|
||||
|
||||
echo json_encode([
|
||||
"status" => "success",
|
||||
"message" => "Logout berhasil"
|
||||
]);
|
||||
?>
|
||||
39
Register.php
39
Register.php
@ -1,37 +1,38 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
include 'Database.php';
|
||||
session_start();
|
||||
|
||||
$data = $_POST;
|
||||
if (empty($data['username']) || empty($data['password'])) {
|
||||
echo json_encode(["status"=>"error","message"=>"Username & password dibutuhkan"]);
|
||||
$username = $_POST['username'] ?? '';
|
||||
$password = $_POST['password'] ?? '';
|
||||
|
||||
if (empty($username) || empty($password)) {
|
||||
echo json_encode(["status" => "error", "message" => "Username dan password wajib diisi"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$username = trim($data['username']);
|
||||
$password = $data['password'];
|
||||
$check = $conn->prepare("SELECT id FROM users WHERE username = ?");
|
||||
$check->bind_param("s", $username);
|
||||
$check->execute();
|
||||
$check->store_result();
|
||||
|
||||
$stmt = $conn->prepare("SELECT id FROM users WHERE username = ?");
|
||||
$stmt->bind_param("s", $username);
|
||||
$stmt->execute();
|
||||
$stmt->store_result();
|
||||
if ($stmt->num_rows > 0) {
|
||||
echo json_encode(["status"=>"error","message"=>"Username sudah terpakai"]);
|
||||
if ($check->num_rows > 0) {
|
||||
echo json_encode(["status" => "error", "message" => "Username sudah digunakan"]);
|
||||
$check->close();
|
||||
$conn->close();
|
||||
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->bind_param("ss", $username, $hash);
|
||||
$stmt->bind_param("ss", $username, $hashedPassword);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
$_SESSION['user_id'] = $stmt->insert_id;
|
||||
$_SESSION['username'] = $username;
|
||||
echo json_encode(["status"=>"success","message"=>"Register berhasil"]);
|
||||
echo json_encode(["status" => "success", "message" => "Pendaftaran berhasil"]);
|
||||
} else {
|
||||
echo json_encode(["status"=>"error","message"=>"Gagal mendaftar"]);
|
||||
echo json_encode(["status" => "error", "message" => "Gagal mendaftar"]);
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
$conn->close();
|
||||
?>
|
||||
@ -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
32
Save_Score.php
Normal 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
18
Score.js
Normal 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
15
Session_Check.php
Normal 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"
|
||||
]);
|
||||
}
|
||||
?>
|
||||
Loading…
x
Reference in New Issue
Block a user