diff --git a/backend/src/main/java/com/kob/backend/consumer/WebSocketServer.java b/backend/src/main/java/com/kob/backend/consumer/WebSocketServer.java index db6e841..11121ff 100644 --- a/backend/src/main/java/com/kob/backend/consumer/WebSocketServer.java +++ b/backend/src/main/java/com/kob/backend/consumer/WebSocketServer.java @@ -5,6 +5,7 @@ package com.kob.backend.consumer; import com.alibaba.fastjson2.JSONObject; import com.kob.backend.consumer.utils.Game; import com.kob.backend.consumer.utils.JwtAuthenticationUtil; +import com.kob.backend.mapper.RecordMapper; import com.kob.backend.mapper.UserMapper; import com.kob.backend.pojo.User; import org.springframework.beans.factory.annotation.Autowired; @@ -32,6 +33,8 @@ public class WebSocketServer { private static final CopyOnWriteArraySet matchPool = new CopyOnWriteArraySet<>(); // 在 WebSocketServer 中注入数据库的方法演示-> 使用 static 定义为独一份的变量 private static UserMapper userMapper; + // 注入 RecordMapper 用于调用实现游戏数据到数据库的存储 + public static RecordMapper recordMapper; // 后端向前端发送信息,首先需要创建一个 session private Session session = null; // 用户信息:定义一个成员变量 @@ -45,6 +48,11 @@ public class WebSocketServer { WebSocketServer.userMapper = userMapper; } + @Autowired + public void setRecordMapper(RecordMapper recordMapper) { + WebSocketServer.recordMapper = recordMapper; + } + // @OnOpen 创建链接时自动触发这个函数 @OnOpen @@ -91,7 +99,7 @@ public class WebSocketServer { System.out.println("start matching"); matchPool.add(this.user); - while (matchPool.size()>=2){ + while (matchPool.size() >= 2) { // 迭代器用于枚举前两个人进行匹配 Iterator it = matchPool.iterator(); User a = it.next(), b = it.next(); @@ -100,7 +108,7 @@ public class WebSocketServer { matchPool.remove(b); // 匹配成功时,创建联机地图 - Game game = new Game(13,14,20,a.getId(),b.getId()); + Game game = new Game(13, 14, 20, a.getId(), b.getId()); game.createMap(); // 初始化地图 users.get(a.getId()).game = game; // 将 game 赋给 a 玩家 users.get(b.getId()).game = game; @@ -108,32 +116,32 @@ public class WebSocketServer { game.start(); // 开启新线程,执行函数 JSONObject respGameData = new JSONObject(); - respGameData.put("game_map",game.getG()); - respGameData.put("rows",game.getRows()); - respGameData.put("cols",game.getCols()); - respGameData.put("inner_walls_count",game.getInnerWallsCount()); - respGameData.put("a_id",game.getPlayerA().getId()); - respGameData.put("a_sx",game.getPlayerA().getSx()); - respGameData.put("a_sy",game.getPlayerA().getSy()); - respGameData.put("b_id",game.getPlayerB().getId()); - respGameData.put("b_sx",game.getPlayerB().getSx()); - respGameData.put("b_sy",game.getPlayerB().getSy()); + respGameData.put("game_map", game.getG()); + respGameData.put("rows", game.getRows()); + respGameData.put("cols", game.getCols()); + respGameData.put("inner_walls_count", game.getInnerWallsCount()); + respGameData.put("a_id", game.getPlayerA().getId()); + respGameData.put("a_sx", game.getPlayerA().getSx()); + respGameData.put("a_sy", game.getPlayerA().getSy()); + respGameData.put("b_id", game.getPlayerB().getId()); + respGameData.put("b_sx", game.getPlayerB().getSx()); + respGameData.put("b_sy", game.getPlayerB().getSy()); // 将 a 配对成功的消息传回客户端 JSONObject respA = new JSONObject(); - respA.put("event","start-matching"); - respA.put("opponent_username",b.getUsername()); - respA.put("opponent_photo",b.getPhoto()); - respA.put("game_data",respGameData); + respA.put("event", "start-matching"); + respA.put("opponent_username", b.getUsername()); + respA.put("opponent_photo", b.getPhoto()); + respA.put("game_data", respGameData); // 获取 a 的链接,并通过 sendMessage 将消息传给前端 users.get(a.getId()).sendMessage(respA.toJSONString()); // 同理,将 b 的匹配成功信息传回给前端 JSONObject respB = new JSONObject(); - respB.put("event","start-matching"); - respB.put("opponent_username",a.getUsername()); - respB.put("opponent_photo",a.getPhoto()); - respB.put("game_data",respGameData); + respB.put("event", "start-matching"); + respB.put("opponent_username", a.getUsername()); + respB.put("opponent_photo", a.getPhoto()); + respB.put("game_data", respGameData); users.get(b.getId()).sendMessage(respB.toJSONString()); } } @@ -145,13 +153,12 @@ public class WebSocketServer { } // direction 传入 move(移动) 方向参数 - private void move(int direction){ + private void move(int direction) { // 判断角色:如果是 A 角色,则将获取到的方向设置为 A 的 nextStep 方向 // user.getId() 是获取当前链接的用户 id - if(game.getPlayerA().getId().equals(user.getId())){ + if (game.getPlayerA().getId().equals(user.getId())) { game.setNextStepA(direction); - } - else if(game.getPlayerB().getId().equals(user.getId())){ + } else if (game.getPlayerB().getId().equals(user.getId())) { game.setNextStepB(direction); } } diff --git a/backend/src/main/java/com/kob/backend/consumer/utils/Game.java b/backend/src/main/java/com/kob/backend/consumer/utils/Game.java index 5146692..f5d6dcd 100644 --- a/backend/src/main/java/com/kob/backend/consumer/utils/Game.java +++ b/backend/src/main/java/com/kob/backend/consumer/utils/Game.java @@ -2,12 +2,11 @@ package com.kob.backend.consumer.utils; import com.alibaba.fastjson2.JSONObject; import com.kob.backend.consumer.WebSocketServer; +import com.kob.backend.pojo.Record; import javax.swing.event.InternalFrameEvent; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Random; +import java.sql.Time; +import java.util.*; import java.util.concurrent.locks.ReentrantLock; // 用来管理整个游戏流程:这里需要多线程 @@ -62,6 +61,23 @@ public class Game extends Thread { return inner_walls_count; } + private String getGameMapString(){ + StringBuilder res = new StringBuilder(); + // 将地图数据展开成一维 +/* for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + res.append(g[i][j]); + } + }*/ + for (int[] row:g){ + for(int col:row){ + res.append(col); + } + } + + return res.toString(); + } + public void setNextStepA(Integer nextStepA) { // 为了防止两方读写冲突,需要加线程锁之后操作 nextStep 值 lock.lock(); @@ -273,6 +289,27 @@ public class Game extends Thread { } } + // 将游戏结果存到数据库中 + private void saveToDataBase(){ + Record record = new Record( + null, + playerA.getId(), + playerA.getSx(), + playerA.getSy(), + playerB.getId(), + playerB.getSx(), + playerB.getSy(), + playerA.getStepsString(), + playerB.getStepsString(), + getGameMapString(), + loser, + new Date() + ); + + WebSocketServer.recordMapper.insert(record); + } + + // 向两个 Client 公布结果 private void sendResult() { lock.lock(); @@ -283,6 +320,8 @@ public class Game extends Thread { // 将最后碰撞时的蛇的眼睛指向传给前端 resp.put("a_eyes_finally_direction", nextStepA); resp.put("b_eyes_finally_direction", nextStepB); + // 发送结果之前,先将结果存到数据库中 + saveToDataBase(); sendAllMessage(resp.toJSONString()); } finally { lock.unlock(); diff --git a/backend/src/main/java/com/kob/backend/consumer/utils/Player.java b/backend/src/main/java/com/kob/backend/consumer/utils/Player.java index ac2186c..66be0ff 100644 --- a/backend/src/main/java/com/kob/backend/consumer/utils/Player.java +++ b/backend/src/main/java/com/kob/backend/consumer/utils/Player.java @@ -48,4 +48,14 @@ public class Player { } return res; } + + // steps 转换为 string 的辅助函数 + public String getStepsString() { + StringBuilder res = new StringBuilder(); + for (int d : steps) { + res.append(d); + } + + return res.toString(); + } } diff --git a/backend/src/main/java/com/kob/backend/mapper/RecordMapper.java b/backend/src/main/java/com/kob/backend/mapper/RecordMapper.java new file mode 100644 index 0000000..4541ca4 --- /dev/null +++ b/backend/src/main/java/com/kob/backend/mapper/RecordMapper.java @@ -0,0 +1,9 @@ +package com.kob.backend.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.kob.backend.pojo.Record; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface RecordMapper extends BaseMapper { +} diff --git a/backend/src/main/java/com/kob/backend/pojo/Bot.java b/backend/src/main/java/com/kob/backend/pojo/Bot.java index 478c15d..e4cc821 100644 --- a/backend/src/main/java/com/kob/backend/pojo/Bot.java +++ b/backend/src/main/java/com/kob/backend/pojo/Bot.java @@ -1,4 +1,5 @@ -//用于将 Mysql 表 Bot 转换为 class +// 用于将 Mysql 表 Bot 转换为 class +// 数据库中 user_id 这种在 pojo 里要命名为 userId package com.kob.backend.pojo; import com.baomidou.mybatisplus.annotation.IdType; diff --git a/backend/src/main/java/com/kob/backend/pojo/Record.java b/backend/src/main/java/com/kob/backend/pojo/Record.java new file mode 100644 index 0000000..dd00e62 --- /dev/null +++ b/backend/src/main/java/com/kob/backend/pojo/Record.java @@ -0,0 +1,34 @@ +package com.kob.backend.pojo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; +import java.util.Timer; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Record { + @TableId(type = IdType.AUTO) + private Integer id; + + private Integer aId; + private Integer aSx; + private Integer aSy; + private Integer bId; + private Integer bSx; + private Integer bSy; + + private String aSteps; + private String bSteps; + private String map; + private String loser; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") + private Date createtime; +}