【Java学习笔记】实战——网络象棋

服务端
客户端
项目结构

源码

1、服务端:主函数

package jiemian;

import moxing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class jiemian1 extends JFrame implements ActionListener {
    JLabel bq = new JLabel("端口号");// 创建标签 用于显示文本框中的内容表示的是什么
    JTextField wbk = new JTextField("9999");// 创建文本框 并初始化文本框中的内容
    JButton b1 = new JButton("开启");// 创建 开始 按钮
    JButton b2 = new JButton("关闭");// 创建 关闭 按钮
    JPanel p1 = new JPanel();// 创建面板用于添加 按钮 标签 文本框
    Vector online = new Vector();// 用于存储在线用户的集合
    JList lis = new JList();// 创建列表
    JScrollPane gd = new JScrollPane(lis);
    JSplitPane fg = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, gd, p1);
    ZThread zt;// 创建主线程对象

    public static void main(String[] args) {
        jiemian1 one = new jiemian1();
    }

    public jiemian1()// 构造函数
    {
        this.cskj();// 初始化控件
        this.sjjt();// 初始化监听scrollPane.getViewport().setView(myList);
        this.csct();// 初始化窗体
    }

    public void cskj()// 初始化组件的函数
    {
        p1.setLayout(null);
        bq.setBounds(20, 20, 50, 50);
        p1.add(bq);// 将标签添加进面板
        wbk.setBounds(70, 35, 50, 20);
        p1.add(wbk);// 将文本框添加进面板
        b1.setBounds(15, 70, 60, 20);
        p1.add(b1);// 将开启服务器按钮添加进面板
        b2.setBounds(85, 70, 60, 20);
        b2.setEnabled(false);// 将关闭按钮设置成不可操作的
        p1.add(b2);// 将关闭按钮添加进面板
        fg.setDividerLocation(230);// 设置分割条的位置
        fg.setDividerSize(4);// 设置分割条的大小

    }

    public void csct()// 初始化窗体的函数
    {
        this.add(fg);
        this.setTitle("网络象棋服务器");
        this.setSize(420, 400);
        int wieth = Toolkit.getDefaultToolkit().getScreenSize().width;
        int heigth = Toolkit.getDefaultToolkit().getScreenSize().height;
        this.setLocation(wieth / 2 - 200, heigth / 2 - 200);
        this.setVisible(true);
        this.setResizable(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void sjjt()// 为组件做监听的函数
    {
        b1.addActionListener(this);
        b2.addActionListener(this);
    }

    public void sjnr1()// 按下启动按钮后做的动作
    {
        int ii = 0;
        try {
            String str = wbk.getText().trim();
            ii = Integer.parseInt(str);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, "端口号填写错误,为整数(0-65535)");
            return;
        }
        if (ii < 0 || ii > 65535) {
            JOptionPane.showMessageDialog(this, "端口号填写错误,为整数(0-65535)");
            return;
        }
        JOptionPane.showMessageDialog(this, "服务器开启成功");
        b2.setEnabled(true);// 将关闭按钮设为可操作
        b1.setEnabled(false);// 将开启按钮设为不可操作
        this.wbk.setEditable(false);
        this.sxlist();
        zt = new ZThread(this);
        zt.start();// 开启主线程
    }

    public void sjnr2()// 按下关闭按钮后的动作
    {
        JOptionPane.showMessageDialog(this, "服务器关闭成功");
        this.b2.setEnabled(false);// 将关闭按钮设为不可操作
        this.b1.setEnabled(true);// 将开启按钮设为可操作
        this.wbk.setEditable(true);
        zt.shengm(false);// 将主线程的生命设为False
        zt.close();// 关闭ss he s
        online.clear();// 将在线用户清除
        lis.setListData(online);// 刷新在线用户列表
    }

    public void sxlist()// 刷新列表的函数
    {
        // for(int i=0;i<20;i++){
        // online.add("dfsdfasdf");
        // }
        lis.setListData(online);

    }

    public Vector getVector() {
        return online;
    }

    public void actionPerformed(ActionEvent e)// 重写事件里的方法
    {
        if (e.getSource() == b1) {
            this.sjnr1();
        } else if (e.getSource() == b2) {
            this.sjnr2();
        }
    }

}

2、服务端:主线程

package moxing;

import jiemian.jiemian1;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;

public class ZThread extends Thread {
    ServerSocket ss;// 声明ServerSocket 引用
    boolean flag = true;
    jiemian1 jm;//
    FThread zh;

    public ZThread(jiemian1 jm)// 构造函数
    {
        this.jm = jm;
        this.cjss();// 对ServerSocket 进行初始化
    }

    public void cjss()// ServerSocket 初始化的函数
    {
        try {
            ss = new ServerSocket(9999);

        } catch (Exception e) {
            System.out.println(e.toString());
        }
        System.out.println("ServerSocket 初始化成功");
    }

    public void shengm(boolean a)// 设置主线程生命的方法
    {
        flag = a;

    }

    int sum = 1;

    public void run()// run 方法
    {
        while (flag) {

            try {
                System.out.println("正在等待接收第:" + sum + "个客户端的链接");
                Socket s = ss.accept();// 接收 Socket 对象,也就是等待客户端的链接
                zh = new FThread(jm, s);// 创建分线程的对象
                zh.start();// 启动分线程
            } catch (Exception e) {
                System.out.println(e.toString());
            }

            System.out.println("主线程接收到客户端的链接   Socket 对象创建成功");

            sum++;// 用于显示第几个客户端
        }
        System.out.println("主线程正常关闭");
    }

    public void close()// 关闭 ServerSocket 和 Socket 的方法
    {
        try {

            ss.close();// 关闭serversocket 方法
            zh.clse();// 调用分线程的服务器关闭方法
        } catch (Exception e) {
            System.out.println("服务关闭异常" + e.toString());
        }
    }
}

3、服务端:子线程

package moxing;

import jiemian.jiemian1;//导入界面包
import java.net.*;
import java.io.*;
import java.util.*;

public class FThread extends Thread {
    Socket s;// 创建Socket 引用
    Vector v = new Vector();// 建立Vector 集合
    boolean sm = true;// 初始化辅助线程的生命
    DataInputStream din;// 声明数据输入流对象引用
    DataOutputStream dou;// 声明数据输出流对象引用
    jiemian1 jm;// 声明主界面的类引用

    public FThread(jiemian1 jm, Socket s)// 构造方法 参数 从主线程传入的 Socket 对象
    {
        this.jm = jm;
        this.s = s;
        this.cjfzxc();// 初始化数据流
        
    }

    public void cjfzxc()// 创建数据流的方法
    {
        try {
            din = new DataInputStream(s.getInputStream());
            dou = new DataOutputStream(s.getOutputStream());
        } catch (Exception e) {
            System.out.println("辅助线程 数据流的创建异常:" + e.toString());
        }

    }

    public void shengm1(boolean boo)// 改变辅助线程的生命
    {

        sm = boo;

    }

    public void run()// run 方法

    {
        System.out.println("进入辅助线程");
        while (sm) {
            try {

                String str = din.readUTF().trim();
                System.out.println("客户端发来的昵称:" + str);
                if (str.startsWith("#nc#"))// 客户端新用户上线
                {
                    this.xyh(str);// 用户上线的方法
                } else if (str.startsWith("#likai#"))// 客户端离开
                {
                    this.yhlk(str);// 用户离开的方法
                } else if (str.startsWith("#tiaozhan#"))// 客户端发送挑战的信息
                {
                    this.yhfqtz(str);
                } else if (str.startsWith("#jieshou#"))// 客户端接受挑战
                {
                    this.yhjstz(str);
                } else if (str.startsWith("#jjtz#"))// 客户端拒绝挑战
                {
                    this.yhjjtz(str);// 被挑战者拒绝挑战的方法
                } else if (str.startsWith("#yjjstz#"))// 客户端已经接受了挑战(第一种情况)
                {
                    this.yjjstz(str);
                } else if (str.startsWith("#yhfm#"))// 客户端已经接受了挑战 (第二种情况)
                {
                    this.yhfm(str);
                } else if (str.startsWith("#renshu#"))// 客户端认输的方法
                {
                    this.renshu(str);
                } else if (str.startsWith("#yidong#"))// 收到客户端发来移动棋子的信息
                {
                    this.yidong(str);
                }
            } catch (Exception e) {
                System.out.println("辅助线程读取异常" + e.toString());
            }

        }
    }

