class Mastermind { constructor() { this.colorsCnt; this.rptColors; this.codeLen; this.guessCnt; this.guesses; this.code; this.selected; this.game_over; this.clear = (el) => { while (el.hasChildNodes()) { el.removeChild(el.firstChild); } }; this.colors = ["🤡", "👹", "👺", "👻", "👽", "👾", "🤖", "🐵", "🐭", "🐸", "🎃", "🤠", "☠️", "🦄", "🦇", "🛸", "🎅", "👿", "🐲", "🦋" ]; } newGame() { this.selected = null; this.guessCnt = parseInt(document.getElementById("gssCnt").value); this.colorsCnt = parseInt(document.getElementById("clrCnt").value); this.codeLen = parseInt(document.getElementById("codeLen").value); if (this.codeLen > this.colorsCnt) { document.getElementById("rptClr").selectedIndex = 1; } this.rptColors = document.getElementById("rptClr").value === "yes"; this.guesses = 0; this.game_over = false; const go = document.getElementById("gameover"); go.innerText = ""; go.style.visibility = "hidden"; this.clear(document.getElementById("code")); this.buildPalette(); this.buildPlayField(); } buildPalette() { const pal = document.getElementById("palette"), z = this.colorsCnt / 5, h = Math.floor(z) != z ? Math.floor(z) + 1 : z; this.clear(pal); pal.style.height = `${44 * h + 3 * h}px`; const clrs = []; for (let c = 0; c < this.colorsCnt; c++) { clrs.push(c); const b = document.createElement("div"); b.className = "bucket"; b.clr = c; b.innerText = this.colors[c]; b.addEventListener("click", () => { this.palClick(b); }); pal.appendChild(b); } this.code = []; while (this.code.length < this.codeLen) { const r = Math.floor(Math.random() * clrs.length); this.code.push(clrs[r]); if (!this.rptColors) { clrs.splice(r, 1); } } } buildPlayField() { const brd = document.getElementById("board"); this.clear(brd); const w = 49 * this.codeLen + 7 * this.codeLen + 5; brd.active = 0; brd.style.width = `${w}px`; document.querySelector(".column").style.width = `${w + 20}px`; this.addGuessLine(brd); } addGuessLine(brd) { const z = document.createElement("div"); z.style.clear = "both"; brd.appendChild(z); brd.active += 10; for (let c = 0; c < this.codeLen; c++) { const d = document.createElement("div"); d.className = "bucket"; d.id = `brd${brd.active+ c}`; d.clr = -1; d.addEventListener("click", () => { this.playClick(d); }) brd.appendChild(d); } } palClick(bucket) { if (this.game_over) return; if (null === this.selected) { bucket.classList.add("selected"); this.selected = bucket; return; } if (this.selected !== bucket) { this.selected.classList.remove("selected"); bucket.classList.add("selected"); this.selected = bucket; return; } this.selected.classList.remove("selected"); this.selected = null; } vibrate() { const brd = document.getElementById("board"); let timerCnt = 0; const exp = setInterval(() => { if ((timerCnt++) > 60) { clearInterval(exp); brd.style.top = "0px"; brd.style.left = "0px"; } let x = Math.random() * 4, y = Math.random() * 4; if (Math.random() < .5) x = -x; if (Math.random() < .5) y = -y; brd.style.top = y + "px"; brd.style.left = x + "px"; }, 10); } playClick(bucket) { if (this.game_over) return; if (this.selected) { bucket.innerText = this.selected.innerText; bucket.clr = this.selected.clr; } else { this.vibrate(); } } check() { if (this.game_over) return; let code = []; const brd = document.getElementById("board"); for (let b = 0; b < this.codeLen; b++) { const h = document.getElementById(`brd${brd.active + b}`).clr; if (h < 0) { this.vibrate(); return; } code.push(h); } this.guesses++; if (this.compareCode(code)) { this.gameOver(true); return; } if (this.guesses >= this.guessCnt) { this.gameOver(false); return; } this.addGuessLine(brd); } compareCode(code) { let black = 0, white = 0, b_match = new Array(this.codeLen).fill(false), w_match = new Array(this.codeLen).fill(false); for (let i = 0; i < this.codeLen; i++) { if (code[i] === this.code[i]) { b_match[i] = true; w_match[i] = true; black++; } } for (let i = 0; i < this.codeLen; i++) { if (b_match[i]) continue; for (let j = 0; j < this.codeLen; j++) { if (i == j || w_match[j]) continue; if (code[i] === this.code[j]) { w_match[j] = true; white++; break; } } } const brd = document.getElementById("board"); let d; for (let i = 0; i < black; i++) { d = document.createElement("div"); d.className = "pin"; d.style.backgroundColor = "#a00"; brd.appendChild(d); } for (let i = 0; i < white; i++) { d = document.createElement("div"); d.className = "pin"; d.style.backgroundColor = "#eee"; brd.appendChild(d); } return (black == this.codeLen); } gameOver(win) { if (this.game_over) return; this.game_over = true; const cd = document.getElementById("code"); for (let c = 0; c < this.codeLen; c++) { const d = document.createElement("div"); d.className = "bucket"; d.innerText = this.colors[this.code[c]]; cd.appendChild(d); } const go = document.getElementById("gameover"); go.style.visibility = "visible"; go.innerText = win ? "GREAT!" : "YOU FAILED!"; const i = setInterval(() => { go.style.visibility = "hidden"; clearInterval(i); }, 3000); } } const mm = new Mastermind(); document.getElementById("newGame").addEventListener("click", () => { mm.newGame() }); document.getElementById("giveUp").addEventListener("click", () => { mm.gameOver(); }); document.getElementById("check").addEventListener("click", () => { mm.check() });