webSocket实现多人对战抢答的任务

最新要实现app答题对战的任务,准备用websocket去实现,查了百度也没参考,就自己写了写

实现 WebSocket 的抢答答题游戏可以按照以下步骤进行:

  1. 设计数据结构:为了记录每个玩家的得分和答题情况,可以定义一个玩家类(Player)来存储相关信息,例如玩家姓名、得分等。同时,需要设计题目数据的结构,可以使用题目类(Question)来表示每个问题,包括问题内容和正确答案。后面加了房间信息(room)

  2. 准备题目:在服务器端准备一系列的题目,并将其存储在列表或数组中。

  3. 1v1 模式答题流程:

    • 等待两个玩家加入游戏并建立 WebSocket 连接。
    • 随机选择一道题目发送给玩家。
    • 如果有一个玩家回答问题,正确并将答案发送给服务器。错误,就让他等待,如果没人回答或者都答错了,就等待10s之后跳下一题
    • 如果答案正确,则给第一个玩家加一分,并通知两个玩家当前得分情况。游戏结束。
    • 如果答案错误,则将问题和答案传递给下一个玩家,并重复上述步骤,直到有玩家答对或所有玩家都答错。
  4. 2v2 或多对多模式答题流程:

    • 等待足够数量的玩家加入并建立 WebSocket 连接。
    • 根据玩家人数随机分组,每个小组内玩家互为队友。
    • 随机选择一道题目发送给第一个小组的第一个玩家。
    • 第一个玩家回答问题,并将答案发送给服务器。
    • 如果答案正确,则给小组内所有玩家加一分,并通知所有玩家当前得分情况。游戏结束条件可根据实际需求设定。
    • 如果答案错误,则将问题和答案传递给下一个小组的第一个玩家,并重复上述步骤,直到有玩家答对或所有玩家都答错。

先创建对象:player 玩家信息


import lombok.Data;
import javax.websocket.Session;
import java.io.IOException;

// Player 类表示参与游戏的玩家和相关信息
@Data
public class Player {
        private Session session;
        private String name;
        private int score;
        private GameQuestion currentQuestion;
        private boolean playing;
        //游戏类型
        private String mode;
        private String roomId;
        //是否回答过问题
        private boolean answered;
        private int currentQuestionIndex;

        public Player(Session session) {
            this.session = session;
            //this.name = "Player " + session.getId();
            this.name =  session.getRequestParameterMap().get("name").get(0);
            this.score = 0;
            this.playing = false;
            this.mode = session.getRequestParameterMap().get("mode").get(0);
            this.currentQuestionIndex = 0;
        }

        public Session getSession() {
            return session;
        }

        public String getName() {
            return name;
        }

        public int getScore() {
            return score;
        }

        public void setScore(int score) {
            this.score = score;
        }

        public GameQuestion getCurrentQuestion() {
            return currentQuestion;
        }

        public void setCurrentQuestion(GameQuestion currentQuestion) {
            this.currentQuestion = currentQuestion;
        }

        public boolean isPlaying() {
            return playing;
        }

        public void setPlaying(boolean playing) {
            this.playing = playing;
        }



        public void send(String message) throws IOException {
            session.getBasicRemote().sendText(message);
        }

        public void addScore() {
            score++;
        }
}

room 房间信息


import lombok.Data;

import javax.management.timer.Timer;
import java.util.ArrayList;
import java.util.List;

/// Room 类表示游戏房间,包括玩家、题目、得分等信息
@Data
public class Room {
    private String roomName;
    private List<Player> players;
    private boolean started;
    private String mode; // 新增游戏模式字段

    private int currentQuestionIndex;
    private List<Question> questions;
    private Timer timer;

    public Room(String roomName) {
        this.roomName = roomName;
        this.players = new ArrayList<>();
        this.started = false;
        this.currentQuestionIndex = 0;
        this.questions = new ArrayList<>();
        this.timer = new Timer();
    }

}

问题信息  question


import lombok.Data;

// Question 类表示每个题目和对应答案
@Data
public class Question {
    private String content;
    private String answer;

