formatted like my Boss wants it (help!)
This commit is contained in:
parent
5d11f87dd3
commit
b507a6b0ea
19 changed files with 1425 additions and 1136 deletions
|
@ -1,173 +1,192 @@
|
|||
document.getElementById('startGame').addEventListener('click', function () {
|
||||
const gridSize = parseInt(document.getElementById('gridSize').value);
|
||||
const bombs = parseInt(document.getElementById('bombs').value);
|
||||
document.getElementById("startGame").addEventListener("click", function () {
|
||||
const gridSize = parseInt(document.getElementById("gridSize").value);
|
||||
const bombs = parseInt(document.getElementById("bombs").value);
|
||||
|
||||
document.getElementById('settings').style.display = 'none';
|
||||
document.getElementById('game').style.display = 'block';
|
||||
document.getElementById("settings").style.display = "none";
|
||||
document.getElementById("game").style.display = "block";
|
||||
|
||||
renderGame(gridSize, bombs);
|
||||
renderGame(gridSize, bombs);
|
||||
});
|
||||
|
||||
const canvas = document.getElementById('game');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const canvas = document.getElementById("game");
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
class Minesweeper {
|
||||
constructor(width, height, bombs) {
|
||||
this.size = 25;
|
||||
this.field = new Array(width);
|
||||
this.bombs = new Array(width);
|
||||
for (let x = 0; x < this.field.length; x++) {
|
||||
this.field[x] = new Array(height);
|
||||
this.bombs[x] = new Array(height);
|
||||
for (let y = 0; y < this.field[x].length; y++) {
|
||||
this.field[x][y] = 1;
|
||||
this.bombs[x][y] = false;
|
||||
}
|
||||
}
|
||||
|
||||
this.bombAmount = bombs > width * height / 2 ? width * height / 2 : bombs;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.firstClick = false;
|
||||
this.drawField();
|
||||
constructor(width, height, bombs) {
|
||||
this.size = 25;
|
||||
this.field = new Array(width);
|
||||
this.bombs = new Array(width);
|
||||
for (let x = 0; x < this.field.length; x++) {
|
||||
this.field[x] = new Array(height);
|
||||
this.bombs[x] = new Array(height);
|
||||
for (let y = 0; y < this.field[x].length; y++) {
|
||||
this.field[x][y] = 1;
|
||||
this.bombs[x][y] = false;
|
||||
}
|
||||
}
|
||||
|
||||
generateBombs() {
|
||||
for (let i = 0; i < this.bombAmount; i++) {
|
||||
let x = Math.floor(Math.random() * this.width);
|
||||
let y = Math.floor(Math.random() * this.height);
|
||||
(this.bombs[x][y] || this.field[x][y] == 0) ? i-- : this.bombs[x][y] = true;
|
||||
}
|
||||
this.firstClick = true;
|
||||
}
|
||||
this.bombAmount =
|
||||
bombs > (width * height) / 2 ? (width * height) / 2 : bombs;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.firstClick = false;
|
||||
this.drawField();
|
||||
}
|
||||
|
||||
getNearbyBombs(x, y) {
|
||||
let counter = 0;
|
||||
for (let newX = x - 1; newX <= x + 1; newX++) {
|
||||
for (let newY = y - 1; newY <= y + 1; newY++) {
|
||||
if (newX < this.field.length && newX >= 0 && newY < this.field[0].length && newY >= 0) {
|
||||
this.bombs[newX][newY] ? counter++ : {};
|
||||
}
|
||||
}
|
||||
}
|
||||
return counter;
|
||||
generateBombs() {
|
||||
for (let i = 0; i < this.bombAmount; i++) {
|
||||
let x = Math.floor(Math.random() * this.width);
|
||||
let y = Math.floor(Math.random() * this.height);
|
||||
this.bombs[x][y] || this.field[x][y] == 0
|
||||
? i--
|
||||
: (this.bombs[x][y] = true);
|
||||
}
|
||||
this.firstClick = true;
|
||||
}
|
||||
|
||||
checkWin() {
|
||||
for (let x = 0; x < this.field.length; x++) {
|
||||
for (let y = 0; y < this.field[x].length; y++) {
|
||||
if (this.field[x][y] != 0 && !this.bombs[x][y]) {
|
||||
return;
|
||||
} else if (this.field[x][y] == 0 && this.bombs[x][y]) {
|
||||
alert(`[ERROR]: Square (${x}|${y}) should not be a bomb!`);
|
||||
this.bombs[x][y] = false;
|
||||
}
|
||||
}
|
||||
getNearbyBombs(x, y) {
|
||||
let counter = 0;
|
||||
for (let newX = x - 1; newX <= x + 1; newX++) {
|
||||
for (let newY = y - 1; newY <= y + 1; newY++) {
|
||||
if (
|
||||
newX < this.field.length &&
|
||||
newX >= 0 &&
|
||||
newY < this.field[0].length &&
|
||||
newY >= 0
|
||||
) {
|
||||
this.bombs[newX][newY] ? counter++ : {};
|
||||
}
|
||||
this.drawField();
|
||||
alert('You won!');
|
||||
}
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
checkWin() {
|
||||
for (let x = 0; x < this.field.length; x++) {
|
||||
for (let y = 0; y < this.field[x].length; y++) {
|
||||
if (this.field[x][y] != 0 && !this.bombs[x][y]) {
|
||||
return;
|
||||
} else if (this.field[x][y] == 0 && this.bombs[x][y]) {
|
||||
alert(`[ERROR]: Square (${x}|${y}) should not be a bomb!`);
|
||||
this.bombs[x][y] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.drawField();
|
||||
alert("You won!");
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
markSquare(x, y) {
|
||||
if (x < this.field.length && y < this.field[0].length) {
|
||||
switch (this.field[x][y]) {
|
||||
case 1:
|
||||
this.field[x][y]++;
|
||||
break;
|
||||
case 2:
|
||||
this.field[x][y]++;
|
||||
break;
|
||||
case 3:
|
||||
this.field[x][y] = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this.drawField();
|
||||
}
|
||||
}
|
||||
|
||||
uncoverSquare(x, y) {
|
||||
if (x < this.field.length && x >= 0 && y < this.field[0].length && y >= 0) {
|
||||
if (this.bombs[x][y] && this.field[x][y] == 1) {
|
||||
alert("You lost!");
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
markSquare(x, y) {
|
||||
if (x < this.field.length && y < this.field[0].length) {
|
||||
switch (this.field[x][y]) {
|
||||
case 1:
|
||||
this.field[x][y]++;
|
||||
break;
|
||||
case 2:
|
||||
this.field[x][y]++;
|
||||
break;
|
||||
case 3:
|
||||
this.field[x][y] = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} else if (this.field[x][y] == 1) {
|
||||
this.field[x][y] = 0;
|
||||
!this.firstClick ? this.generateBombs() : {};
|
||||
if (this.getNearbyBombs(x, y) == 0) {
|
||||
for (let newX = x - 1; newX <= x + 1; newX++) {
|
||||
for (let newY = y - 1; newY <= y + 1; newY++) {
|
||||
if (
|
||||
newX < this.field.length &&
|
||||
newX >= 0 &&
|
||||
newY < this.field[0].length &&
|
||||
newY >= 0
|
||||
) {
|
||||
this.field[newX][newY] == 1
|
||||
? this.uncoverSquare(newX, newY)
|
||||
: {};
|
||||
}
|
||||
}
|
||||
this.drawField();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.checkWin();
|
||||
this.drawField();
|
||||
}
|
||||
}
|
||||
|
||||
drawSquare(x, y, type) {
|
||||
ctx.lineWidth = 3;
|
||||
let uncovered = (x + y) % 2 === 0 ? "#D3D3D3" : "#A9A9A9";
|
||||
let covered = (x + y) % 2 === 0 ? "#4CAF50" : "#81C784";
|
||||
ctx.fillStyle = type != 0 ? covered : uncovered;
|
||||
ctx.fillRect(x * this.size, y * this.size, this.size, this.size);
|
||||
ctx.strokeStyle = "#000";
|
||||
ctx.strokeRect(x * this.size, y * this.size, this.size, this.size);
|
||||
|
||||
if (type != 1) {
|
||||
const fontSize = this.size / 2;
|
||||
const number = this.getNearbyBombs(x, y);
|
||||
let finalPrint;
|
||||
ctx.font = `${fontSize}px sans-serif`;
|
||||
ctx.fillStyle = "#000";
|
||||
type == 0 ? (finalPrint = number ? number : " ") : {};
|
||||
type == 2 ? (finalPrint = "🚩") : {};
|
||||
type == 3 ? (finalPrint = "❓") : {};
|
||||
ctx.fillText(
|
||||
finalPrint,
|
||||
x * this.size + fontSize / (type == 0 ? 1.5 : 1.8),
|
||||
y * this.size + fontSize * 1.3
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
drawField() {
|
||||
if (window.innerWidth > window.innerHeight) {
|
||||
this.size = window.innerHeight / (this.field[0].length + 4);
|
||||
} else {
|
||||
this.size = window.innerWidth / (this.field.length + 4);
|
||||
}
|
||||
|
||||
uncoverSquare(x, y) {
|
||||
if (x < this.field.length && x >= 0 && y < this.field[0].length && y >= 0) {
|
||||
if (this.bombs[x][y] && this.field[x][y] == 1) {
|
||||
alert('You lost!');
|
||||
window.location.reload();
|
||||
} else if (this.field[x][y] == 1) {
|
||||
this.field[x][y] = 0;
|
||||
!this.firstClick ? this.generateBombs() : {};
|
||||
if (this.getNearbyBombs(x, y) == 0) {
|
||||
for (let newX = x - 1; newX <= x + 1; newX++) {
|
||||
for (let newY = y - 1; newY <= y + 1; newY++) {
|
||||
if (newX < this.field.length && newX >= 0 && newY < this.field[0].length && newY >= 0) {
|
||||
this.field[newX][newY] == 1 ? this.uncoverSquare(newX, newY) : {};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.checkWin();
|
||||
this.drawField();
|
||||
}
|
||||
}
|
||||
|
||||
drawSquare(x, y, type) {
|
||||
ctx.lineWidth = 3;
|
||||
let uncovered = (x + y) % 2 === 0 ? '#D3D3D3' : '#A9A9A9';
|
||||
let covered = (x + y) % 2 === 0 ? '#4CAF50' : '#81C784';
|
||||
ctx.fillStyle = type != 0 ? covered : uncovered;
|
||||
ctx.fillRect(x * this.size, y * this.size, this.size, this.size);
|
||||
ctx.strokeStyle = '#000';
|
||||
ctx.strokeRect(x * this.size, y * this.size, this.size, this.size);
|
||||
|
||||
if (type != 1) {
|
||||
const fontSize = this.size / 2;
|
||||
const number = this.getNearbyBombs(x, y);
|
||||
let finalPrint;
|
||||
ctx.font = `${fontSize}px sans-serif`;
|
||||
ctx.fillStyle = '#000';
|
||||
type == 0 ? finalPrint = number ? number : ' ' : {};
|
||||
type == 2 ? finalPrint = '🚩' : {};
|
||||
type == 3 ? finalPrint = '❓' : {};
|
||||
ctx.fillText(finalPrint, x * this.size + fontSize / (type == 0 ? 1.5 : 1.8), y * this.size + fontSize * 1.3);
|
||||
}
|
||||
}
|
||||
|
||||
drawField() {
|
||||
if (window.innerWidth > window.innerHeight) {
|
||||
this.size = window.innerHeight / (this.field[0].length + 4);
|
||||
} else {
|
||||
this.size = window.innerWidth / (this.field.length + 4);
|
||||
}
|
||||
|
||||
canvas.width = this.size * this.field.length;
|
||||
canvas.height = this.size * this.field[0].length;
|
||||
|
||||
const offsetX = (canvas.width - (this.field.length * this.size)) / 2;
|
||||
const offsetY = (canvas.height - (this.field[0].length * this.size)) / 2;
|
||||
|
||||
for (let x = 0; x < this.field.length; x++) {
|
||||
for (let y = 0; y < this.field[x].length; y++) {
|
||||
this.drawSquare(x, y, this.field[x][y], offsetX, offsetY);
|
||||
}
|
||||
}
|
||||
canvas.width = this.size * this.field.length;
|
||||
canvas.height = this.size * this.field[0].length;
|
||||
|
||||
const offsetX = (canvas.width - this.field.length * this.size) / 2;
|
||||
const offsetY = (canvas.height - this.field[0].length * this.size) / 2;
|
||||
|
||||
for (let x = 0; x < this.field.length; x++) {
|
||||
for (let y = 0; y < this.field[x].length; y++) {
|
||||
this.drawSquare(x, y, this.field[x][y], offsetX, offsetY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const renderGame = (gridSize, bombs) => {
|
||||
let field = new Minesweeper(gridSize, gridSize, bombs);
|
||||
window.addEventListener('resize', () => field.drawField());
|
||||
canvas.addEventListener('click', (event) => {
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const x = Math.floor((event.clientX - rect.left) / field.size);
|
||||
const y = Math.floor((event.clientY - rect.top) / field.size);
|
||||
field.uncoverSquare(x, y);
|
||||
});
|
||||
canvas.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault();
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const x = Math.floor((event.clientX - rect.left) / field.size);
|
||||
const y = Math.floor((event.clientY - rect.top) / field.size);
|
||||
field.markSquare(x, y);
|
||||
});
|
||||
let field = new Minesweeper(gridSize, gridSize, bombs);
|
||||
window.addEventListener("resize", () => field.drawField());
|
||||
canvas.addEventListener("click", (event) => {
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const x = Math.floor((event.clientX - rect.left) / field.size);
|
||||
const y = Math.floor((event.clientY - rect.top) / field.size);
|
||||
field.uncoverSquare(x, y);
|
||||
});
|
||||
canvas.addEventListener("contextmenu", (event) => {
|
||||
event.preventDefault();
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const x = Math.floor((event.clientX - rect.left) / field.size);
|
||||
const y = Math.floor((event.clientY - rect.top) / field.size);
|
||||
field.markSquare(x, y);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,104 +1,104 @@
|
|||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #121212;
|
||||
color: #e0e0e0;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #121212;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
#settings {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
background-color: #1e1e1e;
|
||||
padding: 40px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.5);
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
background-color: #1e1e1e;
|
||||
padding: 40px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.5);
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
margin-bottom: 20px;
|
||||
color: #007bff;
|
||||
font-size: 2.5em;
|
||||
margin-bottom: 20px;
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 12px;
|
||||
font-size: 20px;
|
||||
color: #d1d1d1;
|
||||
margin-bottom: 12px;
|
||||
font-size: 20px;
|
||||
color: #d1d1d1;
|
||||
}
|
||||
|
||||
input[type="number"],
|
||||
input[type="range"],
|
||||
span {
|
||||
padding: 12px;
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
text-align: center;
|
||||
border: 1px solid #444;
|
||||
border-radius: 6px;
|
||||
background-color: #333;
|
||||
color: #e0e0e0;
|
||||
font-size: 18px;
|
||||
transition: border-color 0.3s ease;
|
||||
padding: 12px;
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
text-align: center;
|
||||
border: 1px solid #444;
|
||||
border-radius: 6px;
|
||||
background-color: #333;
|
||||
color: #e0e0e0;
|
||||
font-size: 18px;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
input[type="number"]:focus,
|
||||
input[type="range"]:focus {
|
||||
border-color: #007bff;
|
||||
outline: none;
|
||||
border-color: #007bff;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 12px 24px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
font-size: 18px;
|
||||
padding: 12px 24px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
transform: translateY(-2px);
|
||||
background-color: #0056b3;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
button:active {
|
||||
transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
canvas {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media(max-width: 600px) {
|
||||
#settings {
|
||||
font-size: 16px;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
#settings {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
input[type="number"],
|
||||
input[type="range"],
|
||||
button {
|
||||
width: 90%;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
input[type="number"],
|
||||
input[type="range"],
|
||||
button {
|
||||
width: 90%;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue