From 6f9e0a05b80afb0d1cf1b5b0db21bf8d1caa1cc8 Mon Sep 17 00:00:00 2001 From: CoreChg Date: Fri, 21 Sep 2018 18:09:27 -0400 Subject: Version 1.0 Initial release --- index.html | 34 ++++++++ mines.css | 176 +++++++++++++++++++++++++++++++++++++++ mines.js | 276 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 486 insertions(+) create mode 100644 index.html create mode 100644 mines.css create mode 100644 mines.js diff --git a/index.html b/index.html new file mode 100644 index 0000000..662b4ee --- /dev/null +++ b/index.html @@ -0,0 +1,34 @@ + + + + + + + + + + + +
+ +
+ +
+ +
+
+
+

0

0

+
+ + +
+
+ + + \ No newline at end of file diff --git a/mines.css b/mines.css new file mode 100644 index 0000000..552a4e4 --- /dev/null +++ b/mines.css @@ -0,0 +1,176 @@ +*{ + font-family: 'Open Sans', sans-serif; +} + +body{ + text-align: center; +} + +div.selector, div.game{ + display: inline-block; +} + +div.selector{ + text-align: right; +} + +div.game{ + min-width: 25%; + margin-top: 50px; +} + +input{ + padding: 5px; + margin: 5px; + background-color: #eee; + border: none; + border-radius: 5px; + transition-duration: 0.2s; +} + +input:hover{ + background-color: #ccc; +} + +input:focus{ + background-color: #cef; + border: none; +} + +input:active{ + background-color: #cef; + border: none; +} + +button{ + padding: 5px; + margin: 5px; + background-color: #eee; + border: none; + border-radius: 5px; + transition-duration: 0.2s; +} + +button:hover{ + background-color: #ccc; +} + +button:active{ + background-color: #cef; + border: none; +} + +h1{ + width: calc(50% - 70px); + + display: inline; + + background-color: #eee; + + border-radius: 25%; +} + +h1#mines{ + float: left; +} + +h1#time{ + float: right; +} + +/* Table */ + +table{ + display: inline-table; + background-color: #ddd; + border-radius: 10px; + padding: 5px; +} + +td{ + width: 35px; + height: 35px; + + margin: 5px; + padding: 2px; + + background-color: #bbb; + + box-sizing: border-box; + + border-radius: 25%; + + transition-duration: 0.2s; + + cursor: default; +} + +td.wt:hover{ + background-color: #777; +} + +td.wt:active{ + background-color: #999; +} + +td.chkd{ + background-color: #888; +} + +/* Main button */ + +button#circle{ + padding: 35px; + border: none; + border-radius: 50%; + box-sizing: border-box; +} + +button#circle:active{ + border: none; +} + +button#circle.win{ + background-color: #0f4; +} + +button#circle.win:hover{ + background-color: #0d2; +} + +button#circle.lose{ + background-color: #f33; +} + +button#circle.lose:hover{ + background-color: #d11; +} + +button#circle.ingame{ + background-color: #fa0; + animation: 1s infinite alternate shrink; +} + +button#circle.ingame:hover{ + background-color: #d80; +} + +button#circle.loading{ + background-color: #0af; + animation: 1s infinite alternate shrink; +} + +button#circle.loading:hover{ + background-color: #08d; +} + +@keyframes shrink{ + from{ + padding: 35px; + margin-top: 0px; + } + to{ + padding: 15px; + margin-top: 20px + } +} \ No newline at end of file diff --git a/mines.js b/mines.js new file mode 100644 index 0000000..da0fa4d --- /dev/null +++ b/mines.js @@ -0,0 +1,276 @@ +var colors = ["blue", "limegreen", "orange", "red", "purple", "cyan", "gold", "black"]; + +var mine = "\u25C9"; + +function Board(){ + this.sMines = document.getElementById("mines"); + this.sTime = document.getElementById("time"); + + this.circle = document.getElementById("circle"); + + this.table = document.getElementById("gtable"); + this.table.parentElement.addEventListener("contextmenu", function(e){e.preventDefault();}); + + this.mines = [[0]]; + this.mTotal = 0; + this.mChecked = 0; + + this.boardDim = [1, 1]; + this.checked = 0; + + this.time = 0; + this.clock = -1; + + this.running = false; + this.started = false; +} + +Board.prototype = { + + //Second + + sec: function(){ + let c = parseInt(this.sTime.textContent); + c++; + this.sTime.textContent = c; + }, + + //Game states + + win: function(){ + this.running = false; + clearInterval(this.clock); + this.clock = -1; + this.circle.className = "win"; + + this.revealMines("#08d"); + }, + + lose: function(x, y){ + this.running = false; + clearInterval(this.clock); + this.clock = -1; + this.circle.className = "lose"; + + this.revealMines("black"); + + this.getMineEl(x, y).style.color = "red"; + }, + + revealMines: function(color){ + let lp = this.mines.length; + for(let i = 0; i < lp; i++){ + let lp2 = this.mines[i].length; + for(let j = 0; j < lp2; j++){ + let e = this.getMineEl(this.mines[i][j], i); + e.style.color = color; + e.textContent = mine; + } + } + }, + + start: function(x, y){ + this.started = true; + let flag = false; + if(this.isMine(x, y)){ + for(let i = 0; i < this.boardDim[1] && !flag; i++){ + for(let j = 0; j < this.boardDim[0] && !flag; j++){ + if(!this.isMine(j, i)){ + this.mines[i].push(j); + flag = true; + } + } + } + this.mines[y].splice(this.mines[y].indexOf(x), 1); + } + }, + + //Event managers + + click: function(e){ + let el = e.target; + var x = parseInt(el.getAttribute("x")), y = parseInt(el.getAttribute("y")); + + if(!this.running || el.textContent !== "" || el.classList.contains("chkd")) return; + + if(!this.started){ + this.start(x, y); + } + + if(this.isMine(x, y)){ + this.lose(x, y); + return; + } + + this.check(x, y); + }, + + ctxMenu: function(e){ + let el = e.target; + var x = parseInt(el.getAttribute("x")), y = parseInt(el.getAttribute("y")); + + if(el.classList.contains("chkd") || !this.running || !this.started) { + e.preventDefault(); + return; + } + + if(el.textContent == "!"){ + + el.textContent = "?"; + this.mChecked--; + }else if(el.textContent == "?"){ + + el.textContent = ""; + }else{ + + el.textContent = "!"; + this.mChecked++; + } + this.sMines.textContent = this.mTotal - this.mChecked; + e.preventDefault(); + }, + + //Recognizing the click + + isMine: function(x, y){ + if(y >= this.mines.length || y < 0) return false; + return this.mines[y].includes(x); + }, + + isChecked: function(x, y){ + if(y >= this.boardDim[1] || y < 0) return true; + if(x >= this.boardDim[0] || x < 0) return true; + return this.table.children[y].children[x].className == "chkd"; + }, + + numAround: function(x, y){ + let m = 0;let dx = x; + if(this.isMine(dx, y+1)) m++; + if(this.isMine(dx, y-1)) m++; + dx = x+1; + if(this.isMine(dx, y)) m++; + if(this.isMine(dx, y+1)) m++; + if(this.isMine(dx, y-1)) m++; + dx = x-1; + if(this.isMine(dx, y)) m++; + if(this.isMine(dx, y+1)) m++; + if(this.isMine(dx, y-1)) m++; + return m; + }, + + getMineEl: function(x, y){ + return this.table.children[y].children[x]; + }, + + check: function(x, y){ + if(!this.running) return; + + let n = this.numAround(x, y); + let e = this.getMineEl(x, y); + + e.className = "chkd"; + + if(n !== 0){ + + e.style.color = colors[n-1]; + e.textContent = n; + }else{ + + this.findPath(x, y); + } + + this.checked++; + if(this.checked == (this.boardDim[0]*this.boardDim[1] - this.mTotal)) this.win(); + }, + + findPath: function(x, y){ + let dx = x; + if(!this.isChecked(dx, y+1)) this.check(dx, y+1); + if(!this.isChecked(dx, y-1)) this.check(dx, y-1); + dx = x+1; + if(!this.isChecked(dx, y+1)) this.check(dx, y+1); + if(!this.isChecked(dx, y-1)) this.check(dx, y-1); + if(!this.isChecked(dx, y)) this.check(dx, y); + dx = x-1; + if(!this.isChecked(dx, y+1)) this.check(dx, y+1); + if(!this.isChecked(dx, y-1)) this.check(dx, y-1); + if(!this.isChecked(dx, y)) this.check(dx, y); + }, + + //Managing the board + + reset: function(){ + this.circle.className = "loading"; + + let x = xIn.value; + let y = yIn.value; + let mines = mIn.value; + + if(mines >= x*y-1) { + this.circle.className = "lose"; + return; + } + + this.started = false; + + this.boardDim = [x, y]; + + while(this.table.firstChild){ + this.table.firstChild.remove(); + } + + this.mTotal = mines; + this.mChecked = 0; + this.mines = []; + this.checked = 0; + this.sMines.textContent = mines; + + this.sTime.textContent = 0; + if(this.clock !== -1) clearInterval(this.clock); + this.clock = -1; + + let mRarity = x*y*0.8; + + for(let i = 0; i < y; i++){ + + let row = document.createElement("tr"); + + this.mines.push([]); + + for(let j = 0; j < x; j++){ + + let cell = document.createElement("td"); + cell.setAttribute("x", j); + cell.setAttribute("y", i); + cell.classList = ["wt"]; + cell.addEventListener("click", this.click.bind(this)); + cell.addEventListener("contextmenu", this.ctxMenu.bind(this)); + row.appendChild(cell); + + if(mines > 0 && Math.floor(Math.random()*mRarity) == 0){ + this.mines[i].push(j); + mines--; + } + } + + this.table.appendChild(row); + } + + while(mines > 0){ + for(let i = 0; i < y; i++){ + if(mines <= 0) break; + for(let j = 0; j < x; j++){ + if(mines <= 0) break; + if(!this.isMine(j, i) && Math.floor(Math.random()*mRarity) == 0){ + this.mines[i].push(j); + mines--; + } + } + } + } + + this.circle.className = "ingame"; + this.running = true; + this.clock = setInterval(this.sec.bind(this), 1000); + } +}; \ No newline at end of file -- cgit v1.2.3