<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/vader/jquery-ui.css"> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
<table border="0" width="100%"> <thead> <th colspan="2" id="status" class="ui-widget ui-state-hover ui-corner-all"> ...</th> </thead> <tbody> <td id="stats" class="ui-widget" valign="top"><br /><button id="reload"> </button><br /><br /></td> <td id="board" class="ui-widget" valign="top"><div id="masked" class="ui-widget-shadow ui-corner-all ui-widget-overlay"></div> <table class="ui-widget ui-corner-all" cellpadding="0" cellspacing="0" align="left" id="board-table"></table> </td> </tbody> </table>
var TicTacToe = { gameId: null, // ID . turn: null, // , X O i: false, // , init: function() { ... }, // startGame: function (gameId, turn, x, y) { ... }, // mask: function(state) { ... }, // , :) move: function (id, turn, win) { ... }, // endGame: function (turn, win) { ... } // , }
$(function() { // UI $('#reload').button({icons:{primary:'ui-icon-refresh'}}).click(function(){window.location.reload();}); // nodejs socket.io var socket = io.connect(window.location.hostname + ':1337', {resource: 'api'}); // event' () socket.io // socket.on('connect', function () { $('#status').html(' '); }); // socket.on('reconnect', function () { $('#connect-status').html(', '); }); // socket.on('reconnecting', function () { $('#status').html(' , ...'); }); // socket.on('error', function (e) { $('#status').html(': ' + (e ? e : ' ')); }); // // socket.on('wait', function(){ $('#status').append('... ...'); }); // socket.on('exit', function() { // TicTacToe.endGame(TicTacToe.turn, 'exit'); }); // , // ID , xy socket.on('ready', function(gameId, turn, x, y) { $('#status').html(' ! ! ' + (turn == 'X' ? ' ' : ' ') + '!'); // TicTacToe.startGame(gameId, turn, x, y); // , :) $('#stats').append($('<div/>').attr('class', 'turn ui-state-hover ui-corner-all').html(' : <b>' + (turn=='X'?'':'') + '</b>')); // , $("#board-table td").click(function (e) { // , ID ID , XxY if(TicTacToe.i) socket.emit('step', TicTacToe.gameId, e.target.id); // }).hover(function(){ $(this).toggleClass('ui-state-hover'); }, function(){ $(this).toggleClass('ui-state-hover'); }); }); // socket.on('step', function(id, turn, win) { // ID , . win TicTacToe.move(id, turn, win); }); // socket.on('stats', function (arr) { var stats = $('#stats'); stats.find('div').not('.turn').remove(); for(val in arr) { stats.prepend($('<div/>').attr('class', 'ui-state-hover ui-corner-all').html(arr[val])); } }); });
startGame: function (gameId, turn, x, y) { // ID this.gameId = gameId; // this.turn = turn; // , X :) this.i = (turn == 'X'); // var table = $('#board-table').empty(); // for(var i = 1; i <= y; i++) { var tr = $('<tr/>'); for(var j = 0; j < x; j++) { // ID X Y (id="2x3") tr.append($('<td/>').attr('id', (j+1) + 'x' + i).addClass('ui-state-default').html(' ')); } table.append(tr); } // $("#board").show(); // , this.mask(!this.i); },
move: function (id, turn, win) { // : ID , , this.i = (turn != this.turn); // $("#" + id).attr('class', 'ui-state-hover').html(turn); // if (!win) { // , this.mask(!this.i); // $('#status').html(' ' + (this.i ? ' ' : ' ')); // } else { this.endGame(turn, win); // , } },
endGame: function (turn, win) { // : , var text = ''; // 3 switch(win) { case 'none': text = '!'; break; // case 'exit': text = ' ! '; break; // default: text = ' ' + (this.i ? '! =(' : '! =)'); // } // $("<div/>").html(text).dialog({ title: ' ', modal: true, closeOnEscape: false, resizable: false, buttons: { " ": function() { $(this).dialog("close"); window.location.reload(); }}, close: function() { window.location.reload(); } }); }
npm install express npm install socket.io
// var express = require('express'), socketio = require('socket.io'); // express var app = express.createServer(); // express // , var io = socketio.listen(app); // express app.use(express.static(__dirname + '/public')); // app.listen(80); // socket.io 3, io.set('log level', 3); // , /socket.io io.set('resource', '/api');
var express = require('express'), app = express.createServer(), io = require('socket.io').listen(app), TicTacToe = require('./models/tictactoe'); app.use(express.static(__dirname + '/public')); app.listen(1337); io.set('log level', 1); io.set('resource', '/api');
TicTacToe = require('./models/tictactoe');
// , , var TicTacToe = module.exports = function() { // id = this.games = []; // = id this.users = []; // this.free = []; // this.x = 6; this.y = 6; // this.stepsToWin = 4; } // , var GameItem = function(user, opponent, x, y, stepsToWin) { // this.board[id ] = this.board = []; // this.user = user; // X this.opponent = opponent; // O // this.x = x; this.y = y; // this.stepsToWin = stepsToWin; // - this.steps = 0; }
TicTacToe.prototype.start = function(user, cb) { // - // Object.keys if(Object.keys(this.free).length > 0) { // ID var opponent = Object.keys(this.free).shift(); // var game = new GameItem(user, opponent, this.x, this.y, this.stepsToWin); // ID ID var id = user + opponent; // this.games[id] = game; // this.users[user] = id; // this.users[opponent] = id; // callback cb(true, id, opponent, this.x, this.y); } else { // , this.free[user] = true; // callback cb(false); } }
1. --> 2. TicTacToe.start(); 3. <--
1. --> 2. TicTacToe.start(function(){ 3. <-- });
TicTacToe.prototype.end = function(user, cb) { // delete this.free[user]; // , if(this.users[user] === undefined) return; // ID var gameId = this.users[user]; // , if(this.games[gameId] === undefined) return; // ID var game = this.games[gameId]; // var opponent = (user == game.user ? game.opponent : game.user); // delete this.games[gameId]; // game = null; // delete this.users[user]; // ID ID cb(gameId, opponent); }
TicTacToe.prototype.step = function(gameId, x, y, user, cb) { // proxy this.games[gameId].step(x, y, user, cb); } GameItem.prototype.step = function(x, y, user, cb) { // if(this.board[x + 'x' + y] !== undefined) return; // X Y , this.board[x + 'x' + y] = this.getTurn(user); // this.steps++; // cb(this.checkWinner(x, y, this.getTurn(user)), this.getTurn(user)); }
GameItem.prototype.getTurn = function(user) { return (user == this.user ? 'X' : 'O'); }
GameItem.prototype.checkWinner = function(x, y, turn) { // , if(this.steps == (this.x * this.y)) { // return 'none'; // } else if( // this.checkWinnerDynamic('-', x, y, turn) || this.checkWinnerDynamic('|', x, y, turn) || this.checkWinnerDynamic('\\', x , y, turn) || this.checkWinnerDynamic('/', x, y, turn) ) { // return true; } else { // return false; } }
GameItem.prototype.checkWinnerDynamic = function(a, x, y, turn) { // 4 : , 2 // ,, 4 var win = 1; switch(a) { // case '-': var toLeft = toRight = true, min = x - this.stepsToWin, max = x + this.stepsToWin; min = (min < 1) ? 1 : min; max = (max > this.x) ? this.x : max; for(var i = 1; i <= this.stepsToWin; i++) { if(win >= this.stepsToWin) return true; if(!toLeft && !toRight) return false; if(toLeft && min <= (xi) && this.board[(xi) + 'x' + y] == turn) { win++; } else { toLeft = false; } if(toRight && (x+i) <= max && this.board[(x+i) + 'x' + y] == turn) { win++; } else { toRight = false; } } break; // case '|': var toUp = toDown = true, min = y - this.stepsToWin, max = y + this.stepsToWin; min = (min < 1) ? 1 : min; max = (max > this.y) ? this.y : max; for(var i = 1; i <= this.stepsToWin; i++) { if(win >= this.stepsToWin) return true; if(!toUp && !toDown) return false; if(toUp && min <= (yi) && this.board[x + 'x' + (yi)] == turn) { win++; } else { toUp = false; } if(toDown && (y+i) <= max && this.board[x + 'x' + (y+i)] == turn) { win++; } else { toDown = false; } } break; // case '\\': var toUpLeft = toDownRight = true, minX = x - this.stepsToWin, maxX = x + this.stepsToWin, minY = y - this.stepsToWin, maxY = y + this.stepsToWin; minX = (minX < 1) ? 1 : minX; maxX = (maxX > this.x) ? this.x : maxX; minY = (minY < 1) ? 1 : minY; maxY = (maxY > this.y) ? this.y : maxY; for(var i = 1; i <= this.stepsToWin; i++) { if(win >= this.stepsToWin) return true; if(!toUpLeft && !toDownRight) return false; if(toUpLeft && minX <= (xi) && minY <= (yi) && this.board[(xi) + 'x' + (yi)] == turn) { win++; } else { toUpLeft = false; } if(toDownRight && (x+i) <= maxX && (y+i) <= maxY && this.board[(x+i) + 'x' + (y+i)] == turn) { win++; } else { toDownRight = false; } } break; // case '/': var toDownLeft = toUpRight = true, minX = x - this.stepsToWin, maxX = x + this.stepsToWin, minY = y - this.stepsToWin, maxY = y + this.stepsToWin; minX = (minX < 1) ? 1 : minX; maxX = (maxX > this.x) ? this.x : maxX; minY = (minY < 1) ? 1 : minY; maxY = (maxY > this.y) ? this.y : maxY; for(var i = 1; i <= this.stepsToWin; i++) { if(win >= this.stepsToWin) return true; if(!toDownLeft && !toUpRight) return false; if(toDownLeft && minX <= (xi) && (y+i) <= maxY && this.board[(xi) + 'x' + (y+i)] == turn) { win++; } else { toDownLeft = false; } if(toUpRight && (x+i) <= maxX && (yi) <= maxY && this.board[(x+i) + 'x' + (yi)] == turn) { win++; } else { toUpRight = false; } } break; default: return false; break; } return(win >= this.stepsToWin); }
// , , var countGames = onlinePlayers = onlineGames = 0, countPlayers = [], Game = new TicTacToe(); // , Game.x = Game.y = 6; // Default: 6 // - Game.stepsToWin = 4; // Default: 4 // io.sockets.on('connection', function (socket) { // ID IP console.log('%s: %s - connected', socket.id.toString(), socket.handshake.address.address); // stats io.sockets.emit('stats', [ ' : ' + countGames, ' : ' + Object.keys(countPlayers).length, ' : ' + onlineGames, ' : ' + onlinePlayers ]); // 5 , setInterval(function() { io.sockets.emit('stats', [ ' : ' + countGames, ' : ' + Object.keys(countPlayers).length, ' : ' + onlineGames, ' : ' + onlinePlayers ]); }, 5000); // , ID ID md5 Game.start(socket.id.toString(), function(start, gameId, opponent, x, y){ // callback' , // , null if(start) { // ID ID // socket.io socket.join(gameId); // () io.sockets.socket(opponent).join(gameId); // socket.emit('ready', gameId, 'X', x, y); // io.sockets.socket(opponent).emit('ready', gameId, 'O', x, y); // countGames++; onlineGames++; } else { // , io.sockets.socket(socket.id).emit('wait'); } // ip if(countPlayers[socket.handshake.address.address] == undefined) countPlayers[socket.handshake.address.address] = true; // onlinePlayers++; }); // socket.on('step', function (gameId, id) { // ID XxY var coordinates = id.split('x'); // , proxy Game.step(gameId, parseInt(coordinates[0]), parseInt(coordinates[1]), socket.id.toString(), function(win, turn) { // , , // in() io.sockets.in(gameId).emit('step', id, turn, win); // if(win) { // , Game.end(socket.id.toString(), function(gameId, opponent) { // socket.leave(gameId); // io.sockets.socket(opponent).leave(gameId); }); } }); }); // socket.on('disconnect', function () { // , // , Game.end(socket.id.toString(), function(gameId, opponent) { // , Game.end , ID io.sockets.socket(opponent).emit('exit'); // socket.leave(gameId); // io.sockets.socket(opponent).leave(gameId); // onlineGames--; }); // onlinePlayers--; // console.log('%s: %s - disconnected', socket.id.toString(), socket.handshake.address.address); }); });
Source: https://habr.com/ru/post/132544/
All Articles