https://download.csdn.net/download/xuhangsong/10579033   完整项目下载地址

几年前写的一个webSocket实现的五子棋对战功能,这次整理下分享一下,顺便以后自己也能回忆起来。

实现很简单,就一个html,一个js,再加个websocket.java和封装的传输类就能实现一个可以对战,可以发消息的五子棋功能,那是竟然还在用jdk1.7开发。。

接下来上代码,因为代码中当时写的时候加了注释,我现在回过来看很好理解各种业务设计,给我节约了很多时间。

chess.html页面

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><script type="text/javascript" src="../js/jquery-1.12.3.min.js" ></script><script type="text/javascript" src="../js/json2.js" ></script><script type="text/javascript" src="../js/rule.js" ></script><style type="text/css">#background{position: relative;margin: 20px auto;/*background: #EAC000;*/}.chessman{border-radius: 15px;width: 30px;height: 30px;margin: 0 auto;}.white{background-color:white ;}.black{background-color: black;}.grid,.b_grid{float: left;}.message{width: 320px;height: 100px;margin: 0 auto;}#messageContent{width: 320px;height: 80px;}</style></head><body><div id="background"><!--<div id="back_grid"></div>--><div id="chess"></div></div><div class="message"><textarea id="messageContent" disabled="disabled" readonly="readonly"></textarea><div><input id="message"/> <button onclick="WuZiQi.sendMessage()">发送</button></div></div></body>
</html>

rule.js,具体前端功能的实现都在这个js中了,棋盘背景是用canvas画的,上面盖着div块,用来落子><

