Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.js"></script>
  
  <script type="text/template" id="template-for-lose">
    <div id="cover"></div>
    <div id="window-lose">
      <p>Вы проиграли!</p>
      <button id="btn">Новая игра</button>
    </div>
  </script>
  
  <script type="text/template" id="template-for-win">
    <div id="cover"></div>
    <div id="window-win">
      <p>Вы победили!</p>
      <button id="btn">Новая игра</button>
    </div>
  </script>
</body>
</html>
 
body {
  text-align: center;
}
td { 
  width: 28px; 
  height: 28px; 
  background: #08a3db; 
  border: 1px solid #2352ce; 
  cursor: pointer; 
  text-align: center; 
  border-radius: 1px;
  color: black;
  font-family: 'Arial', sans-serif;
  font-weight: bold;
} 
table { 
  border-collapse: collapse; 
  margin: 0 auto;
}
#cover {
  position: fixed;
  width: 100%;
  height: 100%;
  background: gray;
  opacity: 0.3;
  z-index: 9000;
}
#window-lose { 
  display: inline-block;
  position: absolute;
  width: 60%;
  height: 100px;
  vertical-align: middle;
  text-align: center;
  background: #FF3300;
  border: 2px solid #FF1100;
  z-index: 9999;
}
#window-win {
  display: inline-block;
  position: absolute;
  width: 60%;
  height: 100px;
  vertical-align: middle;
  text-align: center;
  background: grey;
  border: 2px soid white;
  border-radius: 5px;
  z-index: 9999;
}
.open-cell {
  background: #CCFFFF;
}
.close-cell {
  background: #08a3db;
}
#btn {
  display: inline-block;
  width: 120px;
  padding: 5px;
  margin: 0 auto;;
  text-align: center;
  vertical-align: bottom;
  border: 2px solid green;
  background: white;
  border-radius: 3px;
  cursor: pointer;
}
 