    public void xyh(String str)// 新用户的方法
    {
        String name = str.substring(4);
        this.setName(name);
        boolean boo = false;
        v = jm.getVector();
        for (Iterator it = v.iterator(); it.hasNext();) {
            FThread aa = (FThread) it.next();
            String bb = aa.getName();
            if (bb.equals(name)) {
                boo = true;
                break;
            }
        }
        if (boo == true)// 如果出现重名
        {
            try {
                this.dou.writeUTF("#chongming#");
                this.s.close();
                this.din.close();
                this.dou.close();
                this.sm = false;
                System.out.println("重名了");
            } catch (Exception e) {
            }
        } else {
            
            try {
                this.dou.writeUTF("#nochongming#");
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            
            v = jm.getVector();// 获取主界面的集合
            v.add(this);// 讲读取到的昵称添加进集合
            jm.sxlist();// 更新主界面列表中的集合数据
            for (Iterator it = v.iterator(); it.hasNext();) {
                FThread na = (FThread) it.next();// 获取服务器中的所有线程
                for (int i = 0; i < v.size(); i++)// 再次便利获取所有线程的名字
                {
                    FThread ft = (FThread) v.get(i);
                    try {
                        // 让每一个线程把所有线程的名字都发送到每个客户端
                        na.dou.writeUTF("#liebiao#" + ft.getName());
                    } catch (Exception e) {
                    }
                }

                if (!na.getName().equals(name)) {// 将新上线的用户名字发给每个在线用户
                    try {
                        na.dou.writeUTF("#tishi#" + name);
                    } catch (Exception e) {
                    }

                }

            }
        }

    }

    public void yhlk(String str)// 用户离开的方法
    {
        System.out.println("收到用户离开的消息");
        String name = str.substring(7);
        v = this.jm.getVector();
        for (Iterator it = v.iterator(); it.hasNext();) {
            FThread ft = (FThread) it.next();
            if (!(ft.getName().equals(name)))// 将离开的用户发送给每个在线用户
            {
                try {
                    ft.dou.writeUTF("#likai#" + name);
                } catch (Exception e) {
                }
            } else if (ft.getName().equals(name))// 将下线的用的线程关闭
            {
                try {
                    ft.din.close();
                    ft.dou.close();
                    ft.s.close();
                    ft.sm = false;
                } catch (Exception e) {
                }
            }

        }
        for (Iterator it = v.iterator(); it.hasNext();)// 便利服务器的列表讲下线用户删除
        {
            FThread fy = (FThread) it.next();
            if (fy.getName().equals(name)) {
                v.remove(fy);
                this.jm.sxlist();
            }
        }
    }

    public void yhfqtz(String str)// 用户发起挑战的方法
    {
        String name1 = this.getName();// 发起挑战的人
        String name2 = str.substring(10);
        v = this.jm.getVector();
        for (Iterator it = v.iterator(); it.hasNext();) {
            FThread ff = (FThread) it.next();// 遍历得到所有用户
            if (ff.getName().equals(name2))// 得到被挑战人的线程
            {
                try {
                    ff.dou.writeUTF("#tiaozhan#" + name1);
                } catch (Exception e) {
                }
            }
        }

    }

    public void yhjstz(String str)// 用户接受挑战的方法
    {
        String name = str.substring(9);// 接收到挑战者的名字
        v = this.jm.getVector();
        for (Iterator it = v.iterator(); it.hasNext();) {
            FThread ff = (FThread) it.next();
            if (ff.getName().equals(name))// 遍历取得被挑战者的线程
            {
                try {
                    ff.dou.writeUTF("#jieshou#" + this.getName());// 将接受挑战的人名字发送给挑战者
                } catch (Exception e) {
                }
            }
        }

    }

    public void yhjjtz(String str)// 用户拒绝挑战的方法
    {
        String name = str.substring(6);// 获取挑战者的名字
        v = this.jm.getVector();
        for (Iterator it = v.iterator(); it.hasNext();) {
            FThread ff = (FThread) it.next();
            if (ff.getName().equals(name))// 遍历得到挑战者的线程
            {
                try {
                    ff.dou.writeUTF("#jjtz#" + this.getName());// 将被挑战者的名字发送给挑战者
                } catch (Exception e) {
                }
            }
        }
    }

    public void yjjstz(String str)// 自己已经接受挑战了 发送给另一个接受挑战的玩家一个信息
    {
        String name = str.substring(8);
        v = this.jm.getVector();
        for (Iterator it = v.iterator(); it.hasNext();) {
            FThread ff = (FThread) it.next();
            if (ff.getName().equals(name)) {
                try {
                    ff.dou.writeUTF("#yjjstz#" + this.getName());
                } catch (Exception e) {
                }
            }
        }
    }

    public void yhfm(String str)// 用户繁忙不能接受挑战
    {
        String name = str.substring(6);// 获取发起挑战的人
        v = this.jm.getVector();
        for (Iterator it = v.iterator(); it.hasNext();) {
            FThread ff = (FThread) it.next();
            if (ff.getName().equals(name)) {
                try {
                    ff.dou.writeUTF("#yhfm#" + this.getName());// 将被挑战者繁忙的信息发送给挑战者
                } catch (Exception e) {
                }
            }
        }
    }

    public void renshu(String str)// 用户认输的方法
    {
        String name = str.substring(8);
        v = this.jm.getVector();
        for (Iterator it = v.iterator(); it.hasNext();) {
            FThread ff = (FThread) it.next();
            if (ff.getName().equals(name)) {
                try {
                    ff.dou.writeUTF("#renshu#" + this.getName());
                } catch (Exception e) {
                }
            }
        }

    }

    public void zouqi()// 用户奏起的信息
    {
    }

    public void clse()// 服务器关闭的后调用的方法
    {
        v = this.jm.getVector();

        try {
            for (Iterator it = v.iterator(); it.hasNext();)// 给每个线程发送服务器关闭的信息
            {
                FThread ft = (FThread) it.next();
                ft.dou.writeUTF("#close#");
                break;
            }
            this.din.close();
            this.dou.close();
            this.s.close();
        } catch (Exception e) {
        }
    }

    public void yidong(String str) {
        String na = str.substring(8, str.length() - 4);// 获取对方得名字
        v = this.jm.getVector();
        for (Iterator it = v.iterator(); it.hasNext();) {
            FThread ft = (FThread) it.next();
            if (ft.getName().equals(na)) {
                try {
                    ft.dou.writeUTF(str);
                    break;
                } catch (Exception e) {
                }
            }
        }

    }

}

4、客户端:主函数

package jiem;

import MX.lianjie;

import java.awt.Color;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;

public class mainJM extends JFrame implements ActionListener {
    public static final Color bgColor = new Color(245, 250, 160);// 棋盘的背景色
    public static final Color focusbg = new Color(242, 242, 242);// 棋子选中后的背景色
    public static final Color focuschar = new Color(96, 95, 91);// 棋子选中后的字符颜色
    public static final Color color1 = new Color(249, 183, 100);// 红方的颜色
    public static final Color color2 = Color.white;// 白方的颜色
    int kuan = 50;// 楚河汉界的宽度
    QZ[][] arr = new QZ[9][10];// 创建一个用于添加棋子的二维数组
    boolean caiPan = false;// 可否走棋的标志位
    int color = 0;// 0 代表红棋,1代表白棋
    JLabel bq1, bq2, bq3;
    JTextField wbk1, wbk2;
    JTextField wbk3 = new JTextField("Play1");
    JButton b1, b2, b3, b4, b5, b6;
    JComboBox xllb;// 下拉列表
    JPanel p1;
    JSplitPane fg;
    Vector vv = new Vector();
    lianjie lj;// 声明连接类的引用
    QP qp;// 声明棋盘的引用

    public mainJM() {
        this.cjzj();// 初始化组件
        this.cjjt();// 初始化监听
        this.cshzt();// 初始化组件的状态
        this.cjct();// 初始化窗体
        this.cshqz();// 初始化棋子

    }

    public void cjzj()// 创建组件的方法
    {
        qp = new QP(arr, kuan, this);
        p1 = new JPanel();
        
        p1.setLayout(null);
        Font ft = new Font("楷体", Font.PLAIN, 22);
        bq1 = new JLabel("主机名");
        bq1.setBounds(20, 20, 80, 80);
        bq1.setFont(ft);
        p1.add(bq1);
        bq2 = new JLabel("端口号");
        bq2.setBounds(21, 60, 80, 80);
        bq2.setFont(ft);
        p1.add(bq2);
        bq3 = new JLabel("昵  称");
        bq3.setBounds(22, 100, 80, 80);
        bq3.setFont(ft);
        p1.add(bq3);
        wbk1 = new JTextField("127.0.0.1");
        wbk1.setBounds(100, 48, 80, 25);
        p1.add(wbk1);
        wbk2 = new JTextField("9999");
        wbk2.setBounds(100, 88, 80, 25);
        p1.add(wbk2);
        // wbk3=new JTextField("Play1");
        wbk3.setBounds(100, 128, 80, 25);
        p1.add(wbk3);
        b1 = new JButton("链接");
        b1.setBounds(15, 170, 90, 20);
        p1.add(b1);
        b2 = new JButton("断开");
        b2.setBounds(115, 170, 90, 20);
        p1.add(b2);
        xllb = new JComboBox();
        xllb.setBounds(65, 200, 90, 20);
        p1.add(xllb);
        b3 = new JButton("挑战");
        b3.setBounds(15, 230, 90, 20);
        p1.add(b3);
        b4 = new JButton("认输");
        b4.setBounds(115, 230, 90, 20);
        p1.add(b4);
        b5 = new JButton("接受挑战");
        b5.setBounds(15, 260, 90, 20);
        p1.add(b5);
        b6 = new JButton("拒绝挑战");
        b6.setBounds(115, 260, 90, 20);
        p1.add(b6);
        fg = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, qp, p1);
        fg.setDividerLocation(520);
        fg.setDividerSize(4);
    }