var bout = false;//是否允许落子
var color = "";//自己落子颜色
var websocket = null;
var row = 15;
var col = 15;
var widthAndHeight = 30;//格子宽度高度
var WuZiQi = {isEnd:function(xy,chessmanColor){//判断是否结束游戏var id = parseInt(xy);//竖的计算var num = 1;num = WuZiQi.shujia(num,id,chessmanColor);num = WuZiQi.shujian(num,id,chessmanColor);if(num>=5){if(chessmanColor==color){confirm("游戏结束!你赢了!");}else{confirm("游戏结束!你输了!");}return ;}num = 1;num = WuZiQi.hengjia(num,id,chessmanColor);num = WuZiQi.hengjian(num,id,chessmanColor);if(num>=5){if(chessmanColor==color){confirm("游戏结束!你赢了!");}else{confirm("游戏结束!你输了!");}return ;}
;       num = 1;num = WuZiQi.zuoxiejia(num,id,chessmanColor);num = WuZiQi.zuoxiejian(num,id,chessmanColor);if(num>=5){if(chessmanColor==color){confirm("游戏结束!你赢了!");}else{confirm("游戏结束!你输了!");}return ;}num = 1;num = WuZiQi.youxiejia(num,id,chessmanColor);num = WuZiQi.youxiejian(num,id,chessmanColor);if(num>=5){if(chessmanColor==color){confirm("游戏结束!你赢了!");}else{confirm("游戏结束!你输了!");}return ;}},youxiejia:function(num,id,color){var yu = id%row;id = id+(row-1);if(id<(row*col)&&(id%row)<yu){var flag = WuZiQi.checkColor(id,color);if(flag){num++;return WuZiQi.youxiejia(num,id,color);}else{return num;}}else{return num;}},youxiejian:function(num,id,color){var yu = id%row;id = id-(row-1);if(id>=0&&(id%row)>yu){var flag = WuZiQi.checkColor(id,color);if(flag){num++;return WuZiQi.youxiejian(num,id,color);}else{return num;}}else{return num;}},zuoxiejia:function(num,id,color){var yu = id%row;id = id+(row+1);if(id<(row*col)&&(id%row)>yu){var flag = WuZiQi.checkColor(id,color);if(flag){num++;return WuZiQi.zuoxiejia(num,id,color);}else{return num;}}else{return num;}},zuoxiejian:function(num,id,color){var yu = id%row;id = id-(row+1);if(id>=0&&(id%row)<yu){var flag = WuZiQi.checkColor(id,color);if(flag){num++;return WuZiQi.zuoxiejian(num,id,color);}else{return num;}}else{return num;}},hengjia:function(num,id,color){var yu = id%row;id = id+1;if(id<(row*col)&&(id%row)>yu){var flag = WuZiQi.checkColor(id,color);if(flag){num++;return WuZiQi.hengjia(num,id,color);}else{return num;}}else{return num;}},hengjian:function(num,id,color){var yu = id%row;id = id-1;if(id>=0&(id%row)<yu){var flag = WuZiQi.checkColor(id,color);if(flag){num++;return WuZiQi.hengjian(num,id,color);}else{return num;}}else{return num;}},shujia:function(num,id,color){id = id+row;if(id<(row*col)){var flag = WuZiQi.checkColor(id,color);if(flag){num++;return WuZiQi.shujia(num,id,color);}else{return num;}}else{return num;}},shujian:function(num,id,color){id = id-row;if(id>=0){var flag = WuZiQi.checkColor(id,color);if(flag){num++;return WuZiQi.shujian(num,id,color);}else{return num;}}else{return num;}},checkColor:function(xy,color){if($("#"+xy).children("div").hasClass(color)){return true;}else {return false;}},playchess:function(e){if(bout&&color!=""){if($(e).children("div").length>0){alert("这里已经有子了!请在其它地方落子!");return;}var result = {};result.xy = $(e).attr("id");result.color = color;result.message = "系统:您已落子,请等待对手落子!";result.bout = false;if(websocket!=null){websocket.send(JSON.stringify(result));}else{$("#messageContent").append("系统:已断开连接");$("#messageContent").append("\n");}}else{if(color==""){$("#messageContent").append("系统:游戏还没有开始!");$("#messageContent").append("\n");$("#messageContent").scrollTop($("#messageContent")[0].scrollHeight - $("#messageContent").height());}else{$("#messageContent").append("系统:请等待你的对手落子!");$("#messageContent").append("\n");$("#messageContent").scrollTop($("#messageContent")[0].scrollHeight - $("#messageContent").height());}}},//发送消息sendMessage:function(){var message = $("#message").val();if(message!=""){var result = {};result.message = message;websocket.send(JSON.stringify(result));$("#message").val("");}else{$("#messageContent").append("系统:请不要发送空信息!");$("#messageContent").append("\n");$("#messageContent").scrollTop($("#messageContent")[0].scrollHeight - $("#messageContent").height());}}
};
$(function(){//根据棋盘格子数得到棋盘大小$("#background").css({width:(row*widthAndHeight)+"px",height:(col*widthAndHeight)+"px"});//用canvas画棋盘var canvas = document.createElement("canvas");
//  $(canvas).attr({width:((row-1)*widthAndHeight)+"px",height:(col-1)*widthAndHeight+"px"});
//  $(canvas).css({"position":"relative","top":(widthAndHeight/2)+"px","left":(widthAndHeight/2)+"px","z-index":9999});$(canvas).attr({width:(row*widthAndHeight)+"px",height:col*widthAndHeight+"px"});$(canvas).css({position:"relative","z-index":9999});var cot = canvas.getContext("2d");cot.fillStyle = "#EAC000";cot.fillRect(0,0,row*widthAndHeight,col*widthAndHeight);cot.lineWidth = 1;var offset = widthAndHeight/2;for(var i=0;i<row;i++){//面板大小和棋盘一致,但格子线条比棋盘的行列少1cot.moveTo((widthAndHeight*i)+offset,0+offset);cot.lineTo((widthAndHeight*i)+offset,(col*widthAndHeight)-offset);}for(var j=0;j<col;j++){cot.moveTo(0+offset,(widthAndHeight*j)+offset);cot.lineTo((widthAndHeight*row)-offset,(j*widthAndHeight)+offset);}  cot.stroke();$("#background").prepend(canvas);//生成格子横线
//  var b_str="";
//  for(var i=0;i<(row-1);i++){
//      for(var j=0;j<(col-1);j++){
//          b_str+="<div class='b_grid'></div>";
//      }
//  }
//  $("#back_grid").append(b_str);
//  $("#back_grid").css({width:((row-1)*widthAndHeight)+"px",height:(col-1)*widthAndHeight+"px",position: "absolute",top:(widthAndHeight/2)+"px",left:(widthAndHeight/2)+"px",border:"solid 1px black"});
//  //减去线的宽度
//  $(".b_grid").css({width:(widthAndHeight-2)+"px",height:(widthAndHeight-2)+"px",border:"solid 1px black"});//生成落子格子var str="";var index = 0;for(var i=0;i<row;i++){for(var j=0;j<col;j++){str+="<div class='grid' id=\""+index+"\"></div>";index++;}}$("#chess").empty();$("#chess").append(str);$("#chess").css({width:(row*widthAndHeight)+"px",height:(col*widthAndHeight)+"px",position: "absolute",top:"0px",left:"0px","z-index":99999});$(".grid").on("click",function(){WuZiQi.playchess(this);});$(".grid").css({width:widthAndHeight+"px",height:widthAndHeight+"px"});//判断当前浏览器是否支持WebSocketif('WebSocket' in window){websocket = new WebSocket("ws://"+window.location.host+"/WuZiQi/wuziqisocket");}else{alert('Not support websocket');}//连接发生错误的回调方法websocket.onerror = function(){};//连接成功建立的回调方法websocket.onopen = function(event){};//接收到消息的回调方法(包含了聊天,落子,开始游戏)websocket.onmessage = function(){var result = JSON.parse(event.data);if(result.message!=""){$("#messageContent").append(result.message);$("#messageContent").append("\n");//将多行文本滚动总是在最下方$("#messageContent").scrollTop($("#messageContent")[0].scrollHeight - $("#messageContent").height());}if(result.xy!=""&&result.color!=""){$("#"+result.xy).html("<div class=\"chessman "+result.color+"\"></div>");bout = result.bout;//落子后才改状态WuZiQi.isEnd(result.xy,result.color);}else if(result.xy==""&&result.bout){//没有坐标且bout为true,则为对局首次开始落子bout = result.bout;}if(result.xy==""&&result.color!=""){//没有坐标,但有颜色,则为首次赋予棋子颜色color = result.color;}};//连接关闭的回调方法websocket.onclose = function(){};//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function(){websocket.close();};//关闭连接function closeWebSocket(){websocket.close();}
});

