diff --git a/.idea/misc.xml b/.idea/misc.xml index cc61dbb..dbff33b 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -16,7 +16,7 @@ - + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index ccfd51a..b1ac391 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,6 +2,7 @@ + diff --git a/.idea/modules/clubs.main.iml b/.idea/modules/clubs.main.iml index afc1871..cc1e2ab 100644 --- a/.idea/modules/clubs.main.iml +++ b/.idea/modules/clubs.main.iml @@ -3,6 +3,7 @@ + \ No newline at end of file diff --git a/src/main/java/org/mmga/clubs/controller/ChessController.java b/src/main/java/org/mmga/clubs/controller/ChessController.java index 2cf4cc4..0fd8c8d 100644 --- a/src/main/java/org/mmga/clubs/controller/ChessController.java +++ b/src/main/java/org/mmga/clubs/controller/ChessController.java @@ -16,10 +16,7 @@ import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.mmga.clubs.entities.chess.Room; import org.mmga.clubs.entities.chess.packet.*; -import org.mmga.clubs.entities.chess.packet.request.CreateRoomRequest; -import org.mmga.clubs.entities.chess.packet.request.PlaceChessPieceRequest; -import org.mmga.clubs.entities.chess.packet.request.PlayerJoinRequest; -import org.mmga.clubs.entities.chess.packet.request.RoomListRequest; +import org.mmga.clubs.entities.chess.packet.request.*; import org.mmga.clubs.entities.user.User; import org.mmga.clubs.service.UserService; import org.mmga.clubs.utils.JwtUtils; @@ -128,6 +125,23 @@ public class ChessController { Optional s = roomByPlayer.downPiece(x, y, sessionId); if (s.isPresent()) return new ErrorPacket(s.get()); roomByPlayer.broadcast(roomByPlayer.getRoomInfo(users)); + Optional winInfo = roomByPlayer.isWin(); + winInfo.ifPresent(info -> { + roomByPlayer.broadcast(new HasPlayerWinPacket(info)); + if (info.isWhite()) { + WebSocketUtils.sendPacketIfPossible(new PlayerWinPacket(), roomByPlayer.getWhiteSession()); + WebSocketUtils.sendPacketIfPossible(new PlayerLosePacket(), roomByPlayer.getBlackSession()); + } else { + WebSocketUtils.sendPacketIfPossible(new PlayerWinPacket(), roomByPlayer.getBlackSession()); + WebSocketUtils.sendPacketIfPossible(new PlayerLosePacket(), roomByPlayer.getWhiteSession()); + } + }); + } + if (payload instanceof ResetRoomRequest) { + Room roomByPlayer = getRoomByPlayer(sessionId); + if (roomByPlayer == null) return new ErrorPacket("你还没加入房间呢"); + roomByPlayer.requestRestart(session); + roomByPlayer.broadcast(roomByPlayer.getRoomInfo(users)); } } catch (ClassNotFoundException e) { return new ErrorPacket("错误的请求类型"); diff --git a/src/main/java/org/mmga/clubs/entities/chess/Room.java b/src/main/java/org/mmga/clubs/entities/chess/Room.java index fc6cecc..589f529 100644 --- a/src/main/java/org/mmga/clubs/entities/chess/Room.java +++ b/src/main/java/org/mmga/clubs/entities/chess/Room.java @@ -27,6 +27,9 @@ public class Room { private Session blackSession; @JSONField(serialize = false, deserialize = false) private byte[][] pieces; + private boolean isWhiteAcceptRestart; + private boolean isBlackAcceptRestart; + private boolean canWhiteDown; public Room() { this.id = UUID.randomUUID(); @@ -35,12 +38,15 @@ public class Room { } public void resetPieces() { + this.canWhiteDown = false; this.pieces = new byte[16][16]; for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { this.pieces[i][j] = -1; } } + isWhiteAcceptRestart = false; + isBlackAcceptRestart = false; } public boolean isFull() { @@ -105,17 +111,56 @@ public class Room { byte originalValue = this.pieces[y][x]; if (originalValue != -1) return Optional.of("此位置已落子!"); if (whiteSession.getId().equals(sessionId)) { + if (!canWhiteDown) return Optional.of("请等待对手落子"); + canWhiteDown = false; this.pieces[y][x] = 1; } else { + if (canWhiteDown) return Optional.of("请等待对手落子"); + canWhiteDown = true; this.pieces[y][x] = 0; } return Optional.empty(); } public Optional isWin() { + for (int y = 0; y < 16; y++) { + for (int x = 0; x < 16; x++) { + byte startPointType = this.pieces[y][x]; + if (startPointType == -1) continue; + for (Faces value : Faces.values()) { + boolean facePossible = true; + for (int i = 1; i < 5; i++) { + int totalXDelta = value.xDelta * i; + int totalYDelta = value.yDelta * i; + int fullyX = x + totalXDelta; + int fullyY = y + totalYDelta; + if (fullyX < 0 || fullyX > 15 || fullyY < 0 || fullyY > 15) { + facePossible = false; + break; + } + if (this.pieces[fullyY][fullyX] != startPointType) { + facePossible = false; + break; + } + } + if (!facePossible) continue; + return Optional.of(new WinInfo(value, x, y, startPointType == 1)); + } + } + } return Optional.empty(); } + public void requestRestart(Session session) { + String sessionId = session.getId(); + if (sessionId.equals(whiteSession.getId())) { + isWhiteAcceptRestart = true; + } + if (sessionId.equals(blackSession.getId())) { + isBlackAcceptRestart = true; + } + } + public enum RoomState { CREATED, WAITING, diff --git a/src/main/java/org/mmga/clubs/entities/chess/packet/HasPlayerWinPacket.java b/src/main/java/org/mmga/clubs/entities/chess/packet/HasPlayerWinPacket.java new file mode 100644 index 0000000..eb2f235 --- /dev/null +++ b/src/main/java/org/mmga/clubs/entities/chess/packet/HasPlayerWinPacket.java @@ -0,0 +1,6 @@ +package org.mmga.clubs.entities.chess.packet; + +import org.mmga.clubs.entities.chess.Room; + +public record HasPlayerWinPacket(Room.WinInfo winInfo) { +} diff --git a/src/main/java/org/mmga/clubs/entities/chess/packet/request/ResetRoomRequest.java b/src/main/java/org/mmga/clubs/entities/chess/packet/request/ResetRoomRequest.java new file mode 100644 index 0000000..4fd7d38 --- /dev/null +++ b/src/main/java/org/mmga/clubs/entities/chess/packet/request/ResetRoomRequest.java @@ -0,0 +1,4 @@ +package org.mmga.clubs.entities.chess.packet.request; + +public record ResetRoomRequest() { +}