阅读完需:约 5 分钟
如果之前没有接触过WebSocket,或者对WebSocket并不太熟悉,可以先阅读前面三篇文章学习!
游戏效果图:
核心思路:
1.该游戏本质上就是两个人聊天,只不过聊天的内容为棋盘上的坐标
2.用户点击棋盘,根据点击的位置,算出离点击位置最近的一个十字的坐标作为此次点击事件的坐标,将之传递给WebSocket服务端
3.当有两个人已经连接上服务端的时候,此时如果有第三个人连接服务端,则服务端返回一条消息告诉该客户端房间人已满,并且让该客户端主动关闭连接
4.每下一子,都去判断一下该子的上\下,左\右,左上\右下,左下\右上四个方向上同类型的子是否已满5个,满5个表示此次落子的用户赢
5.游戏进行过程中,有一方关闭浏览器,会提示另一方某某人已经下线
素材:
java,html代码:
html前端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>五子棋大战</title>
<script src="jquery-3.2.1.js"></script>
<style>
tr {
height: 40px;
}
td {
width: 39px;
}
table {
/*border-right: 1px solid #010000;*/
/*border-bottom: 1px solid #010000;*/
}
table td {
border-left: 1px solid #010000;
border-top: 1px solid #010000
}
table tr:nth-last-child(1) td {
border-left: 0px solid #010000;
}
table td:nth-last-child(1) {
border-top: 0px solid #010000
}
img {
width: 22px;
height: 22px;
}
</style>
</head>
<body>
<div align="center">
<div id="msgDiv"><input type="text" id="nickname" placeholder="请输入昵称"><input type="button" value="连接" id="connBtn">
</div>
<div style="background:url('./img/bg.png') no-repeat 0px 0px;width: 1081px;height: 610px;padding-top:5px;margin-top: 15px;display: none"
id="gameDiv"></div>
</div>
<script>
var str = "<table cellpadding='0' cellspacing='0' id='gameTable'>";
for (var i = 0; i < 15; i++) {
str += "<tr>";
for (var j = 0; j < 25; j++) {
str += "<td></td>";
}
str += "</tr>";
}
str += "</table>";
$("#gameDiv").html(str);
var webSocket;
$("#connBtn").click(function () {
var nickname = $("#nickname").val();
if (nickname == null || nickname == '') {
alert("必须输入昵称");
return;
}
$("#gameDiv").css("display", "block");
$(this).attr("disabled", "disabled");
webSocket = new WebSocket("ws://192.168.13.48/game/game/" + nickname);
webSocket.onmessage = function (event) {
if(event.data=='房间人已满!'){
$("#msgDiv").html(event.data);
$("#gameDiv").css("display", "none");
webSocket.close(-1);
}
if(event.data.indexOf("获胜")!=-1) {
eval(event.data);
}else{
if (event.data.indexOf("-") != -1) {
var splitArr = event.data.split("-");
var x = splitArr[0];
var y = splitArr[1];
if (splitArr[2] == 0) {
$("#gameTable tr:eq('" + y + "') td:eq('" + x + "')").html("<div style='margin-top: -30px;margin-left: -11px;'><img src='img/white.png'/></div>");
} else {
$("#gameTable tr:eq('" + y+ "') td:eq('" +x+ "')").html("<div style='margin-top: -30px;margin-left: -11px;'><img src='img/black.png'/></div>");
}
} else {
$("#msgDiv").html(event.data);
}
}
}
webSocket.onerror = function (event) {
alert(event.data);
}
webSocket.onopen = function (event) {
$("#msgDiv").html("<p>您已经进入到房间里</p>");
}
});
$("#gameDiv").click(function (event) {
var gameTable = $("#gameTable");
var rect = gameTable[0].getBoundingClientRect();
var clickX = event.clientX - rect.left;
var clickY = event.clientY - rect.top;
var n1 = clickX % 40;
var n2 = clickY % 40;
if (n1 > 15 && n1 < 25 || n2 > 15 && n2 < 25) {
return;
}
var x = (clickX - n1) / 40;
if (n1 >= 25) {
x++;
}
var y = (clickY - n2) / 40;
if (n2 >= 25) {
y++;
}
webSocket.send(x + "-" + y);
});
</script>
</body>
</html>
java后端:
package org.sang;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* Created by sang on 2017/8/28.
*/
@ServerEndpoint("/game/{nickname}")
public class GoBangGame {
private static final Set<GoBangGame> GO_BANG_GAME_SET = new CopyOnWriteArraySet<>();
private Session session;
private String nickname;
private static String lastUser;
private static int count = 0;
private int[][] oriData = new int[15][25];
@OnOpen
public void onOpen(@PathParam("nickname") String nickname, Session session) throws IOException {
this.session = session;
this.nickname = nickname;
if (GO_BANG_GAME_SET.size() > 1) {
System.out.println("房间人满");
session.getBasicRemote().sendText("房间人已满!");
// session.close();
} else {
GO_BANG_GAME_SET.add(this);
StringBuffer sb = new StringBuffer();
for (GoBangGame goBangGame : GO_BANG_GAME_SET) {
sb.append(goBangGame.nickname).append(";");
}
for (int i = 0; i < oriData.length; i++) {
for (int j = 0; j < oriData[i].length; j++) {
oriData[i][j] = -1;
}
}
sendText(nickname + "童鞋进入房间;当前房间有:" + sb.toString());
}
}
@OnMessage
public void onMessage(String message, @PathParam("nickname") String nickname) {
if (nickname == lastUser) {
return;
}
int i = count++ % 2;
String[] split = message.split("-");
int x = Integer.parseInt(split[0]);
int y = Integer.parseInt(split[1]);
oriData[y][x] = i;
int success = isSuccess(x, y, i, oriData);
sendText(message + "-" + i);
if (success == -1) {
lastUser = nickname;
} else {
if (i == 0) {
sendText("alert('白棋获胜,点击确定重新开始游戏!');location.reload(true);");
return;
} else if (i == 1) {
sendText("alert('黑棋获胜,点击确定重新开始游戏!');location.reload(true);");
return;
}
}
}
private static int isSuccess(int x, int y, int f, int[][] oriData) {
//y的范围在0-14之间,x的范围在0-24之间
int count = 0;
for (int i = x - 1; i > -1; i--) {
if (oriData[y][i] != f) {
break;
}
count++;
}
for (int i = x + 1; i < 25; i++) {
if (oriData[y][i] != f) {
break;
}
count++;
}
if (count > 3) {
return f;
}
count = 0;
for (int i = y + 1; i < 15; i++) {
if (oriData[i][x] != f) {
break;
}
count++;
}
for (int i = y - 1; i > -1; i--) {
if (oriData[i][x] != f) {
break;
}
count++;
}
if (count > 3) {
return f;
}
count = 0;
for (int i = x + 1, j = y + 1; i < 25; i++, j++) {
if (j < 15) {
if (oriData[j][i] != f) {
break;
}
count++;
}else
break;
}
for (int i = x - 1, j = y - 1; i > -1; i--, j--) {
if (j > -1) {
if (oriData[j][i] != f) {
break;
}
count++;
}else
break;
}
if (count > 3) {
return f;
}
count = 0;
for (int i = x + 1, j = y - 1; i < 25; i++, j--) {
if (j > -1) {
if (oriData[j][i] != f) {
break;
}
count++;
}else
break;
}
for (int i = x - 1, j = y + 1; i > -1; i--, j++) {
if (j < 25) {
if (oriData[j][i] != f) {
break;
}
count++;
}else
break;
}
if (count > 3) {
return f;
}
return -1;
}
private static void sendText(String msg) {
for (GoBangGame goBangGame : GO_BANG_GAME_SET) {
try {
synchronized (goBangGame) {
goBangGame.session.getBasicRemote().sendText(msg);
}
} catch (IOException e) {
GO_BANG_GAME_SET.remove(goBangGame);
try {
goBangGame.session.close();
} catch (IOException e1) {
}
sendText(goBangGame.nickname + "童鞋已下线");
}
}
}
@OnClose
public void onClose(Session session) {
GO_BANG_GAME_SET.remove(this);
for (GoBangGame goBangGame : GO_BANG_GAME_SET) {
if (goBangGame.nickname == this.nickname) {
sendText(this.nickname + "童鞋已下线");
}
}
}
}