    public Question(String content, String answer) {
        this.content = content;
        this.answer = answer;
    }

}

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/game")
public class Server {
    // 存储每个房间的玩家列表
    private static Map<String, List<Player>> rooms = new HashMap<>();
    // 存储每个玩家的答题状态和得分
    private static Map<Session, Player> players = new HashMap<>();
    // 存储问题
    private static List<Question> questions = new ArrayList<>();

    static {
        // 初始化一些题目
        questions.add(new Question("2+2=?", "4"));
        questions.add(new Question("3*7=?", "21"));
        questions.add(new Question("中国首都是?", "北京"));
    }

    @OnOpen
    public void onOpen(Session session) throws IOException {
        // 处理新玩家加入游戏的请求
        // 创建一个新的Player对象,并将其与session关联
        Player player = new Player(session);
        players.put(session, player);

        System.out.println("New player joined: " + player.getName());

        // 获取可加入的房间列表
        List<String> availableRooms = getAvailableRooms();
        if (availableRooms.isEmpty()) {
            // 如果没有可加入的房间,则创建新房间
            String roomId = createRoom();
            player.setRoomId(roomId);
            System.out.println("New room created: " + roomId);
            player.send("You created a new room: " + roomId);
        } else {
            // 加入第一个可加入的房间
            String roomId = availableRooms.get(0);
            player.setRoomId(roomId);
            System.out.println("Player joined room: " + roomId);
            player.send("You joined room: " + roomId);

            // 检查房间是否已满,如果已满则开始游戏
            if (isRoomFull(roomId)) {
                startGame(roomId);
            }
        }
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        // 处理玩家离开游戏的请求
        // 从players中移除离开的玩家,并检查房间是否需要解散
        Player player = players.get(session);
        players.remove(session);
        if (player != null) {
            leaveRoom(player);
        }
        System.out.println("Player left: " + player.getName());
    }

    @OnError
    public void onError(Throwable throwable) {
        // 处理WebSocket错误
        System.err.println("WebSocket error: " + throwable.getMessage());
    }

    @OnMessage
    public void onMessage(Session session, String message) throws IOException {
        // 处理玩家答题的请求
        Player player = players.get(session);
        if (player != null && player.isPlaying() && !player.isAnswered()) {
            Question currentQuestion = player.getCurrentQuestion();
            if (message.equals(currentQuestion.getAnswer())) {
                // 答案正确,增加玩家分数,并广播当前得分情况
                player.addScore();
                broadcastScores(player.getRoomId());
                player.setAnswered(true);
                player.send("Correct! Your score is now " + player.getScore());

                // 检查是否所有玩家都已经答过题
                if (areAllPlayersAnswered(player.getRoomId())) {
                    checkGameOver(player.getRoomId());
                }
            } else {
                // 答案错误,提示下一个玩家答题
                player.send("Wrong answer, please wait for the next question.");
                passQuestion(player.getRoomId());
            }
        }
    }

    private List<String> getAvailableRooms() {
        // 获取当前可加入的房间列表
        List<String> availableRooms = new ArrayList<>();
        for (String roomId : rooms.keySet()) {
            if (!isRoomFull(roomId)) {
                availableRooms.add(roomId);
            }
        }
        return availableRooms;
    }

    private boolean isRoomFull(String roomId) {
        // 检查房间是否已满
        List<Player> roomPlayers = rooms.get(roomId);
        return roomPlayers != null && roomPlayers.size() >= 2;
    }

    private String createRoom() {
        // 创建新的房间
        String roomId = generateRoomId();
        rooms.put(roomId, new ArrayList<>());
        return roomId;
    }

    private String generateRoomId() {
        // 生成唯一的房间ID
        String roomId;
        do {
            // 随机生成4位数的字符串作为房间ID
            roomId = String.format("%04d", new Random().nextInt(10000));
        } while (rooms.containsKey(roomId));
        return roomId;
    }

    private void leaveRoom(Player player) throws IOException {
        // 离开房间,并检查房间是否需要解散
        String roomId = player.getRoomId();
        List<Player> roomPlayers = rooms.get(roomId);
        roomPlayers.remove(player);
        System.out.println("Player left room: " + roomId);

        // 如果离开的是最后一个玩家,则解散房间
        if (roomPlayers.isEmpty()) {
            rooms.remove(roomId);
            System.out.println("Room dissolved: " + roomId);
        } else {
            if (player.isPlaying() && !player.isAnswered()) {
                // 如果离开的玩家正在答题中且未回答,则传递问题给下一个玩家
                passQuestion(roomId);
            }
            // 广播当前得分情况
            broadcastScores(roomId);
        }
    }

