https://cs.lmu.edu/~ray/notes/websockets/

ws_tictactoeserver.js

// A server for a multi-player tic tac toe game. Loosely based on an example in
// Deitel and Deitel’s “Java How to Program” book. For this project I created a
// new application-level protocol called TTTP (for Tic Tac Toe Protocol), which
// is entirely plain text. The messages of TTTP are:
//
// Client -> Server
//     MOVE <n>
//     QUIT
//
// Server -> Client
//     WELCOME <char>
//     VALID_MOVE
//     OTHER_PLAYER_MOVED <n>
//     OTHER_PLAYER_LEFT
//     VICTORY
//     DEFEAT
//     TIE
//     MESSAGE <text>const WebSocket = require('ws');const server = new WebSocket.Server({port: 58901});(() => {// When null, we are waiting for the first player to connect, after which we will// create a new game. After the second player connects, the game can be fully set// up and played, and this variable immediately set back to null so the future// connections make new games.let game = null;server.on('connection', (ws, req) => {console.log('Connection from', req.connection.remoteAddress);if (game === null) {game = new Game();game.playerX = new Player(game, ws, 'X');} else {game.playerO = new Player(game, ws, 'O');game = null;}});console.log('The Tic Tac Toe server is running...');
})();class Game {// A board has nine squares. Each square is either unowned or it is owned by a// player. So we use a simple array of player references. If null, the corresponding// square is unowned, otherwise the array cell stores a reference to the player that// owns it.constructor() {this.board = Array(9).fill(null);}hasWinner() {const b = this.board;const wins = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]];return wins.some(([x, y, z]) => b[x] != null && b[x] === b[y] && b[y] === b[z]);}boardFilledUp() {return this.board.every(square => square !== null);}move(location, player) {if (player !== this.currentPlayer) {throw new Error('Not your turn');} else if (!player.opponent) {throw new Error('You don’t have an opponent yet');} else if (this.board[location] !== null) {throw new Error('Cell already occupied');}this.board[location] = this.currentPlayer;this.currentPlayer = this.currentPlayer.opponent;}
}class Player {constructor(game, socket, mark) {Object.assign(this, {game, socket, mark});this.send(`WELCOME ${mark}`);if (mark === 'X') {game.currentPlayer = this;this.send('MESSAGE Waiting for opponent to connect');} else {this.opponent = game.playerX;this.opponent.opponent = this;this.send('MESSAGE Your opponent will move first');this.opponent.send('MESSAGE Your move');}socket.on('message', (buffer) => {const command = buffer.toString('utf-8').trim();console.log(`Received ${command}`);if (command === 'QUIT') {socket.close();} else if (/^MOVE \d+$/.test(command)) {const location = Number(command.substring(5));try {game.move(location, this);this.send(`VALID_MOVE ${location}`);this.opponent.send(`OPPONENT_MOVED ${location}`);if (this.game.hasWinner()) {this.send('VICTORY');this.opponent.send('DEFEAT');} else if (this.game.boardFilledUp()) {[this, this.opponent].forEach(p => p.send('TIE'));}} catch (e) {console.trace(e);this.send(`MESSAGE ${e.message}`);}}});socket.on('close', () => {try {this.opponent.send('OTHER_PLAYER_LEFT');} catch (e) {}});}send(message) {try {this.socket.send(`${message}\n`);} catch (e) {console.error(e);}}
}

ws_tictactoeclient.html

<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html><head><title>Tic Tac Toe</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link href='tictactoe.css' rel='stylesheet'></head><body><h1>Tic Tac Toe</h1><p id="info">Click the Join Game button when ready</p><section id="board"></section><footer><button id="join">Join Game at Server:</button><input id="serverIp"><button id="leave">Leave Game</button></footer><script src='tictactoe.js' type='text/javascript'></script></body>
</html>

tictactoe.css

