IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java 在线纸牌游戏 -> 正文阅读

[Java知识库]Java 在线纸牌游戏

作者:token keyword

Java TCP通信 FastJson 在线纸牌游戏

主要想法

  • 设计初衷:本作品名称叫做在线纸牌游戏。开发该作品的原因:在学习了JavaTCP与UDP网络编程的相关知识,以及对Java多线程知识比较感兴趣所以结合两者知识萌生了一个制作在线纸牌游戏的想法。
  • 该作品的主要功能是:第一,在线即时信息聊天,具体表现为在游戏开始之前,玩家进入了相应的房间之后,玩家可以跟同在房间内的玩家进行聊天。第二,纸牌的玩法,与斗地主的规则类似,只不过本游戏的地主是随机分配,且三名玩家的牌的数量相同,最先出完的玩家赢得游戏的胜利。
  • 主要用法:首先在云服务器上运行Server端,之后只要在本地终端或者java编辑器中运行Client端程序即可。游戏需要三名玩家在同一房间内才可以进行游戏。
  • 借鉴产品:斗地主
  • 创新点:
    1.采用TCP封装Send和Receive方法,在方法传输上具有稳定和即时的特点
    2.传输的信息封装以及解析采用了FastJson的数据序列化和反序列化方法。通过FastJson把程序中的Data对象转化为特定格式的Json字符串传输。其特点是有稳定性和速度极快。

概要设计

client:

在这里插入图片描述

Server:

在这里插入图片描述

人机交互:

在这里插入图片描述

核心代码部分

  • 牌型获取
/**
     * create by: shoutoudelanfanqie
     * description: 返回提供的牌的牌型。
     * 经过判断每一张牌是否属于正确的牌
     *    1张牌:PASS或者一张单牌
     *    2张牌:对子或者王炸
     *    3张牌:三个X
     *    4张牌:炸子或者三带一
     *    5张牌:单牌顺子或者三带一对
     *    6张牌:对子顺子
     *    7张牌:单牌顺子
     *    8张牌:对子顺子
     *    10张牌:对子顺子
     * create time: 2022/5/19 20:45
     * @param cardSeparated 已经从String分开的牌的集合体
     * @return java.lang.String
     */
    public static String getCardType(String[] cardSeparated){
        //如果自己没有这张牌那么直接返回错误的牌
        if(!isConfirmed(cardSeparated)){
            return WRONG_CARD;
        }

        int cardLength=cardSeparated.length;

        switch (cardLength) {
            case 1-> {
                if (cardSeparated[0].equals(PASS)) {
                    return PASS;
                } else {
                    return SINGLE;
                }
            }
            case 2-> {
                if (isSame(cardSeparated)) {
                    return PAIRS;
                } else if (cardSeparated[0].equals(BIG_KING)
                        && cardSeparated[1].equals(SMALL_KING)) {
                    return KING_BOMB;
                } else {
                    return WRONG_CARD;
                }
            }
            case 3-> {
                if (isSame(cardSeparated)) {
                    return THREES;
                } else {
                    return WRONG_CARD;
                }
            }
            case 4-> {
                if (isSame(cardSeparated)) {
                    return BOMB;
                } else if (isSame(cardSeparated, 1, 3)
                        && !cardSeparated[3].equals(SMALL_KING)
                        && !cardSeparated[3].equals(BIG_KING)) {
                    return THREE_WITH_SINGLE;
                } else {
                    return WRONG_CARD;
                }
            }
            case 5,7-> {
                if (isSame(cardSeparated, 1, 3)
                        && isSame(cardSeparated, 4, 5)) {
                    return THREE_WITH_PAIRS;
                } else if (isShunZi(cardSeparated, SINGLE_SHUN_ZI)) {
                    return SINGLE_SHUN_ZI;
                } else {
                    return WRONG_CARD;
                }
            }
            case 6,8-> {
                if (isShunZi(cardSeparated, SINGLE_SHUN_ZI)) {
                    return SINGLE_SHUN_ZI;
                } else if (isShunZi(cardSeparated, PAIRS_SHUN_ZI)) {
                    return PAIRS_SHUN_ZI;
                } else {
                    return WRONG_CARD;
                }
            }
            case 10-> {
                if (isShunZi(cardSeparated, PAIRS_SHUN_ZI)) {
                    return PAIRS_SHUN_ZI;
                }
            }
        }
        return WRONG_CARD;
    }
  • Send和Receive封装
/**
      * create by: shoutoudelanfanqie
      * description: 接受来自服务器信息的静态方法
      * create time: 2022/5/29 11:18
      */
    public static Data receive(){
        String msgReceived = null;
        try {
            msgReceived =dis.readUTF();
        } catch (IOException e) {
            System.out.println("数据接受异常");
        }
        Data data= JSONObject.parseObject(msgReceived,Data.class);

        return data;
    }


    /**
      * create by: shoutoudelanfanqie
      * description: 向服务器发送信息的方法
      * create time: 2022/5/29 11:19
      *
      * @param msgToBeSend 将要发送的信息
      */
    public static void send(Data msgToBeSend){

        if(msgToBeSend!=null){
            try {
                String msg=JSONObject.toJSONString(msgToBeSend);
                dos.writeUTF(msg);

                dos.flush();
            } catch (IOException e) {
                System.out.println("连接异常!");
            }
        }
    }
  • Server端的出牌提示逻辑