    private void startGame(String roomId) throws IOException {
        // 开始游戏,发送第一个题目给每个玩家
        List<Player> roomPlayers = rooms.get(roomId);
        List<Question> gameQuestions = new ArrayList<>(questions);
        Collections.shuffle(gameQuestions);
        for (int i = 0; i < roomPlayers.size(); i++) {
            Player player = roomPlayers.get(i);
            player.setPlaying(true);
            player.setScore(0);
            player.setCurrentQuestion(gameQuestions.get(i));
            player.setAnswered(false);
            player.send("Game started! Answer this question: " + gameQuestions.get(i).getContent());
        }
        // 启动定时器,10秒内没有玩家答题则自动进入下一题
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (areAllPlayersAnswered(roomId)) {
                    checkGameOver(roomId);
                } else {
                    passQuestion(roomId);
                }
            }
        }, 10000);
    }

    private void passQuestion(String roomId) throws IOException {
        // 将问题传递给下一个玩家
        List<Player> roomPlayers = rooms.get(roomId);
        Player currentPlayer = getCurrentPlayer(roomPlayers);
        currentPlayer.setAnswered(true);
        int nextIndex = (roomPlayers.indexOf(currentPlayer) + 1) % roomPlayers.size();
        Player nextPlayer = roomPlayers.get(nextIndex);
        nextPlayer.setPlaying(true);
        nextPlayer.setCurrentQuestion(currentPlayer.getCurrentQuestion());
        nextPlayer.setAnswered(false);
        nextPlayer.send("Answer this question: " + currentPlayer.getCurrentQuestion().getContent());
    }

    private void checkGameOver(String roomId) throws IOException {
        // 检查游戏是否结束
        List<Player> roomPlayers = rooms.get(roomId);
        boolean allAnswered = true;
        for (Player player : roomPlayers) {
            if (!player.isAnswered()) {
                allAnswered = false;
                break;
            }
        }
        if (allAnswered) {
            // 所有玩家都已答题完毕,比较分数并广播结果
            List<Player> winners = getWinners(roomPlayers);
            String message;
            if (winners.isEmpty()) {
                message = "Game over! It's a tie.";
            } else {
                message = "Game over! Winners: ";
                for (Player winner : winners) {
                    message += winner.getName() + "(" + winner.getScore() + " points) ";
                }
            }
            for (Player player : roomPlayers) {
                player.send(message);
            }
        }
    }

    private List<Player> getWinners(List<Player> players) {
        // 获取分数最高的玩家
        List<Player> winners = new ArrayList<>();
        int maxScore = 0;
        for (Player player : players) {
            int score = player.getScore();
            if (score > maxScore) {
                maxScore = score;
                winners.clear();
                winners.add(player);
            } else if (score == maxScore) {
                winners.add(player);
            }
        }
        return winners;
    }

    private boolean areAllPlayersAnswered(String roomId) {
        // 检查是否所有玩家都已经答过题
        List<Player> roomPlayers = rooms.get(roomId);
        for (Player player : roomPlayers) {
            if (!player.isAnswered()) {
                return false;
            }
        }
        return true;
    }

    private void broadcastScores(String roomId) throws IOException {
        // 广播当前得分情况
        List<Player> roomPlayers = rooms.get(roomId);
        String scoreMessage = "Current scores: ";
        for (Player player : roomPlayers) {
            scoreMessage += player.getName() + "(" + player.getScore() + " points) ";
        }
        for (Player player : roomPlayers) {
            player.send(scoreMessage);
        }
    }

    private Player getCurrentPlayer(List<Player> players) {
        // 获取当前回答问题的玩家
        for (Player player : players) {
            if (!player.isAnswered()) {
                return player;
            }
        }
        return players.get(0);
    }
}

提供的这个demo发送问题是一个一个发送的,可以把player.send的地方修改一下,修改成全部人一起抢答一题,然后谁先答对就全部通知,然后刷新下一题。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随风奔跑的十八岁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值