    public Vector getVector() {
        return vv;

    }

    public void sxlb() {
        this.xllb.setModel(new DefaultComboBoxModel(vv));
    }

    public JTextField getWbk3() {
        return wbk3;
    }

    public void cjct()// 创建窗体
    {
        this.add(fg);
        this.setTitle("网络象棋客户端");
        this.setSize(750, 550);
        int aa = Toolkit.getDefaultToolkit().getScreenSize().width;
        int bb = Toolkit.getDefaultToolkit().getScreenSize().height;
        this.setLocation(aa / 2 - 500, bb / 2 - 350);
        this.setVisible(true);
        this.setResizable(true);//窗体大小可变
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.out.println("guanbi");
                System.exit(0);
            }
        });
    }

    public void cjjt()// 创建监听的方法
    {
        b1.addActionListener(this);
        b2.addActionListener(this);
        b3.addActionListener(this);
        b4.addActionListener(this);
        b5.addActionListener(this);
        b6.addActionListener(this);
        wbk1.addActionListener(this);
        wbk2.addActionListener(this);
        wbk3.addActionListener(this);
    }

    public void cshzt()// 初始化组件的方法
    {
        b2.setEnabled(false);
        b3.setEnabled(false);
        b4.setEnabled(false);
        b5.setEnabled(false);
        b6.setEnabled(false);
        xllb.setEnabled(false);
    }

    public void cshqz() {
        arr[0][0] = new QZ(color1, "車", 0, 0);
        arr[1][0] = new QZ(color1, "馬", 1, 0);
        arr[2][0] = new QZ(color1, "相", 2, 0);
        arr[3][0] = new QZ(color1, "仕", 3, 0);
        arr[4][0] = new QZ(color1, "帥", 4, 0);
        arr[5][0] = new QZ(color1, "仕", 5, 0);
        arr[6][0] = new QZ(color1, "相", 6, 0);
        arr[7][0] = new QZ(color1, "馬", 7, 0);
        arr[8][0] = new QZ(color1, "車", 8, 0);
        arr[1][2] = new QZ(color1, "砲", 1, 2);
        arr[7][2] = new QZ(color1, "砲", 7, 2);
        arr[0][3] = new QZ(color1, "兵", 0, 3);
        arr[2][3] = new QZ(color1, "兵", 2, 3);
        arr[4][3] = new QZ(color1, "兵", 4, 3);
        arr[6][3] = new QZ(color1, "兵", 6, 3);
        arr[8][3] = new QZ(color1, "兵", 8, 3);
        arr[0][9] = new QZ(color2, "車", 0, 9);
        arr[1][9] = new QZ(color2, "馬", 1, 9);
        arr[2][9] = new QZ(color2, "象", 2, 9);
        arr[3][9] = new QZ(color2, "士", 3, 9);
        arr[4][9] = new QZ(color2, "將", 4, 9);
        arr[5][9] = new QZ(color2, "士", 5, 9);
        arr[6][9] = new QZ(color2, "象", 6, 9);
        arr[7][9] = new QZ(color2, "馬", 7, 9);
        arr[8][9] = new QZ(color2, "車", 8, 9);
        arr[1][7] = new QZ(color2, "炮", 1, 7);
        arr[7][7] = new QZ(color2, "炮", 7, 7);
        arr[0][6] = new QZ(color2, "卒", 0, 6);
        arr[2][6] = new QZ(color2, "卒", 2, 6);
        arr[4][6] = new QZ(color2, "卒", 4, 6);
        arr[6][6] = new QZ(color2, "卒", 6, 6);
        arr[8][6] = new QZ(color2, "卒", 8, 6);
    }

    public void actionPerformed(ActionEvent e) {
        
        if (e.getSource() == this.b1) {
            if (this.yzdkh())// 调用验证端口号的方法
            {
                this.qidong();// 调用启动按钮的操作
            }

        } else if (e.getSource() == this.b2) {
            this.setGuanbi();
        } else if (e.getSource() == this.b3) {
            this.tiaozhan();
        } else if (e.getSource() == this.b4) {
            this.renshu();
        } else if (e.getSource() == this.b5) {
            this.jieshou();
        } else if (e.getSource() == this.b6) {
            this.jujue();
        }
    }

    public void qidong()// 点击启动按钮的方法
    {
        lj = new lianjie(this, qp);// 创建连接类对象 查看是否链接成功
        if (lj.cjsocket()) {
            wbk1.setEditable(false);
            wbk2.setEditable(false);
            wbk3.setEditable(false);
            b2.setEnabled(true);// 关闭设为可用
            b1.setEnabled(false);// 开启设为不可用
            b3.setEnabled(true);// 挑战设为可用
            b4.setEnabled(false);
            b5.setEnabled(false);
            b6.setEnabled(false);
            xllb.setEnabled(true);// 下拉列表设为可用
            lj.start();// 启动客户端线程
            
        } else {
            
            JOptionPane.showMessageDialog(this, "链接失败");
        }
    }
    
    
    
    public void setGuanbi()// 点击关闭按钮的方法
    {
        wbk1.setEditable(true);// 主机设为可用
        wbk2.setEditable(true);// 端口设为可用
        wbk3.setEditable(true);// 设为可用户
        b2.setEnabled(false);// 关闭设为不可用
        b1.setEnabled(true);// 开启设为可用
        b3.setEnabled(false);// 挑战设为不可用
        b4.setEnabled(false);// 认输设为不可用
        b6.setEnabled(false);// jieshou挑战设为不可用
        b5.setEnabled(false);// 拒绝挑战设为不可用
        xllb.setEnabled(false);// 下拉列表设为不可用
        lj.zdlk();// 调用客户端线程的主动离开方法
        // JOptionPane.showMessageDialog(this,"关闭链接");
    }

    public void tiaozhan()// 挑战
    {

        String str = (String) xllb.getSelectedItem();// 获取玩家姓名

        if (str == null || str == "") {// 判断是否取到了玩家姓名
            JOptionPane.showMessageDialog(this, "请选中一名玩家!");
        } else {
            lj.fqtz(str);// 调用发起挑战的方法并将选中的玩家做参数传进去
            this.caiPan = true;
            this.color = 0;// 将自己设为红旗
            JOptionPane.showMessageDialog(this, "已发出挑战! 请稍等!!");
        }

    }

    public void renshu()// 主动认输
    {
        wbk1.setEditable(false);
        wbk2.setEditable(false);
        wbk3.setEditable(false);
        b2.setEnabled(true);// 关闭设为可用
        b1.setEnabled(false);// 开启设为不可用
        b3.setEnabled(true);// 挑战设为可用
        b4.setEnabled(false);
        b5.setEnabled(false);
        b6.setEnabled(false);
        xllb.setEnabled(true);// 下拉列表设为可用
        lj.yhrs();// 调用连接里的主动认输的方法
        // JOptionPane.showMessageDialog(this,"认输");
    }

    public void renshu1()// 对方认输调用的方法
    {
        wbk1.setEditable(false);
        wbk2.setEditable(false);
        wbk3.setEditable(false);
        b2.setEnabled(true);// 关闭设为可用
        b1.setEnabled(false);// 开启设为不可用
        b3.setEnabled(true);// 挑战设为可用
        b4.setEnabled(false);
        b5.setEnabled(false);
        b6.setEnabled(false);
        xllb.setEnabled(true);// 下拉列表设为可用
    }

    public void setCaiPan() {
        caiPan = true;
    }

    public void jieshou()// 接受挑战
    {
        this.caiPan = true;
        this.color = 1;// 将自己设为白棋
        wbk1.setEditable(false);// 主机设为可用
        wbk2.setEditable(false);// 端口设为可用
        wbk3.setEditable(false);// 设为可用户
        b2.setEnabled(false);// 关闭设为不可用
        b1.setEnabled(false);// 开启设为可用
        b3.setEnabled(false);// 挑战设为不可用
        b4.setEnabled(true);// 认输设为不可用
        b6.setEnabled(false);// 发起挑战设为不可用
        b5.setEnabled(false);// 拒绝挑战设为不可用
        xllb.setEnabled(false);// 下拉列表设为不可用
        lj.jieshou1();// 调用链接类中被挑战者接受挑战的方法
        JOptionPane.showMessageDialog(this, "请走白棋!!");

    }

    public void jieshou1()// 挑战者接收到被挑战者同意的放啊
    {
        wbk1.setEditable(false);// 主机设为可用
        wbk2.setEditable(false);// 端口设为可用
        wbk3.setEditable(false);// 设为可用户
        b2.setEnabled(false);// 关闭设为不可用
        b1.setEnabled(false);// 开启设为可用
        b3.setEnabled(false);// 挑战设为不可用
        b4.setEnabled(true);// 认输设为不可用
        b6.setEnabled(false);// 发起挑战设为不可用
        b5.setEnabled(false);// 拒绝挑战设为不可用
        xllb.setEnabled(false);// 下拉列表设为不可用
        JOptionPane.showMessageDialog(this, "请走红旗!!");
    }

    public void yjjstz()// 对方已经接受了挑战自己不能同对方挑战
    {
        wbk1.setEditable(false);
        wbk2.setEditable(false);
        wbk3.setEditable(false);
        b2.setEnabled(true);// 关闭设为可用
        b1.setEnabled(false);// 开启设为不可用
        b3.setEnabled(true);// 挑战设为可用
        b4.setEnabled(false);
        b5.setEnabled(false);
        b6.setEnabled(false);
        xllb.setEnabled(true);// 下拉列表设为可用
        // lj.start();//启动客户端线程
    }

    public void jujue()// 拒绝挑战
    {
        wbk1.setEditable(false);
        wbk2.setEditable(false);
        wbk3.setEditable(false);
        b2.setEnabled(true);// 关闭设为可用
        b1.setEnabled(false);// 开启设为不可用
        b3.setEnabled(true);// 挑战设为可用
        b4.setEnabled(false);
        b5.setEnabled(false);
        b6.setEnabled(false);
        xllb.setEnabled(true);// 下拉列表设为可用
        lj.jujue1();// 调用连接类中的被挑战方拒绝挑战的方法
    }

    public void tz()// 对方发来挑战后讲接受和拒绝按钮设为可用
    {
        wbk1.setEditable(false);// 主机设为可用
        wbk2.setEditable(false);// 端口设为可用
        wbk3.setEditable(false);// 设为可用户
        b2.setEnabled(false);// 关闭设为不可用
        b1.setEnabled(false);// 开启设为可用
        b3.setEnabled(false);// 挑战设为不可用
        b4.setEnabled(false);// 认输设为不可用
        b6.setEnabled(true);// 发起挑战设为可用
        b5.setEnabled(true);// 拒绝挑战设为可用
        xllb.setEnabled(false);// 下拉列表设为不可用
    }

    public boolean yzdkh()// 验证端口号是否正确 如果正确返回true 不正确返回false
    {
        int port = 0;
        try {
            String str = this.wbk2.getText().trim();
            port = Integer.parseInt(str);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, "请输入整数(0-65535)");
            return false;
        }
        if (port < 0 || port > 65535) {
            JOptionPane.showMessageDialog(this, "请输入整数(0-65535)");
            return false;
        }
        return true;
    }

    public void next()// 重置棋子
    {
        wbk1.setEditable(false);
        wbk2.setEditable(false);
        wbk3.setEditable(false);
        b2.setEnabled(true);// 关闭设为可用
        b1.setEnabled(false);// 开启设为不可用
        b3.setEnabled(true);// 挑战设为可用
        b4.setEnabled(false);
        b5.setEnabled(false);
        b6.setEnabled(false);
        xllb.setEnabled(true);// 下拉列表设为可用
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 10; j++) {
                arr[i][j] = null;
            }
        }

        this.cshqz();
        // this.repaint();
    }

    public static void main(String[] args) {
        mainJM one = new mainJM();
    }

}