"// noprotect";
function Util() {
  
}
Util.trim = function(str) {
  return str.replace(/^\s+|\s+$/g,"");
};
Util.hasClass = function(node, klass) {
  var classes = ' ' + node.className.replace(/\s/, ' ') + ' ';
  
  if ( classes.indexOf(' ' + klass + ' ') >= 0 ) { 
    return true; 
  }
  
  return false;
};
Util.addClass = function(node, klass) {
  if ( !Util.hasClass(node, klass) ) {
    if ( node.className.length !== 0 ) {
      node.className += ' ' + klass;
    } else {
      node.className = klass;
    }
  }
  
  return node;
};
Util.removeClass = function(node, klass) {
  if ( Util.hasClass(node, klass) ) {
    var classes = ' ' + node.className + ' ',
        regexp = new RegExp(" " + klass + "(?= )", 'g');
    
    node.className = Util.trim( classes.replace(regexp, ' ') );
  }
  
  return node;
};
Util.toggleClass = function(node, klass) {
  if ( !Util.hasClass(node, klass) ) {
    return Util.addClass(node, klass);
  } else {
    return Util.removeClass(node, klass);
  }
};
Util.clearClass = function(node) {
  node.className = '';
};
Util.hasContentOfTag = function(node, content) {
  var contentStr = node.innerHTML;
  
  if ( contentStr == content) { 
    return true; 
  }
  
  return false;
};
Util.addContentOfTag = function(node, content) {
  node.innerHTML = content;
};
Util.removeContentOfTag = function(node, content) {
  node.innerHTML = '';
};
Util.toggleContentOfTag = function(node, content) {
  if ( !Util.hasContentOfTag(node, content) ) {
    Util.addContentOfTag(node, content);
  } else {
    Util.removeContentOfTag(node, content);
  }
};
Util.getRandom = function(size) {
  return Math.floor(Math.random()*size);
};
Util.showWindow = function(self, id, clickOnBtn) {
  var tpl = document.getElementById(id).innerHTML,
      result = _.template(tpl, 1);
  
  document.body.insertAdjacentHTML('afterBegin', result);
  
  var button = document.getElementById('btn');
button.addEventListener('click', function(event) {
  event.preventDefault();
  
  clickOnBtn(self);
});
  /*var button = document.getElementById('btn');
button.addEventListener('click', function(event) {
  event.preventDefault();
  
  Util.clickBtn(self);
});*/
};
Util.showLoseWindow = function(self) {
  Util.showWindow(self, 'template-for-lose');
};
Util.showWinWindow = function(self) {
  Util.showWindow(self, 'template-for-win');
};
Util.removeWindow = function() {
  var body = document.body,
      window = document.getElementById('window-lose') || document.getElementById('window-win'),
      cover = document.getElementById('cover');
  
  body.removeChild(window);
  body.removeChild(cover);
};
Util.clickBtn = function(self) {
  self.makeNewGame();
};
function Field(width, height, mines) {
  this.width = width;
  this.height = height;
  this.mines = mines;
  this.amountCells = this.width * this.height;
}
Field.prototype.generateField = function() {
  var body = document.body,
      table = document.createElement('table'),
      tr,
      td;
  
  body.insertBefore(table, body.firstChild);
  
  this.table = table;
  this.cells = [];
  
  this.generateCells();
  
  /*for (var x = 0; x < this.width; x++) {
    tr = table.insertRow();
    
    this.cells[x] = [];
    
    for (var y = 0; y < this.height; y++) {
      td = tr.insertCell();
      this.cells[x][y] = new Cell(td, x, y);
    }
  }*/
};
Field.prototype.generateCells = function() {
  var tr, td;
  
  for (var x = 0; x < this.width; x++) {
    tr = this.table.insertRow();
    
    this.cells[x] = [];
    
    for (var y = 0; y < this.height; y++) {
      td = tr.insertCell();
      this.cells[x][y] = new Cell(td, x, y);
    }
  }
};
Field.prototype.generateMines = function() {
  var x, y;
  var i = 0;
  
  while (i < this.mines) {
    x = Util.getRandom(this.width);
    y = Util.getRandom(this.height);
    
    if ( !this.getCellAt(x, y).checkHasMine() ) {
      this.getCellAt(x, y).miningCell();
      console.log(x + ' ' + y);
      i++;
    }
  }
};
Field.prototype.getCellAt = function(x, y) {
  return this.cells[x][y];
};
Field.prototype.getCell = function(td) {
  for (var x = 0; this.width > x; x++) {
    for (var y = 0; this.height > y; y++) {
      if (this.getCellAt(x, y).getTd() == td) {
        return this.cells[x][y];
      }
    }
  }
};
Field.prototype.calcMinesAround = function(cell) {
  var mines = 0,
      cells = this.getNeighboars(cell);
      
  for (var i = 0; i < cells.length; i++) {
    if (cells[i].checkHasMine() === true) {
      mines++;
    }
  }
  
  return mines;
};
Field.prototype.getNeighboars = function(cell) {
  var cells = [];
  
  var posX = cell.getCoorByCell().x,
      posY = cell.getCoorByCell().y;
  
  for (var x = posX - 1; x <= posX + 1; x++) {
    for (var y = posY - 1; y <= posY + 1; y++) {
      if ( this.cellExists(x, y) ) {
        if ( x != posX || y != posY ) {
          cells.push(this.getCellAt(x, y));
        }
      }
    }
  }
  
  return cells;
};
Field.prototype.cellExists = function(x, y) {
  if ( this.cells[x] !== undefined && this.cells[x][y] !== undefined) {
    return true;
  }
  
  return false;
};
Field.prototype.openNullCells = function(cell) {
  var neighbCells = this.getNeighboars(cell);
  
  cell.showOpenCell();
  
  for (var i = 0; i < neighbCells.length; i++) {
    
    this.openCell(neighbCells[i]);
    
  }
};
Field.prototype.openCell = function(cell) {
  var td = cell.getTd(),
      status = cell.getStatus();
  
  if (status === false) {
    if (cell.checkHasMine() === true) {
      var self = this;
      
      cell.showMine(td);
      Util.showWindow(self, 'template-for-lose', function(self) {
                              self.makeNewGame();
                          });
    }
  
    if (cell.checkHasMine() === false) {
      var mines = this.calcMinesAround(cell);
    
      if (mines !== 0) {
        cell.showAmountMines(mines, td);
      }
    
      if (mines === 0) {
        this.openNullCells(cell);
      }
    }
  }
};
Field.prototype.checkWin = function() {
  var amount = 0,
      cell;
  
  for (var x = 0; this.width > x; x++) {
    for (var y = 0; this.height > y; y++) {
      cell = this.getCellAt(x, y);
      if ( cell.getStatus() === true && cell.checkHasMine() === false) {
        amount++;
      }
    }
  }
  
  if (amount == this.amountCells - this.mines) {
    var self = this;
    Util.showWindow(self, 'template-for-win', function(self) {
                              self.makeNewGame();
                          });
  }
};
Field.prototype.makeNewGame = function() {
  this.clearField();
  this.generateCells();
  this.generateMines();
  this.closeCells();
  Util.removeWindow();
};
Field.prototype.closeCells = function() {
  for (var x = 0; this.width > x; x++) {
    for (var y = 0; this.height > y; y++) {
      var td = this.cells[x][y].getTd();
      
      Util.clearClass(td);
      Util.addClass(td, 'close-cell');
    }
  }
};
Field.prototype.clearField = function() {
  this.table.innerHTML = '';
};
function Cell(td, x, y) {
  this.td = td;
  this.hasMine = false;
  this.x = x;
  this.y = y;
  this.isOpened = false;
  this.isFlag = false;
}
Cell.prototype.miningCell = function() {
  this.hasMine = true;
};
Cell.prototype.checkHasMine = function() {
  if (this.hasMine) {
    return true;
  }
  
  return false;
};
Cell.prototype.getTd = function() {
  return this.td;
};
Cell.prototype.getCoorByCell = function() {
  return {'x': this.x, 'y': this.y};
};
Cell.prototype.getStatus = function() {
  return this.isOpened;
};
Cell.prototype.changeStatus = function() {
  this.isOpened = true;
};
Cell.prototype.closeCell = function() {
  this.isOpened = false;
};
Cell.prototype.showOpenCell = function() {
  this.changeStatus();
  Util.clearClass(this.getTd());
  Util.addClass(this.getTd(), 'open-cell');
};
Cell.prototype.showMine = function(td) {
  this.showOpenCell();
  td.innerHTML = '<span>☢</span>';
};
Cell.prototype.showAmountMines = function(mines, td) {
  this.showOpenCell();
  td.innerHTML = '<span>' + mines +'</span>';
};
Cell.prototype.hasFlag = function() {
  return this.isFlag;
};
Cell.prototype.changeHasFlag = function() {
  this.isFlag = !this.isFlag;
};
Cell.prototype.toggleFlag = function() {
  Util.toggleContentOfTag(this.getTd(), '<span>⚑</span>');
};
var field1 = new Field(10, 10, 10);
field1.generateField();
field1.generateMines();
field1.table.addEventListener('mousedown', function(event) {
  event.preventDefault();
  
  var target = event.target;
  
  while (target.tagName != 'TD') {
    target = target.parentNode;
  }
  
  var cell = field1.getCell(target),
      status = cell.getStatus(),
      flag = cell.hasFlag();
  
  if (target.tagName == 'TD') {
    target.setAttribute('oncontextmenu', '; return false');
    
    if (event.which == 1 && flag === false) {
      field1.openCell(cell);
      field1.checkWin();
    } else if ( event.which == 3 && status === false ) {
      cell.changeHasFlag();
      cell.toggleFlag();
    }
  }
});
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
anonymouspro
0viewers