【Java學習筆記】實戰(zhàn)——網(wǎng)絡象棋

服務端
客戶端
項目結構

源碼

1、服務端:主函數(shù)

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("端口號");// 創(chuàng)建標簽 用于顯示文本框中的內容表示的是什么
    JTextField wbk = new JTextField("9999");// 創(chuàng)建文本框 并初始化文本框中的內容
    JButton b1 = new JButton("開啟");// 創(chuàng)建 開始 按鈕
    JButton b2 = new JButton("關閉");// 創(chuàng)建 關閉 按鈕
    JPanel p1 = new JPanel();// 創(chuàng)建面板用于添加 按鈕 標簽 文本框
    Vector online = new Vector();// 用于存儲在線用戶的集合
    JList lis = new JList();// 創(chuàng)建列表
    JScrollPane gd = new JScrollPane(lis);
    JSplitPane fg = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, gd, p1);
    ZThread zt;// 創(chuàng)建主線程對象

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

    public jiemian1()// 構造函數(shù)
    {
        this.cskj();// 初始化控件
        this.sjjt();// 初始化監(jiān)聽scrollPane.getViewport().setView(myList);
        this.csct();// 初始化窗體
    }

    public void cskj()// 初始化組件的函數(shù)
    {
        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()// 初始化窗體的函數(shù)
    {
        this.add(fg);
        this.setTitle("網(wǎng)絡象棋服務器");
        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()// 為組件做監(jiān)聽的函數(shù)
    {
        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, "端口號填寫錯誤,為整數(shù)(0-65535)");
            return;
        }
        if (ii < 0 || ii > 65535) {
            JOptionPane.showMessageDialog(this, "端口號填寫錯誤,為整數(shù)(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()// 刷新列表的函數(shù)
    {
        // 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)// 構造函數(shù)
    {
        this.jm = jm;
        this.cjss();// 對ServerSocket 進行初始化
    }

    public void cjss()// ServerSocket 初始化的函數(shù)
    {
        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);// 創(chuàng)建分線程的對象
                zh.start();// 啟動分線程
            } catch (Exception e) {
                System.out.println(e.toString());
            }

            System.out.println("主線程接收到客戶端的鏈接   Socket 對象創(chuàng)建成功");

            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;// 創(chuàng)建Socket 引用
    Vector v = new Vector();// 建立Vector 集合
    boolean sm = true;// 初始化輔助線程的生命
    DataInputStream din;// 聲明數(shù)據(jù)輸入流對象引用
    DataOutputStream dou;// 聲明數(shù)據(jù)輸出流對象引用
    jiemian1 jm;// 聲明主界面的類引用

    public FThread(jiemian1 jm, Socket s)// 構造方法 參數(shù) 從主線程傳入的 Socket 對象
    {
        this.jm = jm;
        this.s = s;
        this.cjfzxc();// 初始化數(shù)據(jù)流
        
    }

    public void cjfzxc()// 創(chuàng)建數(shù)據(jù)流的方法
    {
        try {
            din = new DataInputStream(s.getInputStream());
            dou = new DataOutputStream(s.getOutputStream());
        } catch (Exception e) {
            System.out.println("輔助線程 數(shù)據(jù)流的創(chuàng)建異常:" + 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("客戶端發(fā)來的昵稱:" + str);
                if (str.startsWith("#nc#"))// 客戶端新用戶上線
                {
                    this.xyh(str);// 用戶上線的方法
                } else if (str.startsWith("#likai#"))// 客戶端離開
                {
                    this.yhlk(str);// 用戶離開的方法
                } else if (str.startsWith("#tiaozhan#"))// 客戶端發(fā)送挑戰(zhàn)的信息
                {
                    this.yhfqtz(str);
                } else if (str.startsWith("#jieshou#"))// 客戶端接受挑戰(zhàn)
                {
                    this.yhjstz(str);
                } else if (str.startsWith("#jjtz#"))// 客戶端拒絕挑戰(zhàn)
                {
                    this.yhjjtz(str);// 被挑戰(zhàn)者拒絕挑戰(zhàn)的方法
                } else if (str.startsWith("#yjjstz#"))// 客戶端已經接受了挑戰(zhàn)(第一種情況)
                {
                    this.yjjstz(str);
                } else if (str.startsWith("#yhfm#"))// 客戶端已經接受了挑戰(zhàn) (第二種情況)
                {
                    this.yhfm(str);
                } else if (str.startsWith("#renshu#"))// 客戶端認輸?shù)姆椒?                {
                    this.renshu(str);
                } else if (str.startsWith("#yidong#"))// 收到客戶端發(fā)來移動棋子的信息
                {
                    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)// 如果出現(xiàn)重名
        {
            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();// 更新主界面列表中的集合數(shù)據(jù)
            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 {
                        // 讓每一個線程把所有線程的名字都發(fā)送到每個客戶端
                        na.dou.writeUTF("#liebiao#" + ft.getName());
                    } catch (Exception e) {
                    }
                }

                if (!na.getName().equals(name)) {// 將新上線的用戶名字發(fā)給每個在線用戶
                    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)))// 將離開的用戶發(fā)送給每個在線用戶
            {
                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)// 用戶發(fā)起挑戰(zhàn)的方法
    {
        String name1 = this.getName();// 發(fā)起挑戰(zhàn)的人
        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))// 得到被挑戰(zhàn)人的線程
            {
                try {
                    ff.dou.writeUTF("#tiaozhan#" + name1);
                } catch (Exception e) {
                }
            }
        }

    }

    public void yhjstz(String str)// 用戶接受挑戰(zhàn)的方法
    {
        String name = str.substring(9);// 接收到挑戰(zhàn)者的名字
        v = this.jm.getVector();
        for (Iterator it = v.iterator(); it.hasNext();) {
            FThread ff = (FThread) it.next();
            if (ff.getName().equals(name))// 遍歷取得被挑戰(zhàn)者的線程
            {
                try {
                    ff.dou.writeUTF("#jieshou#" + this.getName());// 將接受挑戰(zhàn)的人名字發(fā)送給挑戰(zhàn)者
                } catch (Exception e) {
                }
            }
        }

    }

    public void yhjjtz(String str)// 用戶拒絕挑戰(zhàn)的方法
    {
        String name = str.substring(6);// 獲取挑戰(zhàn)者的名字
        v = this.jm.getVector();
        for (Iterator it = v.iterator(); it.hasNext();) {
            FThread ff = (FThread) it.next();
            if (ff.getName().equals(name))// 遍歷得到挑戰(zhàn)者的線程
            {
                try {
                    ff.dou.writeUTF("#jjtz#" + this.getName());// 將被挑戰(zhàn)者的名字發(fā)送給挑戰(zhàn)者
                } catch (Exception e) {
                }
            }
        }
    }

    public void yjjstz(String str)// 自己已經接受挑戰(zhàn)了 發(fā)送給另一個接受挑戰(zhàn)的玩家一個信息
    {
        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)// 用戶繁忙不能接受挑戰(zhàn)
    {
        String name = str.substring(6);// 獲取發(fā)起挑戰(zhàn)的人
        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());// 將被挑戰(zhàn)者繁忙的信息發(fā)送給挑戰(zhàn)者
                } catch (Exception e) {
                }
            }
        }
    }

    public void renshu(String str)// 用戶認輸?shù)姆椒?    {
        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();)// 給每個線程發(fā)送服務器關閉的信息
            {
                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、客戶端:主函數(shù)

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];// 創(chuàng)建一個用于添加棋子的二維數(shù)組
    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();// 初始化監(jiān)聽
        this.cshzt();// 初始化組件的狀態(tài)
        this.cjct();// 初始化窗體
        this.cshqz();// 初始化棋子

    }

    public void cjzj()// 創(chuàng)建組件的方法
    {
        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("挑戰(zhàn)");
        b3.setBounds(15, 230, 90, 20);
        p1.add(b3);
        b4 = new JButton("認輸");
        b4.setBounds(115, 230, 90, 20);
        p1.add(b4);
        b5 = new JButton("接受挑戰(zhàn)");
        b5.setBounds(15, 260, 90, 20);
        p1.add(b5);
        b6 = new JButton("拒絕挑戰(zhàn)");
        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()// 創(chuàng)建窗體
    {
        this.add(fg);
        this.setTitle("網(wǎng)絡象棋客戶端");
        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()// 創(chuàng)建監(jiān)聽的方法
    {
        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);// 創(chuàng)建連接類對象 查看是否鏈接成功
        if (lj.cjsocket()) {
            wbk1.setEditable(false);
            wbk2.setEditable(false);
            wbk3.setEditable(false);
            b2.setEnabled(true);// 關閉設為可用
            b1.setEnabled(false);// 開啟設為不可用
            b3.setEnabled(true);// 挑戰(zhàn)設為可用
            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);// 挑戰(zhàn)設為不可用
        b4.setEnabled(false);// 認輸設為不可用
        b6.setEnabled(false);// jieshou挑戰(zhàn)設為不可用
        b5.setEnabled(false);// 拒絕挑戰(zhàn)設為不可用
        xllb.setEnabled(false);// 下拉列表設為不可用
        lj.zdlk();// 調用客戶端線程的主動離開方法
        // JOptionPane.showMessageDialog(this,"關閉鏈接");
    }

    public void tiaozhan()// 挑戰(zhàn)
    {

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

        if (str == null || str == "") {// 判斷是否取到了玩家姓名
            JOptionPane.showMessageDialog(this, "請選中一名玩家!");
        } else {
            lj.fqtz(str);// 調用發(fā)起挑戰(zhàn)的方法并將選中的玩家做參數(shù)傳進去
            this.caiPan = true;
            this.color = 0;// 將自己設為紅旗
            JOptionPane.showMessageDialog(this, "已發(fā)出挑戰(zhàn)! 請稍等!!");
        }

    }

    public void renshu()// 主動認輸
    {
        wbk1.setEditable(false);
        wbk2.setEditable(false);
        wbk3.setEditable(false);
        b2.setEnabled(true);// 關閉設為可用
        b1.setEnabled(false);// 開啟設為不可用
        b3.setEnabled(true);// 挑戰(zhàn)設為可用
        b4.setEnabled(false);
        b5.setEnabled(false);
        b6.setEnabled(false);
        xllb.setEnabled(true);// 下拉列表設為可用
        lj.yhrs();// 調用連接里的主動認輸?shù)姆椒?        // JOptionPane.showMessageDialog(this,"認輸");
    }

    public void renshu1()// 對方認輸調用的方法
    {
        wbk1.setEditable(false);
        wbk2.setEditable(false);
        wbk3.setEditable(false);
        b2.setEnabled(true);// 關閉設為可用
        b1.setEnabled(false);// 開啟設為不可用
        b3.setEnabled(true);// 挑戰(zhàn)設為可用
        b4.setEnabled(false);
        b5.setEnabled(false);
        b6.setEnabled(false);
        xllb.setEnabled(true);// 下拉列表設為可用
    }

    public void setCaiPan() {
        caiPan = true;
    }

    public void jieshou()// 接受挑戰(zhàn)
    {
        this.caiPan = true;
        this.color = 1;// 將自己設為白棋
        wbk1.setEditable(false);// 主機設為可用
        wbk2.setEditable(false);// 端口設為可用
        wbk3.setEditable(false);// 設為可用戶
        b2.setEnabled(false);// 關閉設為不可用
        b1.setEnabled(false);// 開啟設為可用
        b3.setEnabled(false);// 挑戰(zhàn)設為不可用
        b4.setEnabled(true);// 認輸設為不可用
        b6.setEnabled(false);// 發(fā)起挑戰(zhàn)設為不可用
        b5.setEnabled(false);// 拒絕挑戰(zhàn)設為不可用
        xllb.setEnabled(false);// 下拉列表設為不可用
        lj.jieshou1();// 調用鏈接類中被挑戰(zhàn)者接受挑戰(zhàn)的方法
        JOptionPane.showMessageDialog(this, "請走白棋!!");

    }

    public void jieshou1()// 挑戰(zhàn)者接收到被挑戰(zhàn)者同意的放啊
    {
        wbk1.setEditable(false);// 主機設為可用
        wbk2.setEditable(false);// 端口設為可用
        wbk3.setEditable(false);// 設為可用戶
        b2.setEnabled(false);// 關閉設為不可用
        b1.setEnabled(false);// 開啟設為可用
        b3.setEnabled(false);// 挑戰(zhàn)設為不可用
        b4.setEnabled(true);// 認輸設為不可用
        b6.setEnabled(false);// 發(fā)起挑戰(zhàn)設為不可用
        b5.setEnabled(false);// 拒絕挑戰(zhàn)設為不可用
        xllb.setEnabled(false);// 下拉列表設為不可用
        JOptionPane.showMessageDialog(this, "請走紅旗!!");
    }

    public void yjjstz()// 對方已經接受了挑戰(zhàn)自己不能同對方挑戰(zhàn)
    {
        wbk1.setEditable(false);
        wbk2.setEditable(false);
        wbk3.setEditable(false);
        b2.setEnabled(true);// 關閉設為可用
        b1.setEnabled(false);// 開啟設為不可用
        b3.setEnabled(true);// 挑戰(zhàn)設為可用
        b4.setEnabled(false);
        b5.setEnabled(false);
        b6.setEnabled(false);
        xllb.setEnabled(true);// 下拉列表設為可用
        // lj.start();//啟動客戶端線程
    }

    public void jujue()// 拒絕挑戰(zhàn)
    {
        wbk1.setEditable(false);
        wbk2.setEditable(false);
        wbk3.setEditable(false);
        b2.setEnabled(true);// 關閉設為可用
        b1.setEnabled(false);// 開啟設為不可用
        b3.setEnabled(true);// 挑戰(zhàn)設為可用
        b4.setEnabled(false);
        b5.setEnabled(false);
        b6.setEnabled(false);
        xllb.setEnabled(true);// 下拉列表設為可用
        lj.jujue1();// 調用連接類中的被挑戰(zhàn)方拒絕挑戰(zhàn)的方法
    }

    public void tz()// 對方發(fā)來挑戰(zhàn)后講接受和拒絕按鈕設為可用
    {
        wbk1.setEditable(false);// 主機設為可用
        wbk2.setEditable(false);// 端口設為可用
        wbk3.setEditable(false);// 設為可用戶
        b2.setEnabled(false);// 關閉設為不可用
        b1.setEnabled(false);// 開啟設為可用
        b3.setEnabled(false);// 挑戰(zhàn)設為不可用
        b4.setEnabled(false);// 認輸設為不可用
        b6.setEnabled(true);// 發(fā)起挑戰(zhàn)設為可用
        b5.setEnabled(true);// 拒絕挑戰(zhàn)設為可用
        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, "請輸入整數(shù)(0-65535)");
            return false;
        }
        if (port < 0 || port > 65535) {
            JOptionPane.showMessageDialog(this, "請輸入整數(shù)(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);// 挑戰(zhàn)設為可用
        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;// 創(chuàng)建Socket 的標志位
    DataInputStream dis;
    DataOutputStream dos;
    mainJM mj;// 聲明主界面類對象引用
    QP qp;// 聲明棋盤類的引用
    Vector v;
    String tzz = "";// 用于記錄發(fā)起挑戰(zhàn)的名字
    String btzz = "";// 用于記錄被挑戰(zhàn)者的名字

    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());// 創(chuàng)建輸入流
            dos = new DataOutputStream(s.getOutputStream());// 創(chuàng)建輸出流
            wbk = mj.getWbk3();
            String name = wbk.getText().trim();
            dos.writeUTF("#nc#" + name);// 將昵稱發(fā)送到服務器
        } catch (Exception e) {
            System.out.println("建立數(shù)據(jù)流異常" + e.toString());
        }

    }

    public void run()// run方法
    {
        this.schl();// 調用創(chuàng)建數(shù)據(jù)輸入輸出流的方法
        while (flag) {
            System.out.println("循環(huán)");
            try {
                String str = dis.readUTF().trim();
                if (str.startsWith("#chongming#"))// 收到服務器發(fā)來的重名信息
                {
                    this.chongm();// 調用重名的方法
                } else if (str.startsWith("#close#"))// 收到服務器關閉的信息
                {
                    this.clse();// 調用服務器關閉是客戶端的操作
                } else if (str.startsWith("#liebiao#"))// 收到服務器發(fā)來的列表
                {
                    this.lj(str);// 調用發(fā)來列表的方法
                } else if (str.startsWith("#likai#"))// 收到用戶離開的信息
                {
                    this.likai(str);// 調用 用戶離開的方法
                } else if (str.startsWith("#tiaozhan#"))// 收到挑戰(zhàn)的信息
                {
                    if (btzz == "")// 收到挑戰(zhàn)信息時判斷挑戰(zhàn)者是否無記錄
                    {
                        this.tiaozhan(str);
                    } else // 如果收到挑戰(zhàn)信息btzz有記錄
                    {
                        this.btzzyjl(str);

                    }

                } else if (str.startsWith("#jjtz#"))// 收到拒絕挑戰(zhàn)的信息
                {
                    this.jujue(str);

                } else if (str.startsWith("#jieshou#"))// 收到對方接受挑戰(zhàn)的信息
                {

                    if (btzz == "")// 如果被挑戰(zhàn)者沒有記錄
                    {
                        this.jieshou(str);// 調用被挑戰(zhàn)者接受的方法
                    } else {

                        this.yjjs(str);// 調用挑戰(zhàn)者已接受挑戰(zhàn)的方法
                    }
                } else if (str.startsWith("#yjjstz#"))// 接受到挑戰(zhàn)者發(fā)送來的已接受過其他人挑戰(zhàn)的消息
                {
                    this.yjjstz(str);// 當知道挑戰(zhàn)者已經接受其他人挑戰(zhàn)的消息是做的操作
                } 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)// 另一個用戶發(fā)來接受挑戰(zhàn)的信息
    {
        String name = str.substring(9);// 獲取另一個接受挑戰(zhàn)的玩家名字
        try {
            this.dos.writeUTF("#yjjstz#" + name);
        } catch (Exception e) {
        }
    }

    public void yjjstz(String str)// 挑戰(zhàn)者已經接受挑戰(zhàn)
    {
        String name = str.substring(8);
        tzz = "";// 將挑戰(zhàn)者的名字清空
        this.mj.yjjstz();// 調用主界面中挑戰(zhàn)者已經在同別人挑戰(zhàn)自己不能同發(fā)起者挑戰(zhàn)
        JOptionPane.showMessageDialog(this.mj, name + "正在和其他玩家進行挑戰(zhàn)!!");
    }

    public void tiaozhan(String str)// 對方發(fā)來挑戰(zhàn)的信息后的操作
    {
        tzz = str.substring(10);// 記錄發(fā)起挑戰(zhàn)的人
        this.mj.tz();// 調用主界面對方發(fā)來挑戰(zhàn)的方法
        JOptionPane.showMessageDialog(this.mj, tzz + "向你發(fā)起挑戰(zhàn)!!");
    }

    public void jujue(String str) {
        btzz = str.substring(6);
        JOptionPane.showMessageDialog(this.mj, btzz + "拒絕了您的挑戰(zhàn) !!");
        btzz = "";// 將被挑戰(zhàn)者清空

    }

    public void jieshou(String str) {
        btzz = str.substring(9);
        this.mj.jieshou1();// 調用主界面點擊接受按鈕接的方法
        JOptionPane.showMessageDialog(this.mj, btzz + "接受您的挑戰(zhàn) !!");
    }

    public void btzzyjl(String str)// 當被挑戰(zhàn)者有記錄時
    {
        String name = str.substring(10);// 記錄發(fā)起挑戰(zhàn)的人
        try {
            this.dos.writeUTF("#yhfm#" + name);// 告訴發(fā)起挑戰(zhàn)的人正在挑戰(zhàn)中
        } catch (Exception e) {
        }
    }

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

    }

    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();// 調用主界面對方認輸?shù)姆椒?    }

    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)// 發(fā)起挑戰(zhàn)的方法
    {
        try {
            tzz = this.getName();// 將自身線程的名字賦值給tzz
            this.dos.writeUTF("#tiaozhan#" + str);// 將發(fā)起挑戰(zhàn)的人和被挑戰(zhàn)的人發(fā)送到服務器
        } catch (Exception e) {
        }

    }

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

    public void jujue1()// 被挑戰(zhàn)方拒絕挑戰(zhàn)的方法
    {
        try {
            this.dos.writeUTF("#jjtz#" + tzz);// 將挑戰(zhàn)者的名字發(fā)送到服務器
            tzz = "";// 將挑戰(zhàn)者的名字清空
        } catch (Exception e) {
        }
    }

    public void yhrs()// 主動認輸?shù)姆椒?    {
        if (this.getName().equals(btzz))// 如果自身是被挑戰(zhàn)者
        {
            try {
                this.dos.writeUTF("#renshu#" + tzz);// 將認輸?shù)男畔l(fā)送到對方

            } catch (Exception e) {
            }
        }
        if (this.getName().equals(tzz))// 如果自身是挑戰(zhàn)者
        {
            try {
                this.dos.writeUTF("#renshu#" + btzz);// 將認輸?shù)男畔l(fā)送到對方
            } catch (Exception e) {
            }
        }
        tzz = "";
        btzz = "";
    }

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

    public void setfhmz1() {
        // if(this.getName().equals(btzz))//如果自身是被挑戰(zhàn)者
        // {
        // btzz="";
        // }
        // else if(this.getName().equals(tzz))//如果自身是挑戰(zhàn)者
        // {
        // 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;// 棋盤的初始狀態(tài)
    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;// 棋子的數(shù)組
    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 {// 將該移動信息發(fā)送給對方
                                    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();// 獲得事件發(fā)生的坐標點
        double x = p.getX();
        double y = p.getY();
        if (Math.abs((x - 60) / 1 % 50) <= 15) {// 獲得對應于數(shù)組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) {// 獲得對應于數(shù)組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);// 將該棋子設為選中狀態(tài)
                    zt = true;// 將focus設為true
                    Sx = i;// 保存該坐標點
                    Sy = j;
                }
            } else// 如果是白方
            {
                if (this.arr[i][j].getColor().equals(jm.color2))// 如果該棋子是白色
                {
                    this.arr[i][j].setFlag(true);// 將該棋子設為選中狀態(tài)
                    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);// 將該棋設為非選中狀態(tài)
        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 {// 將該移動信息發(fā)送給對方
            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);// 將該棋設為非選中狀態(tài).
            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、象棋規(guī)則

package jiem;

public class Guize {
    QZ[][] arr;// 聲明棋子的數(shù)組
    int x;// 棋子的起始X坐標
    int y;// 棋子的起始Y坐標
    boolean canmove = false;// 判斷棋子是否能移動的標志位

    public Guize(QZ[][] arr)// 構造函數(shù) 參數(shù)QZ類
    {
        this.arr = arr;
    }

    // 棋子移動時判斷的方法,參數(shù):起始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)// 車的走棋規(guī)則
    {
        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)// 馬的走棋規(guī)則
    {
        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)// 相的走棋規(guī)則
    {
        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)// 象的走棋規(guī)則
    {
        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)// 士的走棋規(guī)則
    {
        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)// 帥的走棋規(guī)則
    {
        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)// 炮的移動規(guī)則
    {
        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)// 兵的走棋規(guī)則
    {
        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)// 卒的走棋規(guī)則
    {
        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;
            }
        }
    }
}

參考

我要自學網(wǎng): http://www.51zxw.net/list.aspx?cid=446

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容

  • 從三月份找實習到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍閱讀 42,320評論 11 349
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,785評論 18 139
  • 一、多線程 說明下線程的狀態(tài) java中的線程一共有 5 種狀態(tài)。 NEW:這種情況指的是,通過 New 關鍵字創(chuàng)...
    Java旅行者閱讀 4,709評論 0 44
  • “巫女大人,有人找你。” 自從正式以醫(yī)師的身份入了義軍,許是因為不像當年在清水鎮(zhèn)時那樣需要把她和母親分別開來,大家...
    小水Vivian閱讀 911評論 0 1