5、客户端:子线程

package MX;

import jiem.*;

import java.io.*;
import java.net.Socket;
import javax.swing.*;

import java.util.*;

public class lianjie extends Thread {
    Socket s;
    JTextField wbk;
    boolean flag = true;// 线程的标志位
    boolean flag1 = true;// 创建Socket 的标志位
    DataInputStream dis;
    DataOutputStream dos;
    mainJM mj;// 声明主界面类对象引用
    QP qp;// 声明棋盘类的引用
    Vector v;
    String tzz = "";// 用于记录发起挑战的名字
    String btzz = "";// 用于记录被挑战者的名字

    public lianjie(mainJM jm, QP qp) {
        this.qp = qp;
        this.mj = jm;

    }

    public DataOutputStream fhyd() {
        return dos;
    }

    public boolean cjsocket() {
        try {
            s = new Socket("127.0.0.1", 9999);
        } catch (Exception e) {
            System.out.println("建立socket异常:" + e.toString());
            return false;
        }
        return flag1;
    }

    public void schl() {

        try {
            dis = new DataInputStream(s.getInputStream());// 创建输入流
            dos = new DataOutputStream(s.getOutputStream());// 创建输出流
            wbk = mj.getWbk3();
            String name = wbk.getText().trim();
            dos.writeUTF("#nc#" + name);// 将昵称发送到服务器
        } catch (Exception e) {
            System.out.println("建立数据流异常" + e.toString());
        }

    }

    public void run()// run方法
    {
        this.schl();// 调用创建数据输入输出流的方法
        while (flag) {
            System.out.println("循环");
            try {
                String str = dis.readUTF().trim();
                if (str.startsWith("#chongming#"))// 收到服务器发来的重名信息
                {
                    this.chongm();// 调用重名的方法
                } else if (str.startsWith("#close#"))// 收到服务器关闭的信息
                {
                    this.clse();// 调用服务器关闭是客户端的操作
                } else if (str.startsWith("#liebiao#"))// 收到服务器发来的列表
                {
                    this.lj(str);// 调用发来列表的方法
                } else if (str.startsWith("#likai#"))// 收到用户离开的信息
                {
                    this.likai(str);// 调用 用户离开的方法
                } else if (str.startsWith("#tiaozhan#"))// 收到挑战的信息
                {
                    if (btzz == "")// 收到挑战信息时判断挑战者是否无记录
                    {
                        this.tiaozhan(str);
                    } else // 如果收到挑战信息btzz有记录
                    {
                        this.btzzyjl(str);

                    }

                } else if (str.startsWith("#jjtz#"))// 收到拒绝挑战的信息
                {
                    this.jujue(str);

                } else if (str.startsWith("#jieshou#"))// 收到对方接受挑战的信息
                {

                    if (btzz == "")// 如果被挑战者没有记录
                    {
                        this.jieshou(str);// 调用被挑战者接受的方法
                    } else {

                        this.yjjs(str);// 调用挑战者已接受挑战的方法
                    }
                } else if (str.startsWith("#yjjstz#"))// 接受到挑战者发送来的已接受过其他人挑战的消息
                {
                    this.yjjstz(str);// 当知道挑战者已经接受其他人挑战的消息是做的操作
                } else if (str.startsWith("#yhfm#"))// 用户忙
                {
                    this.mang(str);
                } else if (str.startsWith("#zq#"))// 走棋
                {
                    this.kaiqi();
                } else if (str.startsWith("#renshu#"))// 认输
                {
                    this.rens(str);
                } else if (str.startsWith("#tishi#"))// 用户上线
                {
                    this.tishi(str);
                } else if (str.startsWith("#yidong#"))// 收到用户走棋的信息
                {
                    this.Move(str);
                } else if (str.startsWith("#nochongming#"))// 收到用户走棋的信息
                {
                    JOptionPane.showMessageDialog(this.mj, "链接成功");
                }
            } catch (Exception e) {
                System.out.println("客户端读取流 读取异常" + e.toString());
            }
        }
    }

    public void chongm() {
        JOptionPane.showMessageDialog(this.mj, "该昵称已被玩家占用");
        System.out.println("站用户");
        try {
            this.mj.setGuanbi();// 调用主界面的关闭方法
            this.flag = false;// 将本线程的标志位设为false 结束run 方法
            this.dis.close();// 关闭输入输出流
            this.dos.close();//
            this.s.close();// 关闭Socket
        } catch (Exception e) {
            System.out.println("关闭流异常" + e.toString());
        }

    }

    public void lj(String str)// 刷新列表的方法
    {
        String aa = str.substring(9);
        String bb = this.mj.getWbk3().getText().trim();
        v = this.mj.getVector();
        if (!aa.equals(bb) && !v.contains(aa))// 当接收的名字不是本玩家名
        // 并且不在本类列表中时 添加进来
        {
            v.add(aa);
            this.mj.sxlb();// 刷新列表
        }

    }

