minesweeper-captcha/script.js
2022-05-01 18:45:20 -07:00

130 lines
3.1 KiB
JavaScript

const images = [
[],
[ "one1.png", "one2.png", "one3.png", "one4.png", "one5.png" ],
[ "two1.png", "two2.png", "two3.png", "two4.png" ],
[ "three1.png" ],
[ "four1.png" ],
[ "five1.png" ],
[ "six1.png" ],
[ "seven1.png" ],
[ "eight1.png" ],
];
function getImage(n) {
return `url(assets/${images[n][Math.floor(Math.random() * images[n].length)]})`;
}
function generateField(w = 4, h = 4, mines = 4) {
const field = [];
for (let i = 0; i < h; i++) {
field.push([]);
for (let i = 0; i < w; i++) {
field[field.length - 1].push(0);
}
}
for (let i = 0; i < mines; i++) {
const idx = Math.floor(Math.random() * w * h);
const x = idx % w;
const y = Math.floor(idx / h);
if (field[y][x] === -1) {
i--;
continue;
}
field[y][x] = -1;
incr(x - 1, y - 1);
incr(x - 1, y);
incr(x - 1, y + 1);
incr(x, y - 1);
incr(x, y);
incr(x, y + 1);
incr(x + 1, y - 1);
incr(x + 1, y);
incr(x + 1, y + 1);
}
return field;
function incr(x, y) {
if (x < 0 || x >= w || y < 0 || y >= h) return;
if (field[y][x] === -1) return;
field[y][x]++;
}
}
function generateCaptcha(field) {
const fieldEl = document.createElement("div");
const displayChance = 0.9;
for (let row of field) {
const rowEl = document.createElement("div");
for (let num of row) {
const numEl = document.createElement("div");
if (num > 0 && Math.random() < displayChance) {
numEl.style.backgroundImage = getImage(num);
}
numEl.addEventListener("click", () => {
numEl.classList.toggle("selected");
});
rowEl.append(numEl);
}
fieldEl.append(rowEl);
}
return fieldEl;
}
function runCaptcha() {
const minefield = generateField(4, 4, Math.floor(Math.random() * 3) + 3); // easy
// const minefield = generateField(6, 6, Math.floor(Math.random() * 10) + 6); // medium
// const minefield = generateField(15, 15, Math.floor(Math.random() * 33) + 12); // hard
// const minefield = generateField(100, 100, Math.floor(Math.random() * 1394) + 3494); // "skill issue"
console.log(minefield);
const wrapperEl = document.createElement("div");
const captchaEl = generateCaptcha(minefield);
const titleEl = document.createElement("div");
const verifyEl = document.createElement("button");
titleEl.innerHTML =
'Select all squares with<br><span class="big">mines</span>';
verifyEl.innerText = "Verify";
wrapperEl.append(titleEl);
wrapperEl.append(captchaEl);
wrapperEl.append(verifyEl);
wrapperEl.classList.add("captcha");
captchaEl.classList.add("main");
titleEl.classList.add("title");
document.body.append(wrapperEl);
verifyEl.addEventListener("click", check);
function check() {
if (isValid()) {
alert("nice");
verifyEl.removeEventListener("click", check);
wrapperEl.remove();
runCaptcha();
} else {
alert("nope");
}
}
function isValid() {
for (let y = 0; y < minefield.length; y++) {
for (let x = 0; x < minefield[0].length; x++) {
const selected =
captchaEl.children[y].children[x].classList.contains("selected");
const isMine = minefield[y][x] === -1;
if (selected !== isMine) return false;
}
}
return true;
}
}
runCaptcha();