java封装传输类,(用来实现发送消息和落子)

package com.weguard.websocket;
/*** * @author xuhan**/
public class Result {/*** 落子坐标*/private String xy;/*** 发送消息*/private String message;/*** 是否允许落子*/private boolean bout;/*** 落子颜色*/private String color;public String getXy() {return xy;}public void setXy(String xy) {this.xy = xy;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public boolean isBout() {return bout;}public void setBout(boolean bout) {this.bout = bout;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}}

最后就是WebSocket了

package com.weguard.websocket;import java.io.IOException;
import java.util.HashMap;import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;import net.sf.json.JSONObject;//该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。类似Servlet的注解mapping。无需在web.xml中配置。
@ServerEndpoint(value="/wuziqisocket")
public class WebSocket {//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识private static HashMap<String,WebSocket> webSocketMap = new HashMap<String,WebSocket>();//与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;//连上来的页面序号,用来配对对战,1与2一组,3与4一组,依次类推,奇数为黑先走,偶数为白,后走private static int index = 0;//同上,用来从hashMap中获取websocket,(我也忘记当时为啥要另外用一个mykey了,而不是直接用index来获取)private int mykey = 0;/*** 连接建立成功调用的方法* @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据* @throws IOException */@OnOpenpublic void onOpen( Session session){this.session = session;index++;try {Result result = new Result();if(index%2==0){WebSocket socket1 = webSocketMap.get((index-1)+"");if(socket1!=null){result.setBout(true);result.setMessage("系统:游戏开始,请您先落子!");result.setColor("black");JSONObject json1 = JSONObject.fromObject(result);socket1.sendMessage(json1.toString());//对先落子的对象发送数据结束result.setMessage("系统:游戏开始,请等待对手落子!");result.setBout(false);result.setColor("white");this.sendMessage(JSONObject.fromObject(result).toString());//对后出手的发送消息结束}else{//偶数时没有查询到与之对应的对手,则其变为奇数,成为等待匹配的人index--;result.setMessage("系统:等待玩家匹配!");this.sendMessage(JSONObject.fromObject(result).toString());}}else{result.setMessage("系统:等待玩家匹配!");this.sendMessage(JSONObject.fromObject(result).toString());}this.mykey = index;webSocketMap.put(mykey+"", this);     //加入map中System.out.println(webSocketMap.size());} catch (Exception e) {e.printStackTrace();}}/*** 连接关闭调用的方法* @throws IOException */@OnClosepublic void onClose(){webSocketMap.remove(mykey+"");  //从set中删除try {WebSocket socket = null;if(mykey%2==0){socket = webSocketMap.get((mykey-1)+"");}else{socket = webSocketMap.get((mykey+1)+"");}if(socket!=null){Result result = new Result();result.setMessage("你的对手已离开!");socket.sendMessage(JSONObject.fromObject(result).toString());}} catch (Exception e) {e.printStackTrace();}}/*** 收到客户端消息后调用的方法* @param message 客户端发送过来的消息* @param session 可选的参数*/@OnMessagepublic void onMessage(String message) {System.out.println(message);JSONObject json = JSONObject.fromObject(message);Result result = (Result) JSONObject.toBean(json,Result.class);try {WebSocket socket = null;if(mykey%2==0){socket = webSocketMap.get((mykey-1)+"");}else{socket = webSocketMap.get((mykey+1)+"");}if(socket!=null){if(result.getXy()!=null&&!"".equals(result.getXy())){//有坐标表示为落子,反之则为发送信息this.sendMessage(message);result.setBout(true);//对手的bout改为true,表示接下来可以落子result.setMessage("系统:对方已落子,正在等待您落子!");socket.sendMessage(JSONObject.fromObject(result).toString());}else{//没有坐标表示为单纯的聊天Result newResult = new Result();newResult.setMessage("自己:"+result.getMessage());this.sendMessage(JSONObject.fromObject(newResult).toString());newResult.setMessage("对方:"+result.getMessage());socket.sendMessage(JSONObject.fromObject(newResult).toString());}}} catch (Exception e) {e.printStackTrace();}}/*** 发生错误时调用* @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error){System.out.println("连接断开");
//      error.printStackTrace();}/*** 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。* @param message* @throws IOException*/public void sendMessage(String message) throws IOException{this.session.getBasicRemote().sendText(message);//this.session.getAsyncRemote().sendText(message);}
}

整个五子棋的功能就在上面了,只要放进目录中,就能正常的运行起来,具体的实现代码里都有注释。有什么见解大家一起讨论下啊

使用WebSocket实现多组即时对战五子棋相关推荐

