/** * @author xiangshouding */ class Box { constructor(x, y, icon) { this.x = x; this.y = y; this.icon = icon; } } class Board { constructor(w, h) { this.w = w; this.h = h; this.p = []; } fill() { var x, y; var icon = this.getIcon(); for (y = 0; y < this.h; y++) { for (x = 0; x < this.w; x++) { if (!this.p[x]) { this.p[x] = []; } this.p[x][y] = new Box(x, y, icon()); } } } isBlocked(x, y) { try { var current = this.p[x][y]; return current.icon; } catch (err) { //console.error(err); } return false; } /** * check horizon */ vertical(p0, p1) { if (p0.x == p1.x && p0.y == p1.y) { return false; } if (p0.x != p1.x) { return false; } var start = Math.min(p0.y, p1.y), end = Math.max(p0.y, p1.y); if (end - start == 1) { return true; } for (var y = start + 1; y < end; y++) { if (this.isBlocked(p0.x, y)) { return false; } } return true; } horizon(p0, p1) { if (p0.x == p1.x && p0.y == p1.y) { return false; } if (p0.y != p1.y) { return false; } var start = Math.min(p0.x, p1.x), end = Math.max(p0.x, p1.x); if (end - start == 1) { return true; } for (var x = start + 1; x < end; x++) { if (this.isBlocked(x, p0.y)) { return false; } } return true; } turnOnce(p0, p1) { if (p0.x == p1.x && p0.y == p1.y) { return false; } var ret = false; if (!this.isBlocked(p0.x, p1.y)) { ret = this.horizon(p0, {x: p0.x, y: p1.y}) && this.vertical({x: p0.x, y: p1.y}, p1); } if (!this.isBlocked(p1.x, p0.y)) { ret = this.horizon(p0, {x: p1.x, y: p0.y}) && this.vertical({x: p1.x, y: p0.y}, p1); } return ret; } turnTwice(p0, p1) { if (p0.x == p1.x && p0.y == p1.y) { return false; } for (var x = 0; x <= this.w; x++) { for (var y = 0; y <= this.h; y++) { if (x != p0.x && x != p1.x && y != p1.y && y != p1.y) { continue; } if ((x == p0.x && y == p0.y) || (x == p1.x && y == p1.y)) { continue; } if (this.isBlocked(x, y)) { continue; } if (this.turnOnce(p0, {x: x, y: y}) && (this.horizon({x: x, y: y}, p1) || this.vertical({x: x, y: y}, p1))) { return true; } if (this.turnOnce({x: x, y: y}, p1) && (this.horizon(p0, {x: x, y: y}) || this.vertical(p0, {x: x, y: y}))) { return true; } } } return false; } clear(x0, y0, x1, y1) { var p0 = {x: x0, y: y0}, p1 = {x: x1, y: y1}; if (this.p[x0][y0].icon != this.p[x1][y1].icon) { return false; } if (this.horizon(p0, p1)) { return true; } if (this.vertical(p0, p1)) { return true; } if (this.turnOnce(p0, p1)) { return true; } if (this.turnTwice(p0, p1)) { return true; } return false; } remove(x0, y0, x1, y1) { if (this.clear(x0, y0, x1, y1)) { this.p[x0][y0] = null; this.p[x1][y1] = null; return true; } return false; } render() { this.fill(); var x, y; var app = document.getElementById('app'); for (y = 0; y < this.h; y++) { for (x = 0; x < this.w; x++) { var node = document.createElement('div'); node.setAttribute('class', 'box'); node.setAttribute('x', x); node.setAttribute('y', y); node.setAttribute('ref', 'box'); node.innerText = this.p[x][y].icon; app.appendChild(node); } var br = document.createElement('br'); app.appendChild(br); } } shuffle(array) { var currentIndex = array.length , temporaryValue , randomIndex; while (0 !== currentIndex) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; temporaryValue = array[currentIndex]; array[currentIndex] = array[randomIndex]; array[randomIndex] = temporaryValue; } return array; } getIcon() { var icons = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '@', '#', '$', '%', '&', '!', '*']; var m = icons.length, cls = Math.floor(m / 2 + Math.random() * m); var times = Math.floor(this.w * this.h / cls); if (times % 2 != 0) { times -= 1; } if (times === 0) { times = 2; } var array = []; for (var i = 0; i < this.w * this.h; i += times) { for (var j = 0; j < times; j++) { array.push(icons[i % m]); } } array = this.shuffle(array); var index = 0; return function (x, y) { return array[index++]; }; } } function main() { var board = new Board(4, 4); board.render(); return board; } function getPosFromDom(elm, axial) { return parseInt(elm.getAttribute(axial)); } function mount() { var board = main(); var queue = []; window.addEventListener('click', function (e) { if (e.target.getAttribute('ref') != 'box') { return; } if (queue.length != 2) { queue.push(e.target); if (queue.length == 2) { try { var isClear = board.remove( getPosFromDom(queue[0], 'x'), getPosFromDom(queue[0], 'y'), getPosFromDom(queue[1], 'x'), getPosFromDom(queue[1], 'y') ); if (isClear) { queue[0].setAttribute('class', 'box done'); queue[0].innerHTML = ' '; queue[1].setAttribute('class', 'box done'); queue[1].innerHTML = ' '; } else { alert('Error, Please choice two same icon box.') } } catch (err) { console.error(err); } queue = []; // clear stack } } else { queue = []; } }) } function clear() { } window.onload = mount;