130 lines
3.1 KiB
JavaScript
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();
|
|
|