User-Profile-Image
hankin
  • 5
  • Java
  • Kotlin
  • Spring
  • Web
  • SQL
  • MegaData
  • More
  • Experience
  • Enamiĝu al vi
  • 分类
    • Zuul
    • Zookeeper
    • XML
    • WebSocket
    • Web Notes
    • Web
    • Vue
    • Thymeleaf
    • SQL Server
    • SQL Notes
    • SQL
    • SpringSecurity
    • SpringMVC
    • SpringJPA
    • SpringCloud
    • SpringBoot
    • Spring Notes
    • Spring
    • Servlet
    • Ribbon
    • Redis
    • RabbitMQ
    • Python
    • PostgreSQL
    • OAuth2
    • NOSQL
    • Netty
    • MySQL
    • MyBatis
    • More
    • MinIO
    • MegaData
    • Maven
    • LoadBalancer
    • Kotlin Notes
    • Kotlin
    • Kafka
    • jQuery
    • JavaScript
    • Java Notes
    • Java
    • Hystrix
    • Git
    • Gateway
    • Freemarker
    • Feign
    • Eureka
    • ElasticSearch
    • Docker
    • Consul
    • Ajax
    • ActiveMQ
  • 页面
    • 归档
    • 摘要
    • 杂图
    • 问题随笔
  • 友链
    • Spring Cloud Alibaba
    • Spring Cloud Alibaba - 指南
    • Spring Cloud
    • Nacos
    • Docker
    • ElasticSearch
    • Kotlin中文版
    • Kotlin易百
    • KotlinWeb3
    • KotlinNhooo
    • 前端开源搜索
    • Ktorm ORM
    • Ktorm-KSP
    • Ebean ORM
    • Maven
    • 江南一点雨
    • 江南国际站
    • 设计模式
    • 熊猫大佬
    • java学习
    • kotlin函数查询
    • Istio 服务网格
    • istio
    • Ktor 异步 Web 框架
    • PostGis
    • kuangstudy
    • 源码地图
    • it教程吧
    • Arthas-JVM调优
    • Electron
    • bugstack虫洞栈
    • github大佬宝典
    • Sa-Token
    • 前端技术胖
    • bennyhuo-Kt大佬
    • Rickiyang博客
    • 李大辉大佬博客
    • KOIN
    • SQLDelight
    • Exposed-Kt-ORM
    • Javalin—Web 框架
    • http4k—HTTP包
    • 爱威尔大佬
    • 小土豆
    • 小胖哥安全框架
    • 负雪明烛刷题
    • Kotlin-FP-Arrow
    • Lua参考手册
    • 美团文章
    • Java 全栈知识体系
    • 尼恩架构师学习
    • 现代 JavaScript 教程
    • GO相关文档
    • Go学习导航
    • GoCN社区
    • GO极客兔兔-案例
    • 讯飞星火GPT
    • Hollis博客
    • PostgreSQL德哥
    • 优质博客推荐
    • 半兽人大佬
    • 系列教程
    • PostgreSQL文章
    • 云原生资料库
    • 并发博客大佬
Help?

Please contact us on our email for need any support

Support
    首页   ›   Web   ›   WebSocket   ›   正文
WebSocket

WebSocket(四)—五子棋

2020-04-16 00:32:36
1153  0 0
参考目录 隐藏
1) 游戏效果图:
2) 核心思路:
3) 素材:
4) java,html代码:
5) html前端:
6) java后端:

阅读完需:约 5 分钟

如果之前没有接触过WebSocket,或者对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 + "童鞋已下线");
            }
        }
    }
}

如本文“对您有用”,欢迎随意打赏作者,让我们坚持创作!

0 打赏
Enamiĝu al vi
不要为明天忧虑.因为明天自有明天的忧虑.一天的难处一天当就够了。
543文章 68评论 294点赞 594058浏览

随机文章
SpringMVC—PathPattern路径模式
3年前
Kotlin-协程(专)—Channel 篇(三十九)
4年前
SpringBoot—搞定 session 共享
5年前
SpringCloud—Consul(一)(Ribbon)
5年前
Minio—快速整理
1年前
博客统计
  • 日志总数:543 篇
  • 评论数目:68 条
  • 建站日期:2020-03-06
  • 运行天数:1927 天
  • 标签总数:23 个
  • 最后更新:2024-12-20
Copyright © 2025 网站备案号: 浙ICP备20017730号 身体没有灵魂是死的,信心没有行为也是死的。
主页
页面
  • 归档
  • 摘要
  • 杂图
  • 问题随笔
博主
Enamiĝu al vi
Enamiĝu al vi 管理员
To be, or not to be
543 文章 68 评论 594058 浏览
测试
测试
看板娘
赞赏作者

请通过微信、支付宝 APP 扫一扫

感谢您对作者的支持!

 支付宝 微信支付