Skip to content

Instantly share code, notes, and snippets.

@jozsefs
Created November 24, 2017 12:47
Show Gist options
  • Save jozsefs/fa1bca24475d5b8735f0c53baa01867f to your computer and use it in GitHub Desktop.
Save jozsefs/fa1bca24475d5b8735f0c53baa01867f to your computer and use it in GitHub Desktop.
multi-minesweeper-server
// server.js
const io = require('socket.io')(1234);
const Board = require('./board');
const game = new Board({size: 15, mineChance: 0.3});
const PLAYER_PREFIX = 'p-';
const players = {};
const cellsToReveal = [];
let counter = 0;
io.on('connection', socket => {
const {id} = socket;
const name = PLAYER_PREFIX + (++counter);
const player = {
id,
name,
score: 0,
hasChosen: false
};
players[id] = player;
socket.on('disconnect', reason => {
delete players[id];
});
socket.on('choose-cell', pos => {
chooseCell(socket, id, pos);
});
socket.on('restart', code => {
if (code === 'supersecret') {
reset();
}
});
socket.emit('new-player', {player});
});
function reset() {
Object.values(players).forEach(player => {
player.hasChosen = false;
player.score = 0;
})
}
function chooseCell(socket, socketId, pos) {
//console.log('choose 1', socketId, pos);
if (!players[socketId].hasChosen) {
const success = game.chooseCell(pos);
//console.log('choose 2', success);
if (success) {
players[socketId].hasChosen = true;
cellsToReveal.push({pos, socketId});
}
}
io.sockets.emit('cell-chosen', {pos, socketId});
}
function getRevealedBoard() {
return game.getBoard().map(row =>
row.map(cell =>
cell.isRevealed ? cell.value : null
)
)
}
function loop() {
//console.log(JSON.stringify([cellsToReveal, players], null, 2));
while (cellsToReveal.length) {
const {pos, socketId} = cellsToReveal.shift();
const {value, isMine} = game.revealCell(pos);
players[socketId].score += isMine ? value : 1;
players[socketId].hasChosen = false;
}
io.sockets.emit('board', getRevealedBoard());
io.sockets.emit('players', players);
}
setInterval(loop, 1000);
// board.js
// BOARD
const MINE = 'X';
const pos = [
// above
[-1, -1],
[ 0, -1],
[ 1, -1],
// same level
[-1, 0],
[ 1, 0],
// below
[-1, 1],
[ 0, 1],
[ 1, 1],
];
class Board {
constructor({size, mineChance}) {
this.rows = size;
this.cols = size;
this.mineChance = mineChance;
this.isStarted = false;
this.gameArea = [];
this.createGameArea();
}
createGameArea() {
let gameArea = [];
for (let i = 0; i < this.rows; i++) {
gameArea.push([]);
const row = gameArea[i];
for (let j = 0; j < this.cols; j++) {
const isMine = Math.random() > (1 - this.mineChance);
const value = isMine ? -10 : 0;
row.push({value, isMine, isRevealed: false, isLocked: false})
}
}
this.gameArea = this.setNumberAmounts(gameArea);
}
getBoard() {
return this.gameArea;
}
setNumberAmounts(gameArea) {
const newTable = gameArea.slice();
for (let i = 0; i < this.rows; i++) {
const row = newTable[i];
for (let j = 0; j < this.cols; j++) {
const cell = row[j];
if (!cell.isMine) {
const amount = this.calcMinesAround(newTable, i, j);
row[j].value = amount;
}
}
}
return newTable;
}
calcMinesAround(gameArea, x, y) {
let sum = 0;
for (let i = 0; i < pos.length; i++) {
const row = gameArea[x + pos[i][0]];
if (row) {
const cell = row[y + pos[i][1]];
if (cell && cell.isMine) {
sum++;
}
}
}
return sum;
}
chooseCell({x, y}) {
const cell = this.gameArea[x][y];
if (cell.isRevealed || cell.isLocked) {
return false;
}
cell.isLocked = true;
return true;
}
revealCell({x, y}) {
const cell = this.gameArea[x][y];
const {value, isMine} = cell;
cell.isRevealed = true;
return {value, isMine};
}
}
module.exports = Board;
// Dockerfile
FROM node:carbon
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./
RUN npm install --only=production
# Bundle app source
COPY . .
EXPOSE 1234
CMD [ "node", "app" ]
// running it
// docker build -t js/rn-minesweeper-server .
// docker run -p 9999:1234 -d js/rn-minesweeper-server
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment