Skip to content

Commit

Permalink
Merge pull request #3879 from Yashgabani845/yash-work
Browse files Browse the repository at this point in the history
16-puzzle added
  • Loading branch information
kunjgit authored May 30, 2024
2 parents a558f03 + edb6370 commit 7655c41
Show file tree
Hide file tree
Showing 7 changed files with 362 additions and 1 deletion.
35 changes: 35 additions & 0 deletions Games/16_Puzzle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Number Puzzle Game

This is a simple and attractive number puzzle game implemented using HTML, CSS, JavaScript, and Bootstrap. The game is inspired by the classic 8-puzzle game, where the objective is to arrange numbered tiles in sequential order by sliding them into an empty space.

## Features

- Interactive 4x4 grid puzzle (16-puzzle).
- Shuffle button to randomize the tiles.
- Move counter to track the number of moves.
- Timer to track the time taken to solve the puzzle.
- Score calculation based on moves and time taken.

## How to Play

1. Open the game in your web browser.
2. Click the "Shuffle" button to start a new game.
3. Slide the tiles by clicking on them to move them into the empty space.
4. Arrange the tiles in numerical order (1 to 16) with the empty space in the bottom-right corner.
5. The game ends when you have arranged all the tiles correctly. Your score will be displayed based on the number of moves and time taken.


## Installation

No installation is required. Simply open the `index.html` file in your web browser to start playing the game.

## Files

- `index.html`: The main HTML file that contains the structure of the game.
- `style.css`: The CSS file that styles the game using Bootstrap and custom styles.
- `script.js`: The JavaScript file that contains the game logic and interactivity.

## Usage

1. Clone the repository or download the files.
2. Open `index.html` in your preferred web browser.
40 changes: 40 additions & 0 deletions Games/16_Puzzle/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!doctype html>
<html>
<head>
<title>Puzzle game</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>

<body>
<div class="game">
<div class="grid">
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>7</button>
<button>8</button>
<button>9</button>
<button>10</button>
<button>11</button>
<button>12</button>
<button>13</button>
<button>14</button>
<button>15</button>
<button></button>
</div>

<div class="footer">
<button>Play</button>
<span id="move">Move: 100</span>
<span id="time">Time: 100</span>
</div>
</div>
<h1 class="message">You win!</h1>


<script src="script.js"></script>
</body>
</html>
201 changes: 201 additions & 0 deletions Games/16_Puzzle/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
class Box {
constructor(x, y) {
this.x = x;
this.y = y;
}

getTopBox() {
if (this.y === 0) return null;
return new Box(this.x, this.y - 1);
}

getRightBox() {
if (this.x === 3) return null;
return new Box(this.x + 1, this.y);
}

getBottomBox() {
if (this.y === 3) return null;
return new Box(this.x, this.y + 1);
}

getLeftBox() {
if (this.x === 0) return null;
return new Box(this.x - 1, this.y);
}

getNextdoorBoxes() {
return [
this.getTopBox(),
this.getRightBox(),
this.getBottomBox(),
this.getLeftBox()
].filter(box => box !== null);
}

getRandomNextdoorBox() {
const nextdoorBoxes = this.getNextdoorBoxes();
return nextdoorBoxes[Math.floor(Math.random() * nextdoorBoxes.length)];
}
}

const swapBoxes = (grid, box1, box2) => {
const temp = grid[box1.y][box1.x];
grid[box1.y][box1.x] = grid[box2.y][box2.x];
grid[box2.y][box2.x] = temp;
};

const isSolved = grid => {
return (
grid[0][0] === 1 &&
grid[0][1] === 2 &&
grid[0][2] === 3 &&
grid[0][3] === 4 &&
grid[1][0] === 5 &&
grid[1][1] === 6 &&
grid[1][2] === 7 &&
grid[1][3] === 8 &&
grid[2][0] === 9 &&
grid[2][1] === 10 &&
grid[2][2] === 11 &&
grid[2][3] === 12 &&
grid[3][0] === 13 &&
grid[3][1] === 14 &&
grid[3][2] === 15 &&
grid[3][3] === 0
);
};

const getRandomGrid = () => {
let grid = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 0]];

// Shuffle
let blankBox = new Box(3, 3);
for (let i = 0; i < 1000; i++) {
const randomNextdoorBox = blankBox.getRandomNextdoorBox();
swapBoxes(grid, blankBox, randomNextdoorBox);
blankBox = randomNextdoorBox;
}

if (isSolved(grid)) return getRandomGrid();
return grid;
};

class State {
constructor(grid, move, time, status) {
this.grid = grid;
this.move = move;
this.time = time;
this.status = status;
}

static ready() {
return new State(
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]],
0,
0,
"ready"
);
}

static start() {
return new State(getRandomGrid(), 0, 0, "playing");
}
}

