项目实战--网页五子棋(游戏大厅)(3)

我们的游戏大厅界面主要需要包含两个功能,一是显示用户信息,二是匹配游戏按钮

1. 页面实现

hall.html

html 复制代码
<!DOCTYPE html>
<html lang="ch">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>游戏大厅</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/hall.css">
</head>
<body>
    <div class="nav">五子棋</div>
    <div class="container">
        <div class="dialog">
            <!-- 展示用户信息 -->
            <div id="screen"></div>
            <!-- 开始匹配 -->
            <button id="match" onclick="findMatch()">开始匹配</button>
        </div>
    </div>
</body>
</html>

hall.css

css 复制代码
.container {
    height: calc(100% - 50px);
    display: flex;
    justify-content: center;
    align-items: center;
}

.container .dialog {
    height: 350px;
    width: 299px;
    background-color: white;
    border-radius: 20px;
    padding-top: 30px;
    display: flex;
    justify-content: center;
    /* align-items: center; */
    flex-wrap: wrap
}

.dialog *{
    display: flex;
    justify-content: center;
    align-items: center;
}

.dialog #screen {
    width: 250px;
    height: 150px;
    background-color: wheat;
    border-radius: 10px;
}

.dialog #match {
    width: 150px;
    height: 40px;
    background-color: rgb(255, 159, 33);
    border-radius: 10px;
}

.dialog #match:active {
    background-color: rgb(204, 128, 21);
}

2. 获取用户信息接口

当用户进入 游戏大厅时,就应该获取到登录用户的信息显示到页面上,我们使用js代码从访问后端接口获取信息:

html 复制代码
    <script src="js/jquery.min.js"></script>
    <script>
        $.ajax({
            type: 'post',
            url: '/user/getLoginUser',
            success: function(result) {
                if(result.username != null) {
                    let screen = document.querySelector("#screen");
                    screen.innerHTML = '当前玩家:' + result.username + '<br>天梯积分:' + 
                    result.score + '<br>比赛场次:' + result.totalCount + 
                    '<br>获胜场次:' + result.winCount;
                }else{
                    alert("获取用户信息失败,请重新登录");
                    location.href = "/login.html";
                }
            },
            error: function() {
                alert("获取用户信息失败");
            }
        });
    </script>

运行效果:

2. WebSocket前端代码

当用户点击匹配按钮时,需要告知服务器该用户要进行匹配,服务器如果接收到则立即回复表示正在匹配,当匹配成功服务器则又需要发送匹配信息给客户端。这里涉及到服务器主动给客户端发送消息的场景,所以我们使用websocket实现

2.1 初始化websocket

javascript 复制代码
let webSocket = new WebSocket('ws://127.0.0.1:8080/findMatch');
        webSocket.onopen = function() {
            console.log("连接成功");
        }
        webSocket.onclose = function() {
            console.log("连接关闭");
        }
        webSocket.onerror = function() {
            console.log("error");
        }

        //页面关闭时释放webSocket
        window.onbeforeunload = function() {
            webSocket.close();
        }

        //处理服务器发送的消息
        webSocket.onmessage = function(e) {

        }

        function findMatch() {
            //检查websocket连接
            if(webSocket.readyState == webSocket.OPEN) {

            }else{
                alert("连接断开,请重新登录");
                location.href = "/login.html";
            }
        }

2.2 实现findMatch()方法

点击开始匹配按钮后就会执行findMatch方法,进入匹配状态,此时我们可以把开始匹配按钮替换成取消匹配按钮,再次点击则会向服务器发送取消匹配请求。

javascript 复制代码
function findMatch() {
            //检查websocket连接
            if(webSocket.readyState == webSocket.OPEN) {
                if($("#match").text() == '开始匹配') {
                    console.log("开始匹配");
                    webSocket.send(JSON.stringify({
                        message: 'startMatch' //约定startMatch表示开始匹配
                    }));
                }else if($("#match").text() == '匹配中...') {
                    console.log("停止匹配");
                    webSocket.send(JSON.stringify({
                        message: 'stopMatch' //约定stopMatch表示停止匹配
                    }));
                }
            }else{
                alert("连接断开,请重新登录");
                location.href = "/login.html";
            }
        }

2.3 实现onmessage

我们约定服务器返回的响应为包含以下三个字段的json:

  • ok: true/false, //表示请求成功还是失败
  • errMsg:"错误信息", //请求失败返回错误信息
  • message: 'startMatch' / 'stopMatch' / 'success' //success表示请求成功
javascript 复制代码
//处理服务器发送的消息
        webSocket.onmessage = function(e) {
            //解析json字符串为js对象
            let resp = JSON.parse(e.data);
            if(!resp.ok) {
                console.log(resp.errMsg);
                return;
            }
            if(resp.message == 'startMatch') {
                //开始匹配请求发送成功正在匹配
                //替换按钮描述
                $("#match").text("匹配中...");
            }else if(resp.message == 'stopMatch') {
                //取消匹配请求发送成功已取消匹配
                //替换按钮描述
                $("#match").text("开始匹配");
            }else if(resp.message == 'success'){
                //匹配成功
                console.log("匹配成功! 进入游戏房间");
                locating.href = "/game.html";
            }else{
                console.log("非法响应 errMsg:" + resp.errMsg);
                
            }

        }

3. WebSocket后端代码

3.1 注册websocket

创建TextWebSocketHandler子类,重写如下方法:

javascript 复制代码
package org.ting.j20250110_gobang.websocket;

import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

@Component
public class MatchWebSocket extends TextWebSocketHandler {
    //连接成功后执行
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
    }
    //接收到请求后执行
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
    }
    //连接异常时执行
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
    }
    //连接正常断开后执行
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
    }
}

注册socket:

java 复制代码
package org.ting.j20250110_gobang.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import org.ting.j20250110_gobang.websocket.MatchWebSocket;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Autowired
    MatchWebSocket matchWebSocket;
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(matchWebSocket, "/findMatch") //注意路径和前端对应
                //添加拦截器获取到session,方便获取session中的用户信息
                .addInterceptors(new HttpSessionHandshakeInterceptor());
    }
}
相关推荐
卓怡学长9 小时前
w214基于jsp知道特产网
java·intellij-idea
步行cgn9 小时前
Spring 注解使用详解
java·spring
一条小小yu9 小时前
Spring IoC的理解
java·后端·spring
落魄实习生9 小时前
Agent Scope Java 2.x 系列【7】工具使用
java·开发语言·ai
旺仔学长 哈哈9 小时前
springboot钓鱼爱好者交流平台APP设计与实现
java·spring boot·mysql·充电桩管理系统
自强的小白11 小时前
核心功能(Service接口)
java·mybatis
乌暮12 小时前
深入理解 Java 泛型:把「万能盒子」用对、用稳
java·开发语言·后端·学习
大猫和小黄12 小时前
深入理解 Java Optional:从设计哲学到工程实战
java
数据库百宝箱12 小时前
rum&gin索引对比
java·数据库·gin