section {display: grid;grid-template-rows: 1fr 1fr 1fr;grid-template-columns: 1fr 1fr 1fr;grid-gap: 5px;height: 300px;width: 300px;background-color: black;
}section div {display: grid;justify-items: center;align-items: center;cursor: pointer;background-color: white;color: blue;font: bold 60px Arial;
}#leave {display: none;
}footer {margin-top: 20px;
}

tictactoe.js

const section = document.querySelector('section');
const messageArea = document.querySelector('#info');
const square = location => document.querySelector(`#s${location}`);
const joinButton = document.querySelector('#join');
const leaveButton = document.querySelector('#leave');
const serverTextField = document.querySelector('#serverIp');joinButton.addEventListener('click', joinGame);
leaveButton.addEventListener('click', () => leaveGame('Bye!'));let socket, mark, gameOver = false;addEventListener('load', () => {for (let i = 0; i < 9; i++) {const square = document.createElement('div');square.setAttribute('id', `s${i}`);square.addEventListener('click', () => {socket.send(`MOVE ${i}`);});section.appendChild(square);}
});function joinGame() {const host = serverTextField.value || 'localhost';gameOver = false;socket = new WebSocket(`ws://${host}:58901`);socket.addEventListener('message', (event) => {processCommand(event.data);});document.querySelectorAll('section div').forEach(s => s.textContent = '');joinButton.style.display = 'none';serverTextField.style.display = 'none';leaveButton.style.display = 'inline';socket.onerror = () => leaveGame("Error: The server is probably down");
}
;function leaveGame(message) {messageArea.textContent = message || 'Game over';socket.send('QUIT');gameOver = true;joinButton.style.display = 'inline';serverTextField.style.display = 'inline';leaveButton.style.display = 'none';
}
;function processCommand(command) {if (command.startsWith('WELCOME')) {mark = command[8];opponentMark = mark === 'X' ? 'O' : 'X';} else if (command.startsWith('VALID_MOVE')) {square(command.substring(11)).textContent = mark;messageArea.textContent = 'Valid move, please wait';} else if (command.startsWith('OPPONENT_MOVED')) {square(command.substring(15)).textContent = opponentMark;messageArea.textContent = 'Opponent moved, your turn';} else if (command.startsWith('MESSAGE')) {messageArea.textContent = command.substring(8);} else if (command.startsWith('VICTORY')) {leaveGame('WINNER WINNER');} else if (command.startsWith('DEFEAT')) {leaveGame('Oh sorry you lost');} else if (command.startsWith('TIE')) {leaveGame('Tie game so boring');} else if (command.startsWith('OTHER_PLAYER_LEFT')) {leaveGame(!gameOver ? 'Woah your opponent bailed' : '');}
}

package.json

{"name": "capitalize","version": "1.0.0","keywords": ["util","functional","server","client","browser"],"author": "Administrator","contributors": [],"dependencies": {"ws": "~8.1.0"}
}