    public void clse()// 收到服务器关闭时的具体操作方法
    {
        try {
            this.mj.setGuanbi();// 调用主界面关闭的方法
            this.flag = false;// 将本线程的标志位设为false 结束run 方法
            this.dis.close();// 关闭输入输出流
            this.dos.close();//
            this.s.close();// 关闭Socket
        } catch (Exception e) {
        }
        JOptionPane.showMessageDialog(this.mj, "服务器已经关闭!!!");
    }

    public void likai(String str)// 当收到用户离开时的方法
    {
        String aa = str.substring(7);
        v = this.mj.getVector();
        v.remove(aa);
        this.mj.sxlb();
        JOptionPane.showMessageDialog(this.mj, aa + "用户已离开!");
    }

    public void yjjs(String str)// 另一个用户发来接受挑战的信息
    {
        String name = str.substring(9);// 获取另一个接受挑战的玩家名字
        try {
            this.dos.writeUTF("#yjjstz#" + name);
        } catch (Exception e) {
        }
    }

    public void yjjstz(String str)// 挑战者已经接受挑战
    {
        String name = str.substring(8);
        tzz = "";// 将挑战者的名字清空
        this.mj.yjjstz();// 调用主界面中挑战者已经在同别人挑战自己不能同发起者挑战
        JOptionPane.showMessageDialog(this.mj, name + "正在和其他玩家进行挑战!!");
    }

    public void tiaozhan(String str)// 对方发来挑战的信息后的操作
    {
        tzz = str.substring(10);// 记录发起挑战的人
        this.mj.tz();// 调用主界面对方发来挑战的方法
        JOptionPane.showMessageDialog(this.mj, tzz + "向你发起挑战!!");
    }

    public void jujue(String str) {
        btzz = str.substring(6);
        JOptionPane.showMessageDialog(this.mj, btzz + "拒绝了您的挑战 !!");
        btzz = "";// 将被挑战者清空

    }

    public void jieshou(String str) {
        btzz = str.substring(9);
        this.mj.jieshou1();// 调用主界面点击接受按钮接的方法
        JOptionPane.showMessageDialog(this.mj, btzz + "接受您的挑战 !!");
    }

    public void btzzyjl(String str)// 当被挑战者有记录时
    {
        String name = str.substring(10);// 记录发起挑战的人
        try {
            this.dos.writeUTF("#yhfm#" + name);// 告诉发起挑战的人正在挑战中
        } catch (Exception e) {
        }
    }

    public void mang(String str) {
        String name = str.substring(6);// 获取到被挑战者的名字
        JOptionPane.showMessageDialog(this.mj, name + "正在接受挑战!!");

    }

    public void kaiqi() {
    }

    public void rens(String str) {
        String name = str.substring(8);
        JOptionPane.showMessageDialog(this.mj, name + "认输了!您赢得了这局!");
        tzz = "";
        btzz = "";
        System.out.println("对方认输了");
        this.mj.renshu1();// 调用主界面对方认输的方法
    }

    public void tishi(String str)// 提示新用户上线的方法
    {
        String sss = str.substring(7);
        JOptionPane.showMessageDialog(this.mj, sss + "上线了");
    }

    public void zdlk()// 当客户端主动离开是的方法
    {
        String aa = this.mj.getWbk3().getText().trim();
        try {
            this.dos.writeUTF("#likai#" + aa);
            this.dis.close();
            this.dos.close();
            this.s.close();
            this.flag = false;
        } catch (Exception e) {
        }
    }

    public void fqtz(String str)// 发起挑战的方法
    {
        try {
            tzz = this.getName();// 将自身线程的名字赋值给tzz
            this.dos.writeUTF("#tiaozhan#" + str);// 将发起挑战的人和被挑战的人发送到服务器
        } catch (Exception e) {
        }

    }

    public void jieshou1()// 被挑战方接受挑战的方法
    {
        try {
            this.btzz = this.getName();
            this.dos.writeUTF("#jieshou#" + tzz);
        } catch (Exception e) {
        }
    }

    public void jujue1()// 被挑战方拒绝挑战的方法
    {
        try {
            this.dos.writeUTF("#jjtz#" + tzz);// 将挑战者的名字发送到服务器
            tzz = "";// 将挑战者的名字清空
        } catch (Exception e) {
        }
    }

    public void yhrs()// 主动认输的方法
    {
        if (this.getName().equals(btzz))// 如果自身是被挑战者
        {
            try {
                this.dos.writeUTF("#renshu#" + tzz);// 将认输的信息发送到对方

            } catch (Exception e) {
            }
        }
        if (this.getName().equals(tzz))// 如果自身是挑战者
        {
            try {
                this.dos.writeUTF("#renshu#" + btzz);// 将认输的信息发送到对方
            } catch (Exception e) {
            }
        }
        tzz = "";
        btzz = "";
    }

    public String fhmz1() {
        if (this.getName().equals(btzz))// 如果自身是被挑战者
        {
            return tzz;
        } else if (this.getName().equals(tzz))// 如果自身是挑战者
        {
            return btzz;
        }
        return "aaaaa";
    }

    public void setfhmz1() {
        // if(this.getName().equals(btzz))//如果自身是被挑战者
        // {
        // btzz="";
        // }
        // else if(this.getName().equals(tzz))//如果自身是挑战者
        // {
        // tzz="";
        // }
        tzz = "";
        btzz = "";
    }

    public void Move(String str)// 走棋的方法
    {
        System.out.println("进入客户端走棋的方法");
        int len = str.length();
        int Sx = Integer.parseInt(str.substring(len - 4, len - 3));
        int Sy = Integer.parseInt(str.substring(len - 3, len - 2));
        int Ex = Integer.parseInt(str.substring(len - 2, len - 1));
        int Ey = Integer.parseInt(str.substring(len - 1));
        System.out.println("333开始坐标:" + Sx + ":" + Sy + "移动后的坐标" + Ex + ":"
                + Ey);
        this.qp.move1(Sx, Sy, Ex, Ey);
        // this.qp.aaa();
        this.mj.setCaiPan();
        System.out.println("客户端走棋的方法完毕");
    }
}

6、象棋棋谱

package jiem;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.io.*;

public class QP extends JPanel implements MouseListener {
    DataOutputStream dos;
    private int kuan;// 楚河汉界的宽度
    boolean zt = false;// 棋盘的初始状态
    int sx = 4;
    int sy = 0;
    int jx = 4;
    int jy = 9;
    int Sx = -1;
    int Sy = -1;
    int Ex = -1;
    int Ey = -1;
    QZ[][] arr;// 棋子的数组
    mainJM jm;
    Guize ge;

    public QP(QZ[][] arr, int kuan, mainJM jm) {
        this.jm = jm;
        this.arr = arr;
        this.kuan = kuan;
        ge = new Guize(arr);
        this.addMouseListener(this);
        this.setBounds(0, 0, 550, 550); 
        this.setLayout(null);
    }

