Java Learning - 6.3 五子棋联机模式

2023-11-09

        在前一篇博文中完成了单机五子棋的编写,接下来将在其基础上完成联机模式,这里的联机模式采用主从形式,需要服务器端启动后,等待客户端连接以匹配游戏

目录

过程存储

胜负逻辑

悔棋

重新开始

存储本局棋谱

回放棋局

下一步


服务器类

       为了进行联机模式,首先需要一个服务器类来完成ServerSocket的创建,其中封装listen()方法提供监听调用

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class GoBang_Server {
    private final int port = 20000;
    private final ServerSocket serverSocket;

    GoBang_Server() {
        try {
            serverSocket = new ServerSocket(port);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public Socket listen() {
        try {
            return serverSocket.accept();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

 联机模式按键

        创建并在UI中添加联机模式按键,这就不做赘述了,重要的是在其监听器上加入创建线程用于建立连接并且接收来自客户端的信息

            {
                //更新模式标志位
                board_listener.setOnline_flag(true);
                board_listener.setOffline_flag(false);

                chess_utils.show_dialog("联机模式开启成功,请等待对手连接到对局");
                //创建线程用于通信
                if(!board_listener.isThread_flag())
                    create_thread();
            }

        这里封装了一个create_thread,它创建了一个线程用于监听来自客户端的连接,并且创建一些通信流,并且每一次通信都按照一定的规则(开头的int是cmd),接收到命令后执行对应操作

    public void create_thread(){
        new Thread(() -> {
            DataInputStream dataInputStream;
            DataOutputStream dataOutputStream;
            socket = goBang_server.listen();
            try {
                dataInputStream = new DataInputStream(socket.getInputStream());
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
            board_listener.setConnected(true);
            try {
                dataOutputStream = new DataOutputStream(socket.getOutputStream());
                board_listener.setDataOutputStream(dataOutputStream);
                regret_button_listener.setDataOutputStream(dataOutputStream);
                startover_button_listener.setDataOutputStream(dataOutputStream);
                exit_button_listener.setDataOutputStream(dataOutputStream);

            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
            chess_utils.show_dialog("已配对到对手,请您先落子");
            while (true) {
                try {
                    int cmd = dataInputStream.readInt();
                    //下棋通信
                    switch (cmd) {...}
            }
        }
    }

操作请求

        在联机模式下,悔棋、重新开始等都需要经过对方同意,因此要发送相关cmd,这里以请求悔棋为例

        //联机模式
        else if(board_listener.isOnline_flag()){
            //到我下了 不能悔棋
            if(board_listener.isOnline_myturn() || board_listener.getWin_flag()!=0 || chess_flow.empty() || board_listener.isStartover_flag() || board_listener.isRegret_flag()){
                chess_utils.show_dialog("当前不可悔棋");
            }
            else{
                try {
                    board_listener.setRegret_flag(true);
                    dataOutputStream.writeInt(REGRET_REQUEST);
                    dataOutputStream.flush();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            }

        }

        对方在收到这个REGRET_REQUEST的cmd后,会在线程中进行处理,这里贴出对悔棋请求的处理,这个处理是在上面贴出的创建的通信线程的switch语句中进行的

//悔棋通信
case REGRET_REQUEST:
    int i=JOptionPane.showConfirmDialog(null,"对方请求悔棋,是否同意","提示",JOptionPane.YES_NO_OPTION);
        //不同意悔棋
    if(i==1){
        //发送REGRET_REQUEST_DENY
        dataOutputStream.writeInt(REGRET_REQUEST_DENY);
        dataOutputStream.flush();
        }
        //同意悔棋
        else{
        //发送REGRET_REQUEST_APPROVE
        dataOutputStream.writeInt((REGRET_REQUEST_APPROVE));
        dataOutputStream.flush();
        board_listener.setOnline_myturn(false);
        int[]pos_1=chess_flow.pop();
        int chess_flag=map[pos_1[0]][pos_1[1]];
        if(chess_flag>0){
        map[pos_1[0]][pos_1[1]]=0;
        board_listener.setChess_flag(chess_flag);
        panel_board.repaint();
        }
    }
        break;

控制flag 

        在加入通信后,由于各自要维护棋局信息,因此要加入很多的用于控制的flag,这里不做展示了,大家可以自己思考,这里仅给出一些例子,比如在请求悔棋时不能进行落子、请求重新开始等,这就需要一个flag来进行控制!

客户端

        客户端的基本架构与服务器一致,仅仅在先后行棋等方面不同!另外也不需要一个客户端类来维护socket,直接在online_button_listener中维护一个线程进行通信即可

       至此,联机模式下的一些功能已经完善,这里附上 git仓库

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java Learning - 6.3 五子棋联机模式 的相关文章

随机推荐

  • Linux设置进程名称(标题) ( 7) -【Linux通信架构系列 】

    系列文章目录 C 技能系列 Linux通信架构系列 C 高性能优化编程系列 深入理解软件架构设计系列 高级C 并发线程编程 期待你的关注哦 现在的一切都是为将来的梦想编织翅膀 让梦想在现实中展翅高飞 Now everything is fo
  • MyBatis Generator 生成的example 使用 and or 简单混合查询

    MyBatis Generator 生成的example 使用 and or 简单混合查询 参考博客 https www cnblogs com kangping p 6001519 html 简单介绍 Example类用于构造复杂的筛选条
  • glTF格式初步了解

    glTF格式初步了解 最近看到Qt 3D的进展 偶然了解到了一种新的格式 glTF格式 这种格式据说比现有的3D格式更加符合OpenGL应用的需要 这引起了我的好奇 于是我在Qt 3D的外部链接中找到了有关glTF的相关链接 上海萌梦信息科
  • Mysql int(11)和Oracles nubmer(11) 的区别

    先说Mysql int 11 到底代表什么意思 这里的int 11 不是表示限制int的长度为11 而是字符的显示宽度 在字段类型为int时 无论你显示宽度设置为多少 int类型能存储的最大值和最小值永远都是固定的 那么这个显示宽度到底有什
  • Java中final关键字的作用

    final关键字可以用来修饰引用 方法和类 1 用来修饰一个引用 如果引用为基本数据类型 则该引用为常量 该值无法修改 如果引用为引用数据类型 比如对象 数组 则该对象 数组本身可以修改 但指向该对象或数组的地址的引用不能修改 如果引用为类
  • 开源DataX集成可视化项目Datax-Web的安装

    关于datax web项目 在做DataX项目测试的时候又收到github的推荐邮件 推荐了一个datax web的开源项目 这不是瞌睡遇到枕头 再研究研究这个项目是不是符合数据同步的要求 datax web https github co
  • JavaWeb 【基础】 servelet 异步操作

    在实际工作中我们会遇到一些耗时操作 这个时候如果不能及时response 就会返回失败 想要执行异步操作 延时返回数据 可以使用以下方法 使用asyncSupported true注解 WebServlet name apitest asy
  • Mysql基础(十二):隔离/锁/MVCC/ReadView

    目录 1 业务系统并发对数据库执行事务 2 脏写 脏读 3 不可重复读 4 幻读 5 事务隔离机制 6 MySQL如何支持4种隔离级别 Spring事务注解如何设置 7 undo log版本链是个什么东西 8 ReadView机制 多个事务
  • Java课题笔记~ Axios

    Axios 对原生的AJAX进行封装 简化书写 Axios官网是 https www axios http cn 2 1 基本使用 axios 使用是比较简单的 分为以下两步 引入 axios 的 js 文件 使用axios 发送请求 并获
  • Steam 灵感的游戏卡悬停效果

    先看效果 再看代码 查看更多
  • 【CSAPP】Binarybomb 实验(phase_1-6+secret_phase)

    Binarybomb 实验 phase 1 6 secret phase 实验内容 一个 binary bombs 二进制炸弹 下文将简称为炸弹 是一个Linux可执行C程序 包含了7个阶段 phase1 phase6和一个隐藏阶段 炸弹运
  • ROS学习笔记13--urdf文件报错:GazeboRosControlPlugin missing <legacyModeNS> while using DefaultRobotHWSim.....

    环境 ubuntn16 04 ROS kinetic vs code urdf文件运行时候报错如下 ERROR 1527494740 144219702 307 635000000 GazeboRosControlPlugin missin
  • jobdu 1 排序

    题目描述 对输入的n个数进行排序并输出 输入 输入的第一行包括一个整数n 1 lt n lt 100 接下来的一行包括n个整数 输出 可能有多组测试数据 对于每组数据 将排序后的n个整数输出 每个数后面都有一个空格 每组测试数据的结果占一行
  • MySQL存储过程与存储函数的区别

    语法定义上的区别就不说了 说一下其他的 如果有不正确的地方 还请大家指正 1 总述 存储函数和存储过程统称为存储例程 stored routine 两者的定义语法很相似 但却是不同的内容 存储函数限制比较多 比如不能用临时表 只能用表变量
  • STM32F4 DWT功能 实现程序运行时间精确测试

    时间戳相关寄存器定义 在Cortex M里面有一个外设叫DWT Data Watchpoint and Trace 该外设有一个32位的寄存器叫CYCCNT 它是一个向上的计数器 记录的是内核时钟运行的个数 最长能记录的时间为 10 74s
  • Dubbo各种协议

    原文地址 http dubbo io User Guide zh htm UserGuide zh 协议参考手册 协议参考手册 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 img QStFh0Ov 166207932
  • 给定一系列正整数请按要求对数字进行分类并输出以下 5 个数字:A1=能被 5 整除的数字中所有偶数的和被5除后余1的数字按给出顺序进行交错求和被5除后余2的数字的个数被5除后余 3 的数字的平均数

    1012 数字分类 20 分 给定一系列正整数 请按要求对数字进行分类 并输出以下 5 个数字 A1 能被 5 整除的数字中所有偶数的和 A2 将被 5 除后余 1 的数字按给出顺序进行交错求和 即计算 n1 n2 n3 n4 A3 被 5
  • k8s资源控制

    文章目录 资源限定 资源限定 tomcat deploy yml apiVersion extensions v1beta1 kind Deployment metadata name tomcat deploy spec replicas
  • malloc相关内容,你知道吗?

    当一个程序经过预编译 编译 链接之后到底经历了一个怎样的过程呢 当我们写的程序内有malloc操作 那么内存到底可以申请多大呢 简单的来说下 程序首先在编译器中 经过编译之后会形成汇编格式的 o后缀的文件 经过链接之后 形成 exe的可执行
  • Java Learning - 6.3 五子棋联机模式

    在前一篇博文中完成了单机五子棋的编写 接下来将在其基础上完成联机模式 这里的联机模式采用主从形式 需要服务器端启动后 等待客户端连接以匹配游戏 目录 过程存储 胜负逻辑 悔棋 重新开始 存储本局棋谱 回放棋局 下一步 服务器类 为了进行联机