Node.js Websocket 井字棋游戏相关推荐

  1. php 井字棋,怎样用JS做出井字棋游戏

    这次给大家带来怎样用JS做出井字棋游戏,用JS做出井字棋游戏的注意事项有哪些,下面就是实战案例,一起来看一下. 最近有一门课结束了,需要做一个井字棋的游戏,我用JavaScript写了一个.首先界面应 ...

  2. php井字游戏代码_JS实现井字棋游戏步骤详解

    这次给大家带来JS实现井字棋游戏步骤详解,JS实现井字棋游戏的注意事项有哪些,下面就是实战案例,一起来看一下. 最近有一门课结束了,需要做一个井字棋的游戏,我用JavaScript写了一个.首先界面应 ...

  3. Minimax 和 Alpha-beta 剪枝算法简介,及以此实现的井字棋游戏(Tic-tac-toe)

    前段时间用 React 写了个2048 游戏来练练手,准备用来回顾下 React 相关的各种技术,以及试验一下新技术.在写这个2048的过程中,我考虑是否可以在其中加入一个 AI 算法来自动进行游戏, ...

  4. React官网的井字棋游戏

    React官网的井字棋游戏 这个是我在官网再次复习这个小游戏时梳理的一些思路,其中也包含了我在尝试时出的一些bug 文章目录 React官网的井字棋游戏 1.整体分析项目 2.为变量添加state并绑 ...

  5. JavaScript 进阶——井字棋游戏智能AI搭建

    目录 井字棋游戏 准备的HTML: 准备的CSS: 第一部分点击出现O的JS代码: 现阶段效果: 第二部分:判断胜利 现阶段结果: 第三部分:简单的智能AI 现阶段结果: 第四部分:之前我们很容易就能 ...

  6. java井字棋ai_JavaScript实现一个带AI的井字棋游戏源码

    JavaScript实现一个带AI的井字棋游戏源码 发布时间:2020-09-05 00:56:12 来源:脚本之家 阅读:100 作者:小楼夜听雨QAQ 最近有一门课结束了,需要做一个井字棋的游戏, ...

  7. php井字游戏,python实现井字棋游戏

    #本游戏python3.4.0下编写调试,只能在windows下运行. import random import subprocess import time #定义函数 def draw_board ...

  8. C++井字棋游戏,DOS界面版

    据说有一个能保证不败的算法.明天看看先再写个PVC版的. 正题.今天无聊写了个井字棋游戏,顺便逐渐让自己习惯良好的代码风格,放上来给新手学习学习. jzq2.cpp /*N字棋游戏PVP版,DOS版本 ...

  9. python井字棋ai_[Python100行系列]-井字棋游戏

    博客:Hzy的博客 | Hzy Blog​hzeyuan.cn一些学习python的小项目,小游戏.python小项目​github.com 话不多说,今天尝试用turtle库来写一个井字棋游戏.1. ...

最新文章

  1. uva 10183 How many Fibs?
  2. Matlab编程与数据类型 -- 开关语句switch/end
  3. nginx日记分割脚本
  4. 微服务架构实践之服务注册发现与调用
  5. IT从花钱到赚钱——惠普IT转型记
  6. 里bl2和bl3为什么分开_施工现场乙炔瓶为什么必须直立?乙炔为什么不能用尽?........
  7. VS2017-VC++中慎用sizeof
  8. linux ubuntu 切换到超级用户失败的解决办法(su 认证失败)
  9. 萌宠历险记html5游戏在线玩,《神武2》天外魔境现世 萌宠历险记首发
  10. 不是明年年初?苹果明年三季度才会推出AirPods Pro 2
  11. unique() 去重函数
  12. 力软 框架 转 mysql_开发框架-.Net:Learun(力软敏捷开发)
  13. 华为自带计算机怎么算平方立方,智能家庭中心:华为荣耀立方体验评测
  14. Android 代码中执行adb shell命令
  15. python爬取拼多多数据 verifyauthtoken_拼多多TOKEN授权
  16. 知识点滴 - 关于苹果认证MFI
  17. HDU6069(数学)
  18. 数据库课程设计:图书信息管理系统(Java+MySQL)(附程序)
  19. 配置opencv,丢失 opencv_world300d.dll
  20. python京东图书信息抓取

热门文章

  1. 十八、阿里云api调用
  2. 使用QImage生成纯透明png图片
  3. 第一章 C语言编程(Ivor Horton)
  4. 用JS实现贪吃蛇小游戏
  5. 微信企业号接入微信支付
  6. java中获得词根的方法_分析在各大考纲词汇中同时拥有前缀后缀和词根的词(一)...
  7. 好奇那些进了大厂的程序员面试前都做了哪些准备?Android大厂面试官全套教程教你:这样准备面试顺利拿到offer
  8. 作业帮-后台开发岗 面经
  9. 块元素盒子内容被撑开
  10. 视频教程-德国Vue.js2终极开发教程(含Vue路由和Vuex)-Vue