Skip to content

Commit 041cf11

Browse files
authored
Add files via upload
1 parent 5e65289 commit 041cf11

3 files changed

Lines changed: 348 additions & 0 deletions

File tree

index.html

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Snake Game</title>
8+
<link rel="stylesheet" href="style.css">
9+
<script src="script.js" defer></script>
10+
</head>
11+
12+
<body>
13+
<div class="wrapper">
14+
<div class="game-details">
15+
<span class="score">Score: 0</span>
16+
<span class="highscore">High Score: 0</span>
17+
</div>
18+
<div class="play-board"></div>
19+
</div>
20+
21+
<!-- Game Over Modal -->
22+
<div class="game-over-modal" id="gameOverModal">
23+
<div class="game-over-content">
24+
<h2>Game Over!</h2>
25+
<p>Your Score: <span id="finalScore">0</span></p>
26+
<button onclick="restartGame()">Replay</button>
27+
</div>
28+
</div>
29+
30+
<!-- Difficulty Selection Modal -->
31+
<div class="difficulty-modal" id="difficultyModal">
32+
<div class="difficulty-content">
33+
<h2>Select Difficulty</h2>
34+
<button onclick="startGame('easy')">Easy</button>
35+
<button onclick="startGame('medium')">Medium</button>
36+
<button onclick="startGame('hard')">Hard</button>
37+
</div>
38+
</div>
39+
</body>
40+
41+
</html>

script.js

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
const playBoard = document.querySelector(".play-board");
2+
let foodX, foodY;
3+
let snakeX = 5, snakeY = 10;
4+
let snakeBody = [];
5+
let velocityX = 0, velocityY = 0;
6+
let score = 0;
7+
let highScore = localStorage.getItem("highScore") || 0;
8+
let gameInterval;
9+
let GameOver = false;
10+
let gameSpeed = 125; // Default game speed
11+
12+
// Function to change the food position to a random location
13+
const changeFoodPosition = () => {
14+
foodX = Math.floor(Math.random() * 30) + 1;
15+
foodY = Math.floor(Math.random() * 30) + 1;
16+
}
17+
18+
// Function to change the direction of the snake based on arrow keys
19+
const changeDirection = (e) => {
20+
// Prevent the snake from reversing direction
21+
if (e.key === "ArrowUp" && velocityY !== 1) {
22+
velocityX = 0;
23+
velocityY = -1;
24+
} else if (e.key === "ArrowDown" && velocityY !== -1) {
25+
velocityX = 0;
26+
velocityY = 1;
27+
} else if (e.key === "ArrowRight" && velocityX !== -1) {
28+
velocityX = 1;
29+
velocityY = 0;
30+
} else if (e.key === "ArrowLeft" && velocityX !== 1) {
31+
velocityX = -1;
32+
velocityY = 0;
33+
}
34+
}
35+
36+
// Function to display game over message and stop the game
37+
const gameOver = () => {
38+
clearInterval(gameInterval);
39+
GameOver = true;
40+
document.getElementById("finalScore").textContent = score;
41+
document.getElementById("gameOverModal").style.display = "flex";
42+
}
43+
44+
// Function to restart the game
45+
const restartGame = () => {
46+
// Reset game state
47+
snakeX = 5;
48+
snakeY = 10;
49+
snakeBody = [];
50+
velocityX = 0;
51+
velocityY = 0;
52+
score = 0;
53+
GameOver = false;
54+
55+
// Update the score display
56+
document.querySelector(".score").textContent = `Score: ${score}`;
57+
document.querySelector(".highscore").textContent = `High Score: ${highScore}`;
58+
59+
// Hide the game over modal
60+
document.getElementById("gameOverModal").style.display = "none";
61+
62+
// Show difficulty selection modal
63+
document.getElementById("difficultyModal").style.display = "flex";
64+
}
65+
66+
// Function to start the game based on selected difficulty
67+
const startGame = (difficulty) => {
68+
switch (difficulty) {
69+
case 'easy':
70+
gameSpeed = 200; // Slower speed for easy
71+
break;
72+
case 'medium':
73+
gameSpeed = 125; // Medium speed
74+
break;
75+
case 'hard':
76+
gameSpeed = 75; // Faster speed for hard
77+
break;
78+
}
79+
80+
// Hide the difficulty modal
81+
document.getElementById("difficultyModal").style.display = "none";
82+
83+
// Initialize the food position
84+
changeFoodPosition();
85+
86+
// Start the game with the selected speed
87+
gameInterval = setInterval(initGame, gameSpeed);
88+
}
89+
90+
// Main function to update the game state
91+
const initGame = () => {
92+
// Save the current tail position
93+
let tailX = snakeBody.length ? snakeBody[snakeBody.length - 1][0] : snakeX;
94+
let tailY = snakeBody.length ? snakeBody[snakeBody.length - 1][1] : snakeY;
95+
96+
// Update snake's head position based on current velocity
97+
snakeX += velocityX;
98+
snakeY += velocityY;
99+
100+
// Check for border collision (game over condition)
101+
if (snakeX < 1 || snakeX > 30 || snakeY < 1 || snakeY > 30) {
102+
gameOver();
103+
return;
104+
}
105+
106+
// Check for self-collision (game over condition)
107+
for (let i = 0; i < snakeBody.length; i++) {
108+
if (snakeX === snakeBody[i][0] && snakeY === snakeBody[i][1]) {
109+
gameOver();
110+
return;
111+
}
112+
}
113+
114+
// Check if the snake has reached the food
115+
if (snakeX === foodX && snakeY === foodY) {
116+
changeFoodPosition(); // Move the food to a new position
117+
// Add a new segment to the snake's body at the tail's previous position
118+
snakeBody.push([tailX, tailY]);
119+
score++;
120+
if (score > highScore) {
121+
highScore = score;
122+
localStorage.setItem("highScore", highScore);
123+
}
124+
document.querySelector(".score").textContent = `Score: ${score}`;
125+
document.querySelector(".highscore").textContent = `High Score: ${highScore}`;
126+
}
127+
128+
// Move each part of the snake's body to follow the segment in front of it
129+
for (let i = snakeBody.length - 1; i > 0; i--) {
130+
snakeBody[i] = snakeBody[i - 1];
131+
}
132+
// Update the first segment of the snake's body to the previous head position
133+
if (snakeBody.length > 0) {
134+
snakeBody[0] = [snakeX - velocityX, snakeY - velocityY];
135+
}
136+
137+
// Render the food and the snake's head on the grid
138+
let htmlMarkup = `<div class="food" style='grid-area: ${foodY} / ${foodX}'></div>`;
139+
htmlMarkup += `<div class="head" style='grid-area: ${snakeY} / ${snakeX}'></div>`;
140+
141+
// Render the snake's body on the grid
142+
for (let i = 0; i < snakeBody.length; i++) {
143+
htmlMarkup += `<div class="body" style='grid-area: ${snakeBody[i][1]} / ${snakeBody[i][0]}'></div>`;
144+
}
145+
146+
// Update the play board with the new positions
147+
playBoard.innerHTML = htmlMarkup;
148+
}
149+
150+
// Show the difficulty selection modal on page load
151+
document.getElementById("difficultyModal").style.display = "flex";
152+
153+
// Add event listener for keypress to change the snake's direction
154+
document.addEventListener('keydown', changeDirection);