    public void paint(Graphics gg) {
        Graphics2D g = (Graphics2D) gg;// 获得2D画笔
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON); //消除线段的锯齿边缘
        Color color = g.getColor();// 获得画笔的的颜色
        g.setColor(jm.bgColor);// 将画笔的颜色换成棋盘背景颜色
        g.fill3DRect(10, 10, 500, 500, false);// 绘制一个矩形棋盘
        // g.fill3DRect(0,0,800,700,false);
        g.setColor(Color.BLACK);// 将画笔的颜色设置为黑色
        for (int i = 35; i <= 485; i = i + 50) {// 绘制棋盘中的横线
            g.drawLine(60, i, 460, i);
        }
        g.drawLine(60, 35, 60, 485);// 绘制左边线
        g.drawLine(460, 35, 460, 485);// 绘制右边线
        for (int i = 110; i <= 410; i = i + 50) {// 绘制中间的竖线
            g.drawLine(i, 35, i, 235);
            g.drawLine(i, 285, i, 485);
        }
        g.drawLine(210, 35, 310, 135);// 绘制两边的斜线
        g.drawLine(310, 35, 210, 135);
        g.drawLine(210, 385, 310, 485);
        g.drawLine(310, 385, 210, 485);
        this.smallLine(g, 1, 2);// 绘制红炮所在位置的标志
        this.smallLine(g, 7, 2);// 绘制红炮所在位置的标志
        this.smallLine(g, 0, 3);// 绘制兵所在位置的标志
        this.smallLine(g, 2, 3);// 绘制兵所在位置的标志
        this.smallLine(g, 4, 3);// 绘制兵所在位置的标志
        this.smallLine(g, 6, 3);// 绘制兵所在位置的标志
        this.smallLine(g, 8, 3);// 绘制兵所在位置的标志
        this.smallLine(g, 0, 6);// 绘制卒所在位置的标志
        this.smallLine(g, 2, 6);// 绘制卒所在位置的标志
        this.smallLine(g, 4, 6);// 绘制卒所在位置的标志
        this.smallLine(g, 6, 6);// 绘制卒所在位置的标志
        this.smallLine(g, 8, 6);// 绘制卒所在位置的标志
        this.smallLine(g, 1, 7);// 绘制白炮所在位置的标志
        this.smallLine(g, 7, 7);// 绘制白炮所在位置的标志
        g.setColor(Color.black);
        Font font1 = new Font("宋体", Font.BOLD, 30);// 设置字体
        g.setFont(font1);
        g.drawString("楚 河", 90, 270);// 绘制楚河汉界
        g.drawString("漢 界", 340, 270);
        Font font = new Font("宋体", Font.BOLD, 20);
        g.setFont(font);// 设置字体
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 10; j++) {// 绘制棋子
                if (arr[i][j] != null) {
                    if (this.arr[i][j].getFlag() != false) {// 被选中
                        g.setColor(jm.focusbg);// 选中后的背景色
                        g.fillOval(45 + i * 50, 20 + j * 50, 30, 30);// 绘制该棋子
                        g.setColor(jm.focuschar);// 字符的颜色
                    } else {
                        g.fillOval(45 + i * 50, 20 + j * 50, 30, 30);// 绘制该棋子
                        g.setColor(arr[i][j].getColor());// 设置画笔颜色
                    }
                    g.drawString(arr[i][j].getName(), 50 + i * 50,
                            42 + j * 50);
                    g.setColor(Color.black);// 设为黑色
                }
            }
        }
        // g.setColor(c);//还原画笔颜色

    }

    public void smallLine(Graphics2D g, int i, int j) {
        int x = 60 + 50 * i;// 计算坐标
        int y = 35 + 50 * j;
        if (i > 0) {// 绘制左上方的标志
            g.drawLine(x - 3, y - 3, x - 20, y - 3);
            g.drawLine(x - 3, y - 3, x - 3, y - 20);
        }
        if (i < 8) {// 绘制右上方的标志
            g.drawLine(x + 3, y - 3, x + 20, y - 3);
            g.drawLine(x + 3, y - 3, x + 3, y - 20);
        }
        if (i > 0) {// 绘制左下方的标志
            g.drawLine(x - 3, y + 3, x - 20, y + 3);
            g.drawLine(x - 3, y + 3, x - 3, y + 20);
        }
        if (i < 8) {// 绘制右下方的标志
            g.drawLine(x + 3, y + 3, x + 20, y + 3);
            g.drawLine(x + 3, y + 3, x + 3, y + 20);
        }
    }

    public void mouseClicked(MouseEvent e)// 按下并释放时调用
    {
        if (this.jm.caiPan == true) {// 判断是否轮到该玩家走棋
            int i = -1, j = -1;
            int[] pos = getPos(e);
            i = pos[0];
            j = pos[1];
            if (i >= 0 && i <= 8 && j >= 0 && j <= 9) {// 如果在棋盘范围内
                if (zt == false) {// 如果棋盘中没有选中棋子
                    this.noFocus(i, j);
                    System.out.println("进入没有选中棋子");
                } else {// 如果以前选中过棋子
                // 以下是判断再次点击的地方是否有棋子
                    if (arr[i][j] != null) {// 如果该处有棋子
                        if (arr[i][j].getColor() == arr[Sx][Sy].getColor()) {// 如果是自己的棋子
                            System.out.println("是自己的棋子");
                            arr[Sx][Sy].setFlag(false);
                            arr[i][j].setFlag(true);// 更改选中对象
                            Sx = i;
                            Sy = j;// 保存修改
                        } else {// 如果是对方棋子
                            Ex = i;// 保存该点
                            Ey = j;
                            System.out.println("不是自己的棋子");
                            String name = arr[Sx][Sy].getName();// 获得该棋子的名字
                            // 看是否可以移动
                            boolean canMove = ge.canMove(Sx, Ex, Sy, Ey, name);
                            System.out.println("不是自己的棋子判断是否可以移动:" + canMove
                                    + "己方的棋子是" + name);
                            // canMove=true;
                            System.out.println("canmove:" + canMove);
                            if (canMove)// 如果可以移动
                            {
                                try {// 将该移动信息发送给对方
                                    dos = this.jm.lj.fhyd();// 获取用户输出流
                                    String name1 = this.jm.lj.fhmz1();// 获取对方得名字
                                    dos.writeUTF("#yidong#" + name1 + Sx + Sy
                                            + Ex + Ey);
                                    System.out.println("#yidong#" + name1 + Sx
                                            + Sy + Ex + Ey);
                                    this.jm.caiPan = false;
                                    if (arr[Ex][Ey].getName().equals("帥")
                                            || arr[Ex][Ey].getName()
                                                    .equals("將")) {// 如果终点处是对方的"将"
                                        this.success();
                                    } else {// 如果终点不是对方的"将"
                                        this.noJiang();
                                    }
                                } catch (Exception ee) {
                                    ee.printStackTrace();
                                }
                            }
                        }
                    } else {// 如果没有棋子
                        System.out.println("进入走棋");
                        Ex = i;
                        Ey = j;// 保存终点
                        System.out.print("111开始坐标:" + Sx + ":" + Sy + "移动后的X坐标"
                                + Ex + ":" + Ey);
                        String name = arr[Sx][Sy].getName();// 获得该棋的名字
                        boolean canMove = ge.canMove(Sx, Ex, Sy, Ey, name);// 判断是否可走
                        System.out.println(canMove);
                        if (canMove) {// 如果可以移动
                            this.noQiZi();
                        }
                    }
                }
            }
            this.jm.repaint();// 重绘
        }
    }

    public void mouseEntered(MouseEvent e)// 进入到组件上调用
    {
    }

    public void mouseExited(MouseEvent e)// 离开是调用
    {
    }

    public void mousePressed(MouseEvent e) // 按下时调用
    {
    }

    public void mouseReleased(MouseEvent e) // 松开是调用
    {
    }

    public int[] getPos(MouseEvent e) {
        System.out.println("进入获取X,Y坐标方法");
        int[] pos = new int[2];
        pos[0] = -1;
        pos[1] = -1;
        Point p = e.getPoint();// 获得事件发生的坐标点
        double x = p.getX();
        double y = p.getY();
        if (Math.abs((x - 60) / 1 % 50) <= 15) {// 获得对应于数组x下标的位置
            pos[0] = Math.round((float) (x - 60)) / 50;
        } else if (Math.abs((x - 60) / 1 % 50) >= 35) {
            pos[0] = Math.round((float) (x - 60)) / 50 + 1;
        }
        if (Math.abs((y - 35) / 1 % 50) <= 15) {// 获得对应于数组y下标的位置
            pos[1] = Math.round((float) (y - 35)) / 50;
        } else if (Math.abs((y - 35) / 1 % 50) >= 35) {
            pos[1] = Math.round((float) (y - 35)) / 50 + 1;
        }
        System.out.println("点击坐标:("+pos[0]+","+pos[1]+")");
        return pos;
    }

    public void noFocus(int i, int j) {
        if (this.arr[i][j] != null)// 如果该位置有棋子
        {
            if (this.jm.color == 0)// 如果是红方
            {
                if (this.arr[i][j].getColor().equals(jm.color1))// 如果棋子是红色
                {
                    this.arr[i][j].setFlag(true);// 将该棋子设为选中状态
                    zt = true;// 将focus设为true
                    Sx = i;// 保存该坐标点
                    Sy = j;
                }
            } else// 如果是白方
            {
                if (this.arr[i][j].getColor().equals(jm.color2))// 如果该棋子是白色
                {
                    this.arr[i][j].setFlag(true);// 将该棋子设为选中状态
                    zt = true;// 将focus设为true
                    Sx = i;// 保存该坐标点
                    Sy = j;
                }
            }
        }
    }

    public void success() {
        System.out.println("进入成功吃掉对方得将或帅");
        arr[Ex][Ey] = arr[Sx][Sy];// 吃掉该棋子
        arr[Sx][Sy] = null;// 将原来的位置设为空
        this.jm.repaint();// 重绘
        JOptionPane.showMessageDialog(this.jm, "恭喜您,您获胜了", "提示",
                JOptionPane.INFORMATION_MESSAGE);// 给出获胜信息
        this.jm.lj.setfhmz1();
        this.jm.color = 0;
        this.jm.caiPan = false;
        this.jm.next();// 还原棋盘,进入下一盘
        Sx = -1;// 还原保存点
        Sy = -1;
        Ex = -1;
        Ey = -1;
        sx = 4;// "帥"的i坐标
        sy = 0;// "帥"的j坐标
        jx = 4;// "將"的i坐标
        jy = 9;// "將"的j坐标
        zt = false;
        this.jm.repaint();
    }

    public void noJiang() {
        arr[Ex][Ey] = arr[Sx][Sy];
        arr[Sx][Sy] = null;// 走棋
        arr[Ex][Ey].setFlag(false);// 将该棋设为非选中状态
        this.jm.repaint();// 重绘
        if (arr[Ex][Ey].getName().equals("帥")) {// 如果移动的是"帥"
            sx = Ex;// 更新"帥"的位置坐标
            sy = Ey;
        } else if (arr[Ex][Ey].getName().equals("將")) {// 如果移动的是"將"
            jx = Ex;// 更新"將"的位置坐标
            jy = Ey;
        }
        if (jx == sx) {// 如果"將"和"帥"在一条竖线上
            int count = 0;
            for (int i = sy + 1; i < jy; i++) {// 遍历这条竖线
                if (arr[jx][i] != null) {
                    count++;
                    break;
                }
            }
            if (count == 0) {// 如果等于零则照将
                JOptionPane.showMessageDialog(this.jm, "照将!!!你失败了!!!", "提示",
                        JOptionPane.INFORMATION_MESSAGE);// 给出失败信息
                this.jm.lj.setfhmz1();
                this.jm.color = 0;// 还原棋盘,进入下一盘
                this.jm.caiPan = false;
                this.jm.next();// 进入下一盘
                sx = 4;// "帥"的i坐标
                sy = 0;// "帥"的j坐标
                jx = 4;// "將"的i坐标
                jy = 9;// "將"的j坐标
            }
        }
        Sx = -1;
        Sy = -1;// 还原保存点
        Ex = -1;
        Ey = -1;
        zt = false;
    }

    public void noQiZi() {
        System.out.println("进入终点没有棋子的方法");
        try {// 将该移动信息发送给对方
            dos = this.jm.lj.fhyd();
            String nnn = this.jm.lj.fhmz1();
            dos.writeUTF("#yidong#" + nnn + Sx + Sy + Ex + Ey);
            System.out.print("222开始坐标:" + Sx + ":" + Sy + "移动后的X坐标" + Ex + ":"
                    + Ey);
            this.jm.caiPan = false;
            arr[Ex][Ey] = arr[Sx][Sy];
            arr[Sx][Sy] = null;// 走棋
            arr[Ex][Ey].setFlag(false);// 将该棋设为非选中状态.
            System.out.println("重绘棋子");
            this.jm.repaint();// 重绘
            if (arr[Ex][Ey].getName().equals("帥")) {// 如果移动的是"帥"
                sx = Ex;// 更新"帥"的位置坐标
                sy = Ey;
            } else if (arr[Ex][Ey].getName().equals("將")) {// 如果移动的是"將"
                jx = Ex;// 更新"將"的位置坐标
                jy = Ey;
            }
            if (jx == sx)// 如果"將"和"帥"在一条竖线上
            {
                int count = 0;
                for (int i = sy + 1; i < jy; i++) {// 遍历这条竖线
                    if (arr[jx][i] != null) {
                        count++;
                        break;
                    }
                }
                if (count == 0) {// 如果等于零则照将
                    JOptionPane.showMessageDialog(this.jm, "照将!!!你失败了!!!",
                            "提示", JOptionPane.INFORMATION_MESSAGE);// 给出失败信息
                    this.jm.lj.setfhmz1();
                    this.jm.color = 0;// 还原棋盘,进入下一盘
                    this.jm.caiPan = false;
                    this.jm.next();// 进入下一盘
                    sx = 4;// "帥"的i坐标
                    sy = 0;// "帥"的j坐标
                    jx = 4;// "將"的i坐标
                    jy = 9;// "將"的j坐标
                }
            }
            Sx = -1;
            Sy = -1;// 还原保存点
            Ex = -1;
            Ey = -1;
            zt = false;
        } catch (Exception ee) {
            System.out.println("走棋为成功" + ee.toString());
        }
        this.jm.repaint();
    }

    public void move1(int Sx, int Sy, int Ex, int Ey) {
        System.out.println("进入棋盘移动的方法");
        if (arr[Ex][Ey] != null
                && (arr[Ex][Ey].getName().equals("帥") || arr[Ex][Ey].getName()
                        .equals("將"))) {// 如果"将"被吃了
            arr[Ex][Ey] = arr[Sx][Sy];
            arr[Sx][Sy] = null;// 走棋
            this.jm.repaint();// 重绘
            JOptionPane.showMessageDialog(this.jm, "很遗憾,您失败了!!!", "提示",
                    JOptionPane.INFORMATION_MESSAGE);// 给出失败信息
            System.out.println("进入重新开始的地点");
            this.jm.lj.setfhmz1();
            this.jm.color = 0;// 还原棋盘,进入下一盘
            this.jm.caiPan = false;
            this.jm.next();// 进入下一盘
            sx = 4;// "帥"的i坐标
            sy = 0;// "帥"的j坐标
            jx = 4;// "將"的i坐标
            jy = 9;// "將"的j坐标
        } else {// 如果不是"将"
            arr[Ex][Ey] = arr[Sx][Sy];
            arr[Sx][Sy] = null;// 走棋
            this.jm.repaint();// 重绘
            if (arr[Ex][Ey].getName().equals("帥")) {
                sx = Ex;// 如果是"帥"
                sy = Ey;
            } else if (arr[Ex][Ey].getName().equals("將")) {
                jx = Ex;// 如果是"將"
                jy = Ey;
            }
            if (sx == jx) {// 如果两将在一条线上
                int count = 0;
                for (int i = sy + 1; i < jy; i++) {
                    if (arr[sx][i] != null) {// 有棋子
                        count++;
                        break;
                    }
                }
                if (count == 0) {

                    JOptionPane.showMessageDialog(this.jm, "对方照将!!!你胜利了!!!",
                            "提示", JOptionPane.INFORMATION_MESSAGE);// 给出失败信息
                    this.jm.lj.setfhmz1();
                    this.jm.color = 0;// 还原棋盘,进入下一盘
                    this.jm.caiPan = false;
                    this.jm.next();// 进入下一盘
                    sx = 4;// "帥"的i坐标
                    sy = 0;// "帥"的j坐标
                    jx = 4;// "將"的i坐标
                    jy = 9;// "將"的j坐标
                }
            }
        }
        this.zt = false;
        this.jm.repaint();// 重绘
    }

}