  1. 刚做了象棋和跳棋游戏 求教如何 实现游戏的在线即时对战功能

    我做了两个小游戏,目前还都只支持 chrome,暂没做其它浏览器的兼容处理,见博客链接或附件 听说用 nodeJS + webSocket 可以实现一次握手,一直连线通讯功能,相互之间可以进行即时消息 ...

  2. WebSocket之仿QQWeb即时聊天系统(上)

    1. 前言 Java web学完了,到了学期末,开始课设了,一共给了几个题目,大部分都是 JSP+servlet题目,当然我们也是主要学习的这些,一般都是什么什么管理系统,没啥意思,看到一个仿QQWe ...

  3. WebSocket之仿QQWeb即时聊天系统(下)

    1. 前言 上篇主要说了准备阶段和要学的基本知识,当然学的知识还是死的,还是要敲代码,下篇主要就是用上编学的知识实现本次课设任务 WebSocket之仿QQWeb即时聊天系统(上) WebSocket ...

  4. 车载通讯模组的“进阶战”

    4G车载通信模组市场竞争已经趋于白热化,各大车载通信模组厂商正在全力冲击下一轮的市场"抢位战". 根据高工智能汽车研究院统计的数据显示,2021年1-12月国内新车(自主+合资品牌 ...

  5. 基于WebSocket的网页端即时通讯

    基于WebSocket的网页端即时通讯 最近项目中需要用到一些即时通讯的相关技术,查阅了一些资料后发现有些示例不是让人很满意,所以博主写了一个demo,就怕以后会忘掉,也方便博友查看. 由于博主用的是 ...

  6. iOS简易蓝牙对战五子棋游戏设计思路之二——核心棋盘逻辑与胜负判定算法

    2019独角兽企业重金招聘Python工程师标准>>> iOS简易蓝牙对战五子棋游戏设计思路之二--核心棋盘逻辑与胜负判定算法 一.引言 上一篇博客我们介绍了在开发一款蓝牙对战五子棋 ...

  7. 借助实时数据推送快速制作在线对战五子棋小游戏丨实战

    1 项目概述 游戏开发,尤其是微信小游戏开发,是最近几年比较热门的话题. 本次「云开发」公开课,将通过实战「在线对战五子棋」,一步步带领大家,在不借助后端的情况下,利用「小程序 ✖ 云开发」,独立完成 ...

  8. 网络对战五子棋(来一起PK鸭)

    网络对战五子棋(来一起PK鸭) 一.本地调用和RPC调用的区别 首先了解一下RPC~ RPC主要是解决了两个问题: 解决了分布式系统中,服务之间的调用问题 尤其是在远程调用的时候,可以让调用者感受不到 ...

  9. 400行代码实现双人对战五子棋(适合新手入门)

    400行代码实现双人对战五子棋(适合新手入门) 跟上一篇博客一样,都是看了慕课网的视频之后写的学习记录,记录一下实现的思路,大部分内容比较简单,但也从中学到了很多东西. 按惯例首先看一下效果:(素材都 ...

  10. java swing人机对战五子棋(含背景音乐)

    一.项目简介 本项目是一套基于java swing的人机对战五子棋系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者. 包含:项目源码.数据库脚本等,该项目附带全部源码可 ...

最新文章

  1. 谱聚类 Spectral Clustering
  2. 评价算法的性能从利用计算机资源角度,计算机专业数据结构课后练习题汇编
  3. python正则表达式,看完这篇文章就够了...
  4. Windows 10强推新功能:能否让你的电脑更快
  5. 洛谷4400 BlueMary的旅行(分层图+最大流)
  6. 把100减锐城1用计算机怎么算,北师大四年级下册数学
  7. python2和3语法区别_python2和3语法区别
  8. 数值分析(第五版) 第二章知识点总结
  9. 事业单位考试高频考点一:马克思主义基本原理
  10. 函数指针 回调函数 面向对象风格的C语言
  11. MapXtreme绿色部署
  12. 2007 Microsoft Office 加载项:Microsoft Save as PDF 或 XPS
  13. 《计算机技术领域当前的主流技术及其社会需求调查报告》
  14. 7714天,王小川正式卸任搜狗CEO!网友:别了。。。
  15. Delphi调用IE打开网页
  16. 关于Google大陆手机号不能验证的问题
  17. python 实现一个反向单位矩阵
  18. 安装JAVA SE 安装包
  19. 2022无线蓝牙耳机选哪个?盘点超热门的蓝牙耳机品牌推荐
  20. 【Verilog语法1】加载存储器$readmemh和$readmemb函数的使用

热门文章

  1. requests爬取4399游戏链接
  2. 空间句法软件sDNA安装教程及加载到ArcGIS方法
  3. 思科cisoc 路由器IKEv2使用map配置隧道
  4. oracle e18,ORACLE_10g_各版本下载地址大全
  5. 计算机与地震论文,地震勘探学术论文
  6. 极值点 驻点 鞍点 拐点
  7. word里面的表格调整行高技巧
  8. java制作纯字rpg小游戏_初学JAVA时编写的rpg文字游戏
  9. 12.qgis二次开发qt中实现图层树右键图层更改图层颜色,以及图层标注。
  10. Ubuntu系统上编译和安装perl和cpan模块