style.css

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700&display=swap');
2+
3+
* {
4+
margin: 0;
5+
padding: 0;
6+
box-sizing: border-box;
7+
font-family: 'Open Sans', sans-serif;
8+
}
9+
10+
body {
11+
display: flex;
12+
align-items: center;
13+
justify-content: center;
14+
min-height: 100vh;
15+
background-color: #E3F2FD;
16+
}
17+
18+
.wrapper {
19+
width: 65vmin;
20+
height: 70vmin;
21+
display: flex;
22+
flex-direction: column;
23+
border-radius: 5px;
24+
background-color: #193447;
25+
}
26+
27+
.game-details {
28+
color: #B8C6DC;
29+
font-size: 1.2rem;
30+
font-weight: 500;
31+
padding: 20px 27px;
32+
display: flex;
33+
justify-content: space-between;
34+
}
35+
36+
.play-board {
37+
width: 100%;
38+
height: 100%;
39+
display: grid;
40+
grid-template-rows: repeat(30, 1fr);
41+
grid-template-columns: repeat(30, 1fr);
42+
background-color: #212837;
43+
}
44+
45+
.play-board .food {
46+
background-color: #ff003d;
47+
}
48+
49+
.play-board .head {
50+
background-color: #B8C6DC;
51+
}
52+
53+
.play-board .body {
54+
background-color: #4CAF50; /* Added color for body segments */
55+
}
56+
57+
/* Game Over Modal Styles */
58+
.game-over-modal {
59+
display: none; /* Hidden by default */
60+
position: fixed;
61+
z-index: 1;
62+
left: 0;
63+
top: 0;
64+
width: 100%;
65+
height: 100%;
66+
overflow: auto;
67+
background-color: rgb(0,0,0);
68+
background-color: rgba(0,0,0,0.4);
69+
align-items: center;
70+
justify-content: center;
71+
}
72+
73+
.game-over-content {
74+
background-color: #fefefe;
75+
margin: auto;
76+
padding: 20px;
77+
border: 1px solid #888;
78+
width: 80%;
79+
max-width: 300px;
80+
text-align: center;
81+
border-radius: 10px;
82+
}
83+
84+
.game-over-content h2 {
85+
font-size: 2rem;
86+
margin-bottom: 1rem;
87+
}
88+
89+
.game-over-content p {
90+
font-size: 1.2rem;
91+
margin-bottom: 1.5rem;
92+
}
93+
94+
.game-over-content button {
95+
padding: 10px 20px;
96+
font-size: 1rem;
97+
background-color: #4CAF50;
98+
color: white;
99+
border: none;
100+
border-radius: 5px;
101+
cursor: pointer;
102+
}
103+
104+
.game-over-content button:hover {
105+
background-color: #45a049;
106+
}
107+
108+
/* Difficulty Selection Modal Styles */
109+
.difficulty-modal {
110+
display: flex; /* Show by default for initial selection */
111+
position: fixed;
112+
z-index: 1;
113+
left: 0;
114+
top: 0;
115+
width: 100%;
116+
height: 100%;
117+
overflow: auto;
118+
background-color: rgb(0,0,0);
119+
background-color: rgba(0,0,0,0.4);
120+
align-items: center;
121+
justify-content: center;
122+
}
123+
124+
.difficulty-content {
125+
background-color: #fefefe;
126+
margin: auto;
127+
padding: 20px;
128+
border: 1px solid #888;
129+
width: 80%;
130+
max-width: 300px;
131+
text-align: center;
132+
border-radius: 10px;
133+
}
134+
135+
.difficulty-content h2 {
136+
font-size: 2rem;
137+
margin-bottom: 1rem;
138+
}
139+
140+
.difficulty-content button {
141+
padding: 10px 20px;
142+
font-size: 1rem;
143+
margin: 5px;
144+
background-color: #4CAF50;
145+
color: white;
146+
border: none;
147+
border-radius: 5px;
148+
cursor: pointer;
149+
}
150+
151+
.difficulty-content button:hover {
152+
background-color: #45a049;
153+
}

0 commit comments

Comments
 (0)