/**
      * @author: shoutoudelanfanqie
      * @description: 游戏开始,玩牌
      * @createtime: 2022/5/31 15:56
     */
    public void playCards() {
        while (gameIsStart) {
            //默认第二个玩家第一个出牌
            dataReceived = playerMap.get(secondPlayer).getTransmit().receive();
            if (dataReceived.getDataType().equals(Type.GAME_OVER)) {
                //如果出牌是结束信息,那么向所有人发送信息通知游戏已结束
                playerMap.get(secondPlayer).sendToOther(dataReceived, this.getPlayerMap());
                break;
            } else if (dataReceived.getDataType().equals(Type.CARD_PLAY)) {
                System.out.println("信息种类:" + dataReceived.getDataType() + "   房间号:" + this.roomNumber +
                                "   出牌人:" + dataReceived.getWhoSend() +
                                "   出牌类型:" + dataReceived.getCardType() + "   出牌内容:" + dataReceived.getDataText());
                //在服务端的后台输出出牌信息
                //如果是出牌信息
                dataReceived.setMyTurn(false);
                //按照顺序给另外两名玩家设定是否出牌
                playerMap.get(firstPlayer).getTransmit().send(dataReceived);
                //2号是地主先出牌,所以2号出完之后1号不出,3号出牌
                dataReceived.setMyTurn(true);
                playerMap.get(thirdPlayer).getTransmit().send(dataReceived);
            }


            dataReceived = playerMap.get(thirdPlayer).getTransmit().receive();
            if (dataReceived.getDataType().equals(Type.GAME_OVER)) {
                //如果出牌是结束信息,那么向所有人发送信息通知游戏已结束
                playerMap.get(secondPlayer).sendToOther(dataReceived, this.getPlayerMap());
                break;
            } else if (dataReceived.getDataType().equals(Type.CARD_PLAY)) {
                System.out.println("信息种类:" + dataReceived.getDataType() + "   房间号:" + this.roomNumber +
                        "   出牌人:" + dataReceived.getWhoSend() +
                        "   出牌类型:" + dataReceived.getCardType() + "   出牌内容:" + dataReceived.getDataText());
                //在服务端的后台输出出牌信息
                dataReceived.setMyTurn(false);
                playerMap.get(secondPlayer).getTransmit().send(dataReceived);
                dataReceived.setMyTurn(true);
                playerMap.get(firstPlayer).getTransmit().send(dataReceived);
            }


            dataReceived = playerMap.get(firstPlayer).getTransmit().receive();
            if (dataReceived.getDataType().equals(Type.GAME_OVER)) {
                //如果出牌是结束信息,那么向所有人发送信息通知游戏已结束
                playerMap.get(secondPlayer).sendToOther(dataReceived, this.getPlayerMap());
                break;
            } else if (dataReceived.getDataType().equals(Type.CARD_PLAY)) {
                System.out.println("信息种类:" + dataReceived.getDataType() + "   房间号:" + this.roomNumber +
                        "   出牌人:" + dataReceived.getWhoSend() +
                        "   出牌类型:" + dataReceived.getCardType() + "   出牌内容:" + dataReceived.getDataText());
                //在服务端的后台输出出牌信息
                dataReceived.setMyTurn(true);
                playerMap.get(secondPlayer).getTransmit().send(dataReceived);
                dataReceived.setMyTurn(false);
                playerMap.get(thirdPlayer).getTransmit().send(dataReceived);
            }
        }
    }

主要测试

  • 运行速度上:由TCP以及FastJson的保证,在信息传输和展示上速度快且准确率高。但是在一些特定场景,比如说牌的展示上,为了获得一些动态的效果,采用了sleep
  • 安全性: 安全性较低,在一些不确定场景会出现线程安全问题,因为本人对线程类知识匮乏,所以在一些特定场景下存在较多线程安全的问题。
  • 部署方便性:部署较为方便合理,只需要在服务器上运行Server程序,之后在本地终端上运行Client程序即可
  • 可用性:房间复用性较差(作者尝试解决但是未果)。房间只能一次性使用,即一个服务端的开启最多支持五轮游戏。

更多图片

在这里插入图片描述

使用方法

  • 第一步:在java编辑器或者安装了jdk的设备终端上运行Server.jar程序
    在这里插入图片描述

  • 第二步:在终端运行Client.jar
    在这里插入图片描述

  • 第三步:根据提示进行游戏即可
    在这里插入图片描述

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-06-06 17:11:36  更:2022-06-06 17:13:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 19:57:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码