class Game {
constructor(state) {
this.state = state;
this.tickId = null;
this.tick = this.tick.bind(this);
this.render();
this.handleClickBox = this.handleClickBox.bind(this);
}

static ready() {
return new Game(State.ready());
}

tick() {
this.setState({ time: this.state.time + 1 });
}

setState(newState) {
this.state = { ...this.state, ...newState };
this.render();
}

handleClickBox(box) {
return function() {
const nextdoorBoxes = box.getNextdoorBoxes();
const blankBox = nextdoorBoxes.find(
nextdoorBox => this.state.grid[nextdoorBox.y][nextdoorBox.x] === 0
);
if (blankBox) {
const newGrid = [...this.state.grid];
swapBoxes(newGrid, box, blankBox);
if (isSolved(newGrid)) {
clearInterval(this.tickId);
this.setState({
status: "won",
grid: newGrid,
move: this.state.move + 1
});
} else {
this.setState({
grid: newGrid,
move: this.state.move + 1
});
}
}
}.bind(this);
}

render() {
const { grid, move, time, status } = this.state;

// Render grid
const newGrid = document.createElement("div");
newGrid.className = "grid";
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
const button = document.createElement("button");

if (status === "playing") {
button.addEventListener("click", this.handleClickBox(new Box(j, i)));
}

button.textContent = grid[i][j] === 0 ? "" : grid[i][j].toString();
newGrid.appendChild(button);
}
}
document.querySelector(".grid").replaceWith(newGrid);

// Render button
const newButton = document.createElement("button");
if (status === "ready") newButton.textContent = "Play";
if (status === "playing") newButton.textContent = "Reset";
if (status === "won") newButton.textContent = "Play";
newButton.addEventListener("click", () => {
clearInterval(this.tickId);
this.tickId = setInterval(this.tick, 1000);
this.setState(State.start());
});
document.querySelector(".footer button").replaceWith(newButton);

// Render move
document.getElementById("move").textContent = `Move: ${move}`;

// Render time
document.getElementById("time").textContent = `Time: ${time}`;

// Render message
if (status === "won") {
document.querySelector(".message").textContent = "You win!";
} else {
document.querySelector(".message").textContent = "";
}
}
}

const GAME = Game.ready();
79 changes: 79 additions & 0 deletions Games/16_Puzzle/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
html {
height: 100%;
}

body {
height: 100%;
background-image: linear-gradient(#7B9F35, #226666);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}

.game {
/* position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); */
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
padding: 15px;
background-color: #AA3939;
border-radius: 5px;
}

.grid {
display: grid;
grid-template-columns: 80px 80px 80px 80px;
grid-template-rows: 80px 80px 80px 80px;
border: 1px solid #550000;
}

.grid button {
background-color: #cfcfcf;
color: #003333;
font-size: 24px;
font-weight: bold;
border: 1px solid #550000;
outline: none;
cursor: pointer;
}

.footer {
margin-top: 15px;
display: flex;
justify-content: space-between;
}

.footer button {
border: none;
font-size: 20px;
font-weight: bold;
border-radius: 5px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
padding: 5px;
width: 80px;
background-color: #D4EE9F;
color: #003333;
outline: none;
cursor: pointer;
}

.footer button:hover {
color: #D4EE9F;
background-color: #003333;
}

.footer span {
flex: 1;
text-align: center;
font-size: 20px;
color: #D4EE9F;
font-weight: bold;
margin: auto 0;
}

.message {
color:#AA3939;
height: 80px;
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ This repository also provides one such platforms where contributers come over an
| [Automated_rock_paper_scissor](https://github.com/kunjgit/GameZone/tree/main/Games/automated_rock_paper_scissor) |

| [Maze_Game](https://github.com/kunjgit/GameZone/tree/main/Games/Maze_Game) | [Astronaut_runner](https://github.com/tanishkaa08/GameZone/tree/main/Games/Astronaunt_runner) |

[16_Puzzle](https://github.com/kunjgit/GameZone/tree/main/Games/16_Puzzle) |


| [Dragon_Tower](https://github.com/kunjgit/GameZone/tree/main/Games/Dragon_Tower) |
Expand Down
Binary file added assets/images/16_Puzzle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions assets/js/gamesData.json
Original file line number Diff line number Diff line change
Expand Up @@ -2062,6 +2062,12 @@
"gameTitle": "Candy_Crush_Saga",
"gameUrl": "Candy_Crush_Saga",
"thumbnailUrl": "Candy_Crush_Saga.png"
},"419":{

"gameTitle": "16_Puzzle",
"gameUrl": "16_Puzzle",
"thumbnailUrl": "16_Puzzle.png"

},
"406":{
"gameTitle": "Knife_hit",
Expand Down

0 comments on commit 7655c41

Please sign in to comment.