Files

304 lines
9.0 KiB
HTML

<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Saperrro</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
}
body {
background-color: darkslategray;
}
main {
margin: 1em auto;
width: fit-content;
padding: 1em;
background-color: rgb(40, 40, 45);
color: white;
}
hr {
margin: .5em 0;
}
.settings>p {
font-weight: bold;
}
.setting {
display: flex;
justify-content: space-between;
margin-top: .5em;
}
.setting>input {
margin-left: 8em;
}
#start {
border: none;
width: 100%;
padding: .5em;
}
#start:hover {
background-color: darkslateblue;
cursor: pointer;
color: white;
}
table {
border-collapse: collapse;
}
td {
width: 40px;
height: 40px;
margin: 0;
border: 1px solid white;
text-align: center;
font-family: monospace;
user-select: none;
}
.nieodkryte-pole {
background-color: gray;
}
.nieodkryte-pole:hover {
cursor: pointer;
background-color: darkslateblue;
}
.odkryte-pole {
background-color: darkgray;
font-weight: bold;
}
#message {
text-align: center;
}
</style>
</head>
<body>
<main>
<h1>Saperrro</h1>
<div class="settings">
<hr>
<p>Ustawienia</p>
<div class="setting">
<label for="width">Szerokość planszy</label>
<input type="number" name="width" id="width" size="2" value="10">
</div>
<div class="setting">
<label for="height">Wysokość planszy</label>
<input type="number" name="height" id="height" size="2" value="10">
</div>
<div class="setting">
<label for="mines">Ilość min</label>
<input type="number" name="mines" id="mines" size="2" value="10">
</div>
<div class="setting">
<button id="start">Graj</button>
</div>
<hr>
</div>
<div class="game">
<table id="plansza">
</table>
</div>
<div class="messages">
<hr>
<p id="message">Podaj wymiary planszy i rozpocznij grę.</p>
</div>
</main>
<script>
// wymiary gry
let w = 0
let h = 0
let m = 0
let gra = true
let polozono_miny = false
let odkryte_pola = 0
// tablica z polami
let plansza = [] // tablice obiektów (pól) { x: int, y: int, mina: true/false, sasiednie_miny: int }
const kolorki = ["red", "green", "blue", "darkseagreen", "cornflowerblue", "beige", "orange", "navy"]
function flaga(btn) {
let x = btn.dataset.x
let y = btn.dataset.y
if (!gra) { return }
event.preventDefault()
if (btn.classList.contains("nieodkryte-pole")) {
plansza[y][x].flaga = !plansza[y][x].flaga;
plansza[y][x].flaga ? btn.innerHTML = '&#128681;' : btn.innerHTML = '';
}
}
function klik(btn) {
let x = btn.dataset.x
let y = btn.dataset.y
if (!polozono_miny) {
losuj_miny(x, y)
polozono_miny = true
}
if (!gra) { return }
if (plansza[y][x].flaga) { return }
if (document.getElementById(`p${x}${y}`).classList.contains("odkryte-pole")) { return }
if (plansza[y][x].mina) {
alert("Koniec gry, przegrana!")
document.getElementById(`p${x}${y}`).style.backgroundColor = "red";
gra = false
} else {
btn.classList.remove("nieodkryte-pole")
btn.classList.add("odkryte-pole")
if (plansza[y][x].sasiednie_miny != 0) {
btn.innerText = plansza[y][x].sasiednie_miny
btn.style.color = kolorki[plansza[y][x].sasiednie_miny - 1]
}
odkryte_pola++
if (odkryte_pola == (w * h) - m) {
alert("Koniec gry, wygrana!")
gra = false
}
}
// jeśli nie ma min dookoła to odkryj pola sąsiednie
if (plansza[y][x].sasiednie_miny == 0) {
let i = y;
let j = x - 1;
if (i >= 0 && i < h && j >= 0 && j < w) {
if (document.getElementById(`p${j}${i}`).classList.contains("nieodkryte-pole")) {
klik(document.getElementById(`p${j}${i}`))
}
}
j += 2;
if (i >= 0 && i < h && j >= 0 && j < w) {
if (document.getElementById(`p${j}${i}`).classList.contains("nieodkryte-pole")) {
klik(document.getElementById(`p${j}${i}`))
}
}
j = x;
i = y - 1;
if (i >= 0 && i < h && j >= 0 && j < w) {
if (document.getElementById(`p${j}${i}`).classList.contains("nieodkryte-pole")) {
klik(document.getElementById(`p${j}${i}`))
}
}
i += 2;
if (i >= 0 && i < h && j >= 0 && j < w) {
if (document.getElementById(`p${j}${i}`).classList.contains("nieodkryte-pole")) {
klik(document.getElementById(`p${j}${i}`))
}
}
}
}
function przygotuj() {
plansza = []
const plansza_table = document.getElementById("plansza")
plansza_table.innerHTML = ''
// wypełnij planszę na razie bez min
let n_html = ''
for (let i = 0; i < h; i++) {
plansza.push([])
n_html += '<tr>'
for (let j = 0; j < w; j++) {
plansza[i].push({ x: j, y: i, mina: false, sasiednie_miny: 0, flaga: false })
n_html += `<td class="nieodkryte-pole" id="p${j}${i}" onclick="klik(this)" oncontextmenu="flaga(this)" oncontextmenu="flaga" data-x="${j}" data-y="${i}"></td>`
}
n_html += '</tr>'
}
plansza_table.innerHTML += n_html
}
function losuj_miny(unikaj_x = 0, unikaj_y = 0) {
let wspolrzedne_min = []
while (wspolrzedne_min.length < m) {
let random_x = Math.floor(Math.random() * w)
let random_y = Math.floor(Math.random() * h)
if (!wspolrzedne_min.find(wspolrzedna => (wspolrzedna.x == random_x && wspolrzedna.y == random_y))) {
if (!(random_x == unikaj_x && random_y == unikaj_y)) {
wspolrzedne_min.push({ x: random_x, y: random_y })
}
}
}
wspolrzedne_min.forEach(wspolrzedna => {
// znajdz pole
plansza[wspolrzedna.y][wspolrzedna.x].mina = true
// znajdz pola sasiadujace
for (let i = wspolrzedna.y - 1; i <= wspolrzedna.y + 1; i++) {
if (i < 0) { continue }
if (i >= h) { continue }
for (let j = wspolrzedna.x - 1; j <= wspolrzedna.x + 1; j++) {
if (j < 0) { continue }
if (j >= w) { continue }
if (j == wspolrzedna.x && i == wspolrzedna.y) { continue }
plansza[i][j].sasiednie_miny += 1
}
}
})
}
// funkcja startu gry
document.getElementById("start").onclick = function () {
let w_t = parseInt(document.getElementById("width").value);
let h_t = parseInt(document.getElementById("height").value);
let m_t = parseInt(document.getElementById("mines").value);
// walidacja
if (
isNaN(w_t) |
isNaN(h_t) |
isNaN(m_t)
) {
document.getElementById("message").innerText = "Podaj właściwe wymiary!"
return
}
gra = true
polozono_miny = false
odkryte_pola = 0
w = w_t
h = h_t
m = m_t
przygotuj()
}
</script>
</body>
</html>