7、象棋棋子类

package jiem;

import java.awt.*;

public class QZ {
    private Color color;// 棋子的颜色
    private String name;// 棋子的名字
    private int x;// 棋子的X轴
    private int y;// 棋子的Y轴
    private boolean flag = false;

    public QZ(Color color, String name, int x, int y) {
        this.color = color;
        this.name = name;
        this.x = x;
        this.y = y;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void setFlag(boolean a) {
        this.flag = a;
    }

    public boolean getFlag() {
        return this.flag;
    }
}

8、象棋规则

package jiem;

public class Guize {
    QZ[][] arr;// 声明棋子的数组
    int x;// 棋子的起始X坐标
    int y;// 棋子的起始Y坐标
    boolean canmove = false;// 判断棋子是否能移动的标志位

    public Guize(QZ[][] arr)// 构造函数 参数QZ类
    {
        this.arr = arr;
    }

    // 棋子移动时判断的方法,参数:起始XY,终止XY,棋子的名字
    public boolean canMove(int Sx, int Ex, int Sy, int Ey, String name) {
        int maxX;// 辅助变量
        int minX;
        int maxY;
        int minY;
        canmove = true;// 将判断棋子能否移动的标志位改为true
        if (Sx >= Ex)// 如果起始的X坐标大于等于终止的X坐标
        {
            maxX = Sx;// 将起始的X坐标赋值给maxX
            minX = Ex;// 将终止的X坐标赋值给minX
        } else // 如果起始的X坐标小于终止的X坐标
        {
            maxX = Ex;// 将终止的X坐标赋值给maxX;
            minX = Sx;// 将起始的X坐标赋值给minX;
        }
        if (Sy >= Ey)// 判断起始的Y坐标是否大于等于终止的Y坐标
        {
            maxY = Sy;
            minY = Ey;

        } else {
            maxY = Ey;
            minY = Sy;
        }
        System.out.println("进入判断能否移动的方法中" + "最大" + maxX + "最小X" + minX);
        if (name.equals("車")) {
            this.ju(maxX, minX, maxY, minY);

        } else if (name.equals("馬")) {
            this.ma(maxX, minX, maxY, minY, Sx, Ex, Sy, Ey);
        } else if (name.equals("相")) {
            this.xiang(maxX, minX, maxY, minY, Sx, Ex, Sy, Ey);
        } else if (name.equals("象")) {
            this.xiang1(maxX, minX, maxY, minY, Sx, Ex, Sy, Ey);
        } else if (name.equals("士") || name.equals("仕")) {
            this.shi(maxX, minX, maxY, minY, Sx, Ex, Sy, Ey);
        } else if (name.equals("帥") || name.equals("將")) {
            this.shuai(maxX, minX, maxY, minY, Sx, Ex, Sy, Ey);
        } else if (name.equals("炮") || name.equals("砲")) {
            this.pao(maxX, minX, maxY, minY, Sx, Ex, Sy, Ey);
        } else if (name.equals("兵")) {
            this.bing(maxX, minX, maxY, minY, Sx, Ex, Sy, Ey);
        } else if (name.equals("卒")) {
            this.zu(maxX, minX, maxY, minY, Sx, Ex, Sy, Ey);
        }
        return canmove;
    }

    public void ju(int maxX, int minX, int maxY, int minY)// 車的走棋规则
    {
        System.out.println("进入車的方法中" + "最大" + maxX + "最小X" + minX);
        if (maxX == minX || minX == maxX)// 如果移动前后在一条竖线上
        {
            System.out.println("在一条竖线上");
            for (int i = minY + 1; i < maxY; i++)// 让X不变Y移动看是否两点之间有棋子
            {
                if (arr[maxX][i] != null) {
                    canmove = false;
                    break;
                }
            }
        } else if (maxY == minY)// 如果移动前后在一条竖线上
        {
            System.out.println("在一条横线上");
            for (int i = minX + 1; i < maxX; i++)// 让Y不变 X移动 看是否已有棋子
            {
                if (arr[i][maxY] != null)// 如果有棋子那么将能否移动改为false;
                {
                    canmove = false;
                    break;
                }
            }

        } else if (maxX != minX && maxY != minY)// 移动前后不在一条直线上
        {
            canmove = false;
        }

    }

    public void ma(int maxX, int minX, int maxY, int minY, int Sx, int Ex,
            int Sy, int Ey)// 馬的走棋规则
    {
        int a = maxX - minX;// 判断两点坐标之差
        int b = maxY - minY;
        if (a == 1 && b == 2)// 竖着走
        {
            if (Sy > Ey)// 如果起始的坐标大于终止的坐标证明是从上往下走
            {
                if (arr[Sx][Sy - 1] != null)// 判断马腿处是否有棋子
                {
                    canmove = false;// 证明棋子不可以移动
                }
            } else {
                if (arr[Sx][Sy + 1] != null)// 判断马腿处是否有棋子
                {
                    canmove = false;// 不可以移动
                }

            }
        } else if (a == 2 && b == 1)// 横着走
        {
            if (Sx > Ex)// 从右往左走
            {
                if (arr[Sx - 1][Sy] != null) {
                    canmove = false;
                }
            } else {
                if (arr[Sx + 1][Sy] != null) {
                    canmove = false;
                }
            }
        } else if (!(a == 1 && b == 2 || a == 2 && b == 1)) {
            canmove = false;
        }
    }

    public void xiang(int maxX, int minX, int maxY, int minY, int Sx, int Ex,
            int Sy, int Ey)// 相的走棋规则
    {
        int a = maxX - minX;
        int b = maxY - minY;
        if (a == 2 && b == 2)// 证明是田字
        {
            if (Ey > 4)// 过界了
            {
                canmove = false;
            }
            if (arr[(maxX + minX) / 2][(maxY + minY) / 2] != null) {
                canmove = false;
            }
        } else {
            canmove = false;
        }
    }

    public void xiang1(int maxX, int minX, int maxY, int minY, int Sx, int Ex,
            int Sy, int Ey)// 象的走棋规则
    {
        int a = maxX - minX;
        int b = maxY - minY;
        if (a == 2 && b == 2)// 证明是田字
        {
            if (Ey < 5)// 过界了
            {
                canmove = false;
            }
            if (arr[(maxX + minX) / 2][(maxY + minY) / 2] != null) {
                canmove = false;
            }
        } else {
            canmove = false;
        }
    }

    public void shi(int maxX, int minX, int maxY, int minY, int Sx, int Ex,
            int Sy, int Ey)// 士的走棋规则
    {
        int a = maxX - minX;
        int b = maxY - minY;
        if (a == 1 && b == 1)// 如果走的是斜线
        {
            if (Sy < 4)// 如果是下方的士
            {
                if (Ey > 2)// 越界
                {
                    canmove = false;
                }
            } else// 如果是上方的士
            {
                if (Ey < 7)// 越界
                {
                    canmove = false;
                }
            }
            if (Ex > 5 || Ex < 3) {
                canmove = false;
            }

        } else // 如果走的不是斜线
        {
            canmove = false;
        }
    }

    public void shuai(int maxX, int minX, int maxY, int minY, int Sx, int Ex,
            int Sy, int Ey)// 帅的走棋规则
    {
        int a = maxX - minX;
        int b = maxY - minY;
        if ((a == 0 && b == 1) || (a == 1 && b == 0))// 判断是否走的是一小格
        {
            if (Sy > 7)// 如果是上面的帅
            {
                if (Ey < 7) {
                    canmove = false;
                }
            } else {
                if (Ey > 2) {
                    canmove = false;
                }
            }
            if (Ex < 3 || Ex > 5) {
                canmove = false;
            }
        } else {
            canmove = false;
        }
    }

    public void pao(int maxX, int minX, int maxY, int minY, int Sx, int Ex,
            int Sy, int Ey)// 炮的移动规则
    {
        if (maxX == minX)// 如果在同一条竖线上
        {
            if (arr[Ex][Ey] != null)// 判断终点有棋子的情况下
            {
                int sum = 0;
                for (int i = minY + 1; i < maxY; i++) {
                    if (arr[minX][i] != null) {
                        sum += 1;
                    }
                }
                if (sum != 1)// 如果之间的棋子不是一个
                {
                    canmove = false;
                }
            } else if (arr[Ex][Ey] == null)// 判断终点没有棋子
            {
                for (int i = minY + 1; i < maxY; i++) {
                    if (arr[maxX][i] != null)// 判断起始点之间是否有棋子
                    {
                        canmove = false;
                        break;
                    }
                }
            }

        } else if (maxY == minY)// 如果在一条横线上
        {
            if (arr[Ex][Ey] != null)// 如果终点有棋子
            {
                int sum = 0;
                for (int i = minX + 1; i < maxX; i++)// 判断始终两点之间是否有棋子
                {
                    if (arr[i][maxY] != null) {
                        sum += 1;
                    }
                }
                if (sum != 1) {
                    canmove = false;
                }
            } else if (arr[Ex][Ey] == null) {
                for (int i = minX + 1; i < maxX; i++) {
                    if (arr[i][maxY] != null) {
                        canmove = false;
                        break;
                    }
                }
            }
        } else if (maxX != minX && maxY != minY)// 既不是竖线也不是横线
        {
            canmove = false;
        }
    }

    public void bing(int maxX, int minX, int maxY, int minY, int Sx, int Ex,
            int Sy, int Ey)// 兵的走棋规则
    {
        System.out.println("进入兵的方法");
        if (Ey < 5)// 没过河
        {
            if (Sx != Ex)// 横着走
            {
                canmove = false;
                System.out.println("1");
            }
            if (Ey - Sy != 1) {
                canmove = false;
                System.out.println("2");
            }
        } else// 过河
        {
            if (Ey == Sy)// 横着走
            {
                if (maxX - minX != 1) {
                    canmove = false;
                    System.out.println("3");
                }
            } else if (Ex == Sx)// 竖着走
            {
                if (Ey < Sy) {
                    canmove = false;
                } else {
                    if (maxY - minY != 1) {
                        canmove = false;
                        System.out.println("4");
                    }
                }
            } else if (Sx != Ex && Sy != Ey) {
                canmove = false;
                System.out.println("5");
            }
        }
    }

    public void zu(int maxX, int minX, int maxY, int minY, int Sx, int Ex,
            int Sy, int Ey)// 卒的走棋规则
    {
        if (Ey > 4)// 没过河
        {
            if (Ex != Sx)// 如果不是竖着走
            {
                canmove = false;
            }
            if (Sy - Ey != 1)// 如果走的不是一格
            {
                canmove = false;
            }
        } else// 过河
        {
            if (Sx == Ex)// 如果走的是竖线
            {
                if (Ey > Sy) {
                    canmove = false;
                } else {
                    if (maxY - minY != 1) {
                        canmove = false;
                    }
                }
            } else if (Sy == Ey)// 如果走的横线
            {
                if (maxX - minX != 1) {
                    canmove = false;
                }
            } else if (Sx != Ex && Sy != Ey) {
                canmove = false;
            }
        }
    }
}

参考

我要自学网: http://www.51zxw.net/list.aspx?cid=446

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,218评论 11 349
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • 一、多线程 说明下线程的状态 java中的线程一共有 5 种状态。 NEW:这种情况指的是,通过 New 关键字创...
    Java旅行者阅读 4,665评论 0 44
  • “巫女大人,有人找你。” 自从正式以医师的身份入了义军,许是因为不像当年在清水镇时那样需要把她和母亲分别开来,大家...
    小水Vivian阅读 899评论 0 1