几行代码实现简单的网络象棋游戏,看看Java大牛是怎么做到的?

2023-05-16

几行代码实现简单的网络象棋游戏,看看Java大牛是怎么做到的?

 

游戏规则:

  • 1.将/帅:不能出田字格,不能走斜线,只能前进后退向左向右,每次只走一格;
  • 2.士/仕:不能出田字格,只能走斜线,每次只走一格;
  • 3.象/相:只能走田字格,中间防止蹩脚,不能有棋;

几行代码实现简单的网络象棋游戏,看看Java大牛是怎么做到的?

 

  • 4.马:只能走日,(这个比较麻烦,且看下图标识)

几行代码实现简单的网络象棋游戏,看看Java大牛是怎么做到的?

 

  • 5.车:车只能走直线,这个很好理解,不细说了;
  • 6.炮:
    情况一:纯走路—->中间和目的地都不能有棋
    情况二:吃棋—–>中间要有一颗棋,目标也有棋,且是敌方的棋,毕竟不能自己吃自己哈
  • 7.卒/兵:
    河这边:只能前进不能后退,不能横着走!!!
    河对面:可以前进,可以横着走,不能后退!!!

面板设计

几行代码实现简单的网络象棋游戏,看看Java大牛是怎么做到的?

 

看上去一定很挫!哈哈,别急,听我细细道来!
一般的界面设计我们都知道横纵坐标是这样的:

几行代码实现简单的网络象棋游戏,看看Java大牛是怎么做到的?

 

但是我选择背道而行,不是因为别的,是为了更好的去让初学者理解,我们把原本的x坐标看成数组的列(col),把y坐标看成我们数组的行(row),这样是不是更好理解一点呢,当然了我就是这么理解的,哈哈,接下来的游戏代码编程我们会把横坐标用y*width,纵坐标用x*height你们应该就能理解为什么了,因为x是数组的行,也就是坐标纵坐标(y)的体现,同理数组中的y也是如此。

数据传输:这里我们采用UDP协议来进行通讯,所以你们也要先去了解一下UDP协议的一些基本方法,这里就不细讲了。

通讯协议:这里我们自定义通讯协议啊:

“play|”——–以此开头代表一端发出了游戏邀请,等待另一端的回应;

“connect|”——-以此开头代表另一端收到邀请并且同意建立连接通讯!如果邀请者收到这条消息就代表通讯建立成功,可以开始游戏了;

“move|”——以此开头代表移动数据传输,如果一端移动了棋子,那么另一端也要收到信息,重新绘制界面;

“lose|”——–以此开头代表一方认输,如果有一方认输就会向另一方发送该信息;

“quit|”——-以此开头代表一方退出游戏,任意一方离开都会向对方发送该信息,以提示对方;

“success|”—–以此开头代表胜利,某一方胜利就向对方发出信息,通知对方;

“regret|”——以此开头表示悔棋,这个不用讲了吧,大家都明白,但是本次编程中我没有把这个加进去,这个你们可以自己根据自己需要去添加。

(肯定有人问我这个协议是谁定义的,啊哈哈,让你们失望了,这是我自己定义的,这个通讯协议只适用于你们写的这个代码,和使用这个代码的两个人通讯使用,所以协议如何自己可以定义的哦)

代码实现

1.Chess类:
package internet_chess;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.image.ImageObserver;

import javax.swing.JPanel;

public class Chess {
    public int Row = 12;
    public int Col = 11;
    public String chessName;//当前棋子对象的名字
    public int owner;//当前棋子对象的所有者--黑方还是红方
    public Point point;//当前棋子对象的位置
    public Image chessImage;//当前棋子对象的图像
    private int BLACKCHESS = 1;
    private int REDCHESS = 0;//红方0,黑方1
    private int width = 40;
    private int height = 40;

    public Chess(String name, int own,Point point)//获取每一个棋子对象名字,所有者,位置,和图片信息
    {
        this.chessName = name;
        this.owner = own;
        this.point = point;
        if(owner == BLACKCHESS)//如果所有者是黑方
        {
            if(chessName.equals("将"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/0.png");
            }
            else if(chessName.equals("士"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/1.png");
            }
            else if(chessName.equals("象"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/3.png");
            }
            else if(chessName.equals("马"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/5.png");
            }
            else if(chessName.equals("车"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/7.png");
            }
            else if(chessName.equals("炮"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/9.png");
            }
            else if(chessName.equals("卒"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/11.png");
            }
        }
        else//如果所有者是红方
        {
            if(chessName.equals("帅"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/16.png");
            }
            else if(chessName.equals("仕"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/17.png");
            }
            else if(chessName.equals("相"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/19.png");
            }
            else if(chessName.equals("马"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/21.png");
            }
            else if(chessName.equals("车"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/23.png");
            }
            else if(chessName.equals("炮"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/25.png");
            }
            else if(chessName.equals("兵"))
            {
                chessImage = Toolkit.getDefaultToolkit().getImage("F:/Image/chess/27.png");
            }
        }
    }

    protected void paint(Graphics g,JPanel i)//画棋子
    {
        g.drawImage(chessImage, point.y*width-width/2, point.x*height-height/2, width, height, (ImageObserver)i);
    }

    protected void paintSeclected(Graphics g)//画鼠标选择了以后的棋子对象的边框
    {
        g.drawRect(point.y*width-width/2, point.x*height-height/2, width, height);
    }

    public void SetPos(int x, int y)//重新设置移动以后的棋子对象的位置坐标
    {
        point.x = x;
        point.y = y;
    }

    public void ReversePos()//将该对象的位置坐标逆置输出,用于方便显示信息情况
    {
        point.x = Row-1 - point.x;
        point.y = Col-1 - point.y;
    }
}

2.ChessPanel类:
package internet_chess;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class ChessPanel extends JPanel implements Runnable{
    private int BLACKCHESS = 1;
    private int REDCHESS = 0;//黑棋是1,红旗是0
    public Chess chess[] = new Chess[32];//创建了32个棋子对象
    private int width = 40;
    private int height = 40;
    public int Row = 12;
    public int Col = 11;//11行10列
    public int map[][] = new int [Row][Col];
    public int player;//设置当前玩家对象
    private boolean isFirst = false;//判断是否是第一次点击的棋子,以此分开两次点击棋子的碰撞矛盾
    private int x1,y1,x2,y2;//用来保存第一次第二次选中的坐标的
    private boolean flag = true;//用来控制线程的运行
    private boolean isPlay = false;
    private Chess firstChess = null;
    private Chess secondChess = null;//设置第一次点击的棋子和第二次选中的棋子对象

    private InetAddress myID;//自己id地址
    private InetAddress youID;//目标ID地址
    private int sendport;//发送端口
    private int receiveport = 8888;//接收端口


    public ChessPanel()//构造函数
    {
        init_map();//初始化棋盘
        //给这个面板添加鼠标监听机制
        this.addMouseListener(new MouseAdapter()
        {
            public void mouseClicked(MouseEvent e)
            {
                if(isPlay == true)//判断是否该本方下棋
                {
                    SelectChess(e.getPoint());//选择要移动的棋子
                    repaint();
                }
            }

            public void SelectChess(Point pos)
            {
                int x = pos.x;
                int y = pos.y;//获取此时此刻鼠标点击的位置坐标
                System.out.println("选择要移动的棋子坐标:x->"+x+"  y->"+y);
                if(x > 0 && x < (Col-1)*width && y > 0 && y < (Row-1)*height)//判断鼠标是否在合理的范围,不在就直接退出
                {
                    Point point = ReSetID(x,y);
                    if(isFirst)//判断是否是第一次选中的棋子
                    {
                        x1 = point.x;
                        y1 = point.y;
                        //判断第一次选中的棋子是不是自己的棋子或者是不是无效棋子,不是就失败
                        int id = map[x1][y1];
                        if(id != -1 && chess[id].owner == player)
                        {
                            isFirst = false;
                            firstChess = chess[id];
                            System.out.println("id->"+id);
                        }
                        else//第一次选择的棋子无效
                        {
                            JOptionPane.showConfirmDialog(null, "提示", "第一次选棋无效!请重新选择!", JOptionPane.OK_OPTION);
                            isFirst = true;
                        }
                    }
                    else//第二次选中的棋子
                    {
                        x2 = point.x;
                        y2 = point.y;
                        int id = map[x2][y2];
                        if(id != -1 && chess[id].owner != player)//第二次选择了敌方棋子,将敌方棋子保存起来
                        {
                            isFirst = true;
                            secondChess = chess[id];
                            //开始判断是否可以移动棋子,如果可以就将棋子移动,并发信息给对方我们已经移动的棋子信息
                            //判断是否可以移动棋子
                            if(IsMoveChess(firstChess,x2,y2))//可以移动-吃棋
                            {
                                int idx1 = map[x1][y1];
                                map[x1][y1] = -1;
                                map[x2][y2] = idx1;
                                chess[id] = null;
                                firstChess.SetPos(x2, y2);
                                repaint();
                                send("move|"+String.valueOf(idx1)+"|"+String.valueOf(Row-1-x2)+"|"+String.valueOf(Col-1-y2)+"|",youID,sendport);
                                if(id == 0)//吃掉了黑棋将军
                                {
                                    send("success|红棋赢",youID,sendport);
                                    isPlay = false;
                                    JOptionPane.showConfirmDialog(null, "红棋胜利", "恭喜您,您赢了!", JOptionPane.OK_OPTION);
                                    return;
                                }
                                else if(id == 16)//吃掉了红棋大帅
                                {
                                    send("success|黑棋赢",youID,sendport);
                                    isPlay = false;
                                    JOptionPane.showConfirmDialog(null, "黑棋胜利", "恭喜您,您赢了!", JOptionPane.OK_OPTION);
                                    return;
                                }
                                isFirst = true;
                                isPlay = false;
                            }
                            else//表示不能吃棋,重新下棋
                            {
                                JOptionPane.showConfirmDialog(null, "提示", "对不起,移动棋子失败,请重新选择目标!", JOptionPane.ERROR_MESSAGE);
                                isFirst = false;
                            }
                        }
                        else if(id != -1 && chess[id].owner == player)//第二次又选择了自己的棋子,那么就将第二次选择的棋子当做第一次选择的棋子
                        {
                            firstChess = chess[id];
                            x1 = x2;
                            y1 = y2;
                            isFirst = false;
                        }
                        else//第二次选择的棋子是空,那么就是单纯的移动棋子
                        {
                            secondChess = null;
                            if(IsMoveChess(firstChess,x2,y2))//可以移动-吃棋
                            {
                                int idx1 = map[x1][y1];
                                map[x1][y1] = -1;
                                map[x2][y2] = idx1;
//                              chess[id] = null;
                                firstChess.SetPos(x2, y2);
                                send("move|"+String.valueOf(idx1)+"|"+String.valueOf(Row-1-x2)+"|"+String.valueOf(Col-1-y2)+"|",youID,sendport);
                                System.out.println("第二次选中棋子为空:目标-》"+(Row-1-x2)+"  "+(Col-1-y2));
                                repaint();
                                isFirst = true;
                                isPlay = false;
                            }
                        }
                    }
                }
            }
        });
    }

    public boolean IsMoveChess(Chess chess,int x,int y)//判断是否可以移动棋子----移动棋子的规则
    {
        if(chess.chessName.equals("将") || chess.chessName.equals("帅"))//只能走一步
        {
            int x0 = chess.point.x;
            int y0 = chess.point.y;
            if(x >= 8 && x <= 10 && y >= 4 && y <= 6)
            {
//              int x0 = chess.point.x;
//              int y0 = chess.point.y;
                if(Math.abs(x - x0) > 1 || Math.abs(y - y0) > 1)
                    return false;
                else if(Math.abs(x - x0)*Math.abs(y - y0) != 0)//不能走斜线
                    return false;
                else
                    return true;
            }
            if(this.chess[map[x][y]].chessName.equals("将") || this.chess[map[x][y]].chessName.equals("帅") && (y0 == y))//判断两个将领之间吃棋
            {
                int min = x < x0? x : x0;
                int max = x > x0? x : x0;
                for(min = min+1; min < max; min++)
                {
                    if(map[min][y] != -1)
                        return false;
                }
                return true;
            }
            else
                return false;
        }
        else if(chess.chessName.equals("士") || chess.chessName.equals("仕"))//士也不能出田字格,且,士走斜线,每次只走一格
        {
            if(x >= 8 && x <= 10 && y >= 4 && y <= 6)
            {
                int x0 = chess.point.x;
                int y0 = chess.point.y;
                if(Math.abs(x - x0) * Math.abs(y - y0) != 1)
                {
                    return false;
                }
                else
                    return true;
            }
            else//越界
                return false;
        }
        else if(chess.chessName.equals("象") || chess.chessName.equals("相"))//相走田字,且不能过河
        {
            if(x >= 6 && x != 11 && y >= 1 && y <= 9)
            {
                int x0 = chess.point.x;
                int y0 = chess.point.y;
                if(Math.abs(x - x0) * Math.abs(y - y0) != 4)
                {
                    return false;
                }
                else if(Math.abs(x - x0) == 2 && Math.abs(y - y0) == 2)
                {
                    int xm,ym;//求取中间值,防止中间有值不能走棋
                    xm = x > x0? x-1:x0-1;
                    ym = y > y0? y-1:y0-1;
                    if(map[xm][ym] != -1)//表示中间有棋
                        return false;
                    return true;
                }
                else//防止1*4 == 4的情况出现
                    return false;
            }
            else
                return false;
        }
        else if(chess.chessName.equals("马"))//马走日,防止蹩脚的情况出现
        {
            if(x >= 1 && x <=10 && y >= 1 && y <= 9)
            {
                int x0 = chess.point.x;
                int y0 = chess.point.y;
                if(Math.abs(x - x0) * Math.abs(y - y0) == 2)//判断是否走日
                {
                    //判断是否蹩脚
                    if(Math.abs(y - y0) == 2)
                    {
                        if(map[x0][y+1] != -1 && y < y0)//左边
                        {
                            return false;
                        }
                        if(map[x0][y-1] != -1 && y0 < y)//右边
                        {
                            return false;
                        }
                        return true;
                    }
                    else
                    {
                        if(map[x+1][y0] != -1 && x < x0)//上边
                        {
                            return false;
                        }
                        if(map[x-1][y0] != -1 && x > x0)//下边
                        {
                            return false;
                        }
                        return true;
                    }       
                }
                else
                    return false;
            }
            else
                return false;
        }
        else if(chess.chessName.equals("车"))//车走直线
        {
            if(x >= 1 && x <=10 && y >= 1 && y <= 9)
            {
                int x0 = chess.point.x;
                int y0 = chess.point.y;
                if(x == x0)//水平移动
                {
                    int i = y < y0 ? y : y0;
                    int max = y > y0 ? y : y0;
                    for(i = i+1; i < max; i++)//不判断目标状态,目标状态能否走在外面判断
                    {
                        if(map[x][i] != -1)
                        {
//                          if(i == max && this.chess[map[x][i]].owner != chess.owner)
//                          {
//                              return true;
//                          }
                            return false;
                        }
                    }
                    return true;
                }
                else if(y == y0)//垂直移动
                {
                    int i = x < x0 ? x : x0;
                    int max = x > x0 ? x : x0;
                    for(i = i+1; i < max; i++)
                    {
                        if(map[i][y] != -1)
                        {
//                          if(i == max && this.chess[map[i][y]].owner != chess.owner)
//                          {
//                              return true;
//                          }
                            return false;
                        }
                    }
                    return true;
                }
                return false;
            }
            else
                return false;//越界
        }
        else if(chess.chessName.equals("炮"))//跑隔山打牛,不隔山就走路,水平或者垂直移动
        {
            if(x >= 1 && x <=10 && y >= 1 && y <= 9)
            {
                int x0 = chess.point.x;
                int y0 = chess.point.y;
                int countx = 0;
                int county = 0;
                if(x == x0)//水平移动
                {
                    int i = y < y0 ? y : y0;
                    int max = y > y0 ? y : y0;
                    for(i = i+1; i < max; i++)
                    {
                        if(map[x][i] != -1)
                        {
                            countx++;
                        }
                    }
                }
                else if(y == y0)//垂直移动
                {
                    int i = x < x0 ? x : x0;
                    int max = x > x0 ? x : x0;
                    for(i = i+1; i < max; i++)
                    {
                        if(map[i][y] != -1)
                        {
                            county++;
                        }
                    }
                }
                if(countx == 1 || county == 1)//说明中间有一个棋
                {
//                  if(this.chess[map[x][y]].owner != chess.owner)
//                  {
//                      return true;
//                  }
//                  else
//                      return false;
                    System.out.println("countx:"+countx);
                    System.out.println("county:"+county);
                    return true;
                }
                else if(countx == 0 && county == 0)//说明中间没有棋
                {
                    if(map[x][y] == -1)//目标没有棋
                    {
                        return true;
                    }
                    else
                        return false;
//                  return true;
                }
                else
                    return false;
            }
            else
                return false;//越界
        }
        else if(chess.chessName.equals("兵") || chess.chessName.equals("卒"))//卒子在自己区域不能退,只能前进,每次只走一步
        {
            if(x < 7 && x >= 1 && y >= 1 && y <= 9)
            {
                int x0 = chess.point.x;
                int y0 = chess.point.y;
                if(x == x0 && Math.abs(y-y0) == 1)//横向只走一步,判断是否在河的这边还是那边
                {
                    //如果是河的这边就不能走横向
                    if(x == 6)
                        return false;
                    else
                        return true;
                }
                if(y == y0 && x - x0 == -1)//纵向只走一步,且必须向前走
                {
                    return true;
                }
                return false;
            }
            else
                return false;
        }
        return false;
    }

    public Point ReSetID(int x, int y)//重置id,将id转化成可辨识的坐标信息
    {
        int posx = (y+height/2)/height;
        int posy = (x+width/2)/width;
        return new Point(posx,posy);
    }

    public void init_map()//初始化棋盘
    {
        for(int i = 0; i < Row; i++)
        {
            for(int j = 0; j < Col; j++)
            {
                map[i][j] = -1;//将棋盘初始化为-1,表示没有棋子id
            }
        }
    }

    public void paint(Graphics g)//自己画棋盘
    {
        super.paint(g);
        g.clearRect(0,0,this.getWidth(),this.getHeight());
        //画棋盘
        int a = 1;
        int b = 8;
        int c = 5;//两军中间的分界线
        for(int j = 1; j < Row-1; j++)//画横线
        {
            g.drawLine(a*width, j*height, (Col-2)*width, j*height);
        }
        for(int i = 1; i < Col-1; i++)//画竖线
        {
            g.drawLine(i*width, a*height, i*width, (Row-2)*height);
            if(i == 4)
            {
                g.drawLine(i*width, a*height, (i+2)*width, (a+2)*height);
                g.drawLine(i*width, b*height, (i+2)*width, (b+2)*height);
            }
            if(i == 6)
            {
                g.drawLine(i*width, a*height, (i-2)*width, (a+2)*height);
                g.drawLine(i*width, b*height, (i-2)*width, (b+2)*height);
            }
        }
        g.drawRect(0, 0, (Col-1)*width, (Row-1)*height);
        g.setColor(Color.GRAY);
        g.fillRect(a*width, c*height,(Col-2-a)*width, height);
        g.setFont(new Font("黑体",Font.BOLD,20));
        g.setColor(Color.white);
        g.drawString("楚  河    汉  界", 3*width, (c+1)*height-10);
        g.setColor(Color.black);
        //画棋子
        for(int i = 0; i < chess.length; i++)
        {
            if(chess[i] != null)
            {
                chess[i].paint(g, this);
            }
        }
        if(firstChess != null)
        {
            firstChess.paintSeclected(g);
        }
        if(secondChess != null)
        {
            secondChess.paintSeclected(g);
        }

    }

    public void send(String str,InetAddress ip,int port) //发送数据报
    {
        DatagramSocket s = null;
        try{
            s = new DatagramSocket();//创建一个数据报套接字
            byte data[] = new byte[100];
            data = str.getBytes();
            DatagramPacket pocket = new DatagramPacket(data,data.length,ip,port);//将数据报的信息放入自寻址包中,自寻址信息包括数据,数据长度,目标ip地址,目标端口号
            s.send(pocket);//发送自寻址包
            System.out.println("发送信息:"+str);
        }catch(IOException ex)
        {
            ex.printStackTrace();
        }finally
        {
            if(s != null)
                s.close();
        }
    }

    public void startgame(InetAddress ip, int otherport, int myport)//游戏正式开始的起点入口
    {
        youID = ip;
        this.sendport = otherport;
        this.receiveport = myport;
        try{
            myID = InetAddress.getLocalHost();
        }catch(UnknownHostException ex)
        {
            ex.printStackTrace();
        }
        send("play|",youID,sendport);//发送邀请,等待目标ip的回应----开启一个线程,不断监听端口,检查是否有消息,是否建立连接成功
        Thread t = new Thread(this);
        t.start();
    }

    public void FirstPaintChess()//第一次画棋盘---将每个棋盘上的棋子对象摆放完好,设置各自的初始属性
    {
        //原本把黑棋放上面,红棋放下面,但是为了显示效果,凡是玩家玩,都把玩家的花色放下面
        init_map();//如果再玩一局就要先清空棋盘,然后再重置棋子,否则上一局某些位置上面的id会遗留下来
        paintChess();
        if(player == BLACKCHESS)
        {
            ReverseChess();
        }
        repaint();
    }

    public void ReverseChess()//转置,将坐标改变,以便于下棋者下棋
    {
        //先改变坐标
//      for(int i = 0; i < 32; i++)
//      {
//          if(chess[i] != null)
//             chess[i].ReversePos();
//      }
        //改变map地图id
        for(int i = 0; i < 32; i++)
        {
            if(chess[i] != null)
            {
                chess[i].ReversePos();
                int xx = chess[i].point.x;
                int yy = chess[i].point.y;
                map[xx][yy] = i;
            }
        }
    }

    public void paintChess()//画棋盘显示,上面黑棋,下面红棋
    {
        //黑方
        chess[0] = new Chess("将",BLACKCHESS,new Point(1,5));
        map[1][5] = 0;
        chess[1] = new Chess("士",BLACKCHESS,new Point(1,4));
        map[1][4] = 1;
        chess[2] = new Chess("士",BLACKCHESS,new Point(1,6)); 
        map[1][6] = 2;
        chess[3] = new Chess("象",BLACKCHESS,new Point(1,3)); 
        map[1][3] = 3;
        chess[4] = new Chess("象",BLACKCHESS,new Point(1,7)); 
        map[1][7] = 4;
        chess[5] = new Chess("马",BLACKCHESS,new Point(1,2)); 
        map[1][2] = 5;
        chess[6] = new Chess("马",BLACKCHESS,new Point(1,8)); 
        map[1][8] = 6;
        chess[7] = new Chess("车",BLACKCHESS,new Point(1,1)); 
        map[1][1] = 7;
        chess[8] = new Chess("车",BLACKCHESS,new Point(1,9)); 
        map[1][9] = 8;
        chess[9] = new Chess("炮",BLACKCHESS,new Point(3,2)); 
        map[3][2] = 9;
        chess[10] = new Chess("炮",BLACKCHESS,new Point(3,8)); 
        map[3][8] = 10;
        for(int i = 11,j = 1; i < 16; i++,j+=2)
        {
            chess[i] = new Chess("卒",BLACKCHESS,new Point(4,j)); 
            map[4][j] = i;
        }

        //画红棋
        chess[16] = new Chess("帅",REDCHESS,new Point(10,5)); 
        map[10][5] = 16;
        chess[17] = new Chess("仕",REDCHESS,new Point(10,4)); 
        map[10][4] = 17;
        chess[18] = new Chess("仕",REDCHESS,new Point(10,6)); 
        map[10][6] = 18;
        chess[19] = new Chess("相",REDCHESS,new Point(10,3)); 
        map[10][3] = 19;
        chess[20] = new Chess("相",REDCHESS,new Point(10,7)); 
        map[10][7] = 20;
        chess[21] = new Chess("马",REDCHESS,new Point(10,2)); 
        map[10][2] = 21;
        chess[22] = new Chess("马",REDCHESS,new Point(10,8)); 
        map[10][8] = 22;
        chess[23] = new Chess("车",REDCHESS,new Point(10,1)); 
        map[10][1] = 23;
        chess[24] = new Chess("车",REDCHESS,new Point(10,9)); 
        map[10][9] = 24;
        chess[25] = new Chess("炮",REDCHESS,new Point(8,2)); 
        map[8][2] = 25;
        chess[26] = new Chess("炮",REDCHESS,new Point(8,8)); 
        map[8][8] = 26;
        for(int i = 27, j = 1; i < 32; i++, j+=2)
        {
            chess[i] = new Chess("兵",REDCHESS,new Point(7,j)); 
            map[7][j] = i;
        }
    }

    @Override
    public void run()
    {
        DatagramSocket sock = null;
        try {
            sock = new DatagramSocket(receiveport);//打开监听窗口
            byte data[] = new byte[100];
            DatagramPacket pocket = new DatagramPacket(data,data.length);
            while(flag)
            {
                sock.receive(pocket);//接收数据
                //读取接收信息
                String str = new String(data);
                String s[] = new String[6];
                s = str.split("\\|");//将数据信息按照|进行分割
                if(s[0].equals("play"))//表示此时这个对象是一个被邀请的对象,将被邀请的对象设置为黑棋
                {
                    player = BLACKCHESS;//被邀请者设为黑棋
                    send("connect|",youID,sendport);
                    //开始画棋盘
                    FirstPaintChess();
                    isPlay = false;//因为是红棋先走,所以黑棋此时不能下棋
                }
                else if(s[0].equals("connect"))//表示此时的对象是游戏发出者对象,并且已经和被邀请对象建立连接
                {
                    player = REDCHESS;//游戏发出者设为红棋对象
                    FirstPaintChess();
                    isPlay = true;//因为此时是红棋,而红旗先走,所以红棋此时可以下棋
                }
                else if(s[0].equals("lose"))//对方认输
                {
                    JOptionPane.showConfirmDialog(null, "认输", "对方棋手认输!", JOptionPane.OK_OPTION);
                    isPlay = false;
                }
                else if(s[0].equals("success"))//对方赢了
                {
                    if(s[1].equals("黑棋赢"))
                    {
                       JOptionPane.showConfirmDialog(null, "输了", "黑棋赢了!您输了!", JOptionPane.OK_OPTION);
                    }
                    else if(s[1].equals("红棋赢"))
                    {
                        JOptionPane.showConfirmDialog(null, "输了", "红棋赢了!您输了!", JOptionPane.OK_OPTION);
                    }
                    isPlay = false;
                }
                else if(s[0].equals("move"))//对方走棋
                {
                    int indx = Integer.parseInt(s[1]);
                    System.out.println("indx->"+indx);
                    int posx = Integer.parseInt(s[2]);
                    System.out.println("posx->"+posx);
                    int posy = Integer.parseInt(s[3]);
                    System.out.println("posy->"+posy);
                    int x = chess[indx].point.x;
                    int y = chess[indx].point.y;
                    map[x][y] = -1;
                    chess[indx].point.x = posx;
                    chess[indx].point.y = posy;
                    if(map[posx][posy] != -1)
                    {
                        chess[map[posx][posy]] = null;
                    }
                    map[posx][posy] = indx;
                    repaint();
                    isPlay = true;
                }
                else if(s[0].equals("quit"))//对方退出
                {
                    JOptionPane.showConfirmDialog(null, "提示", "对方离开,游戏结束!", JOptionPane.OK_OPTION);
                    isPlay = false;
                    flag = false;//退出线程
                }

            }

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally
        {
            if(sock != null)
            {
                sock.close();
            }
        }

    }
}

3.ChessFrame类:
package internet_chess;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class ChessFrame extends JFrame{
    private JButton start = new JButton("开始");
    private JButton end = new JButton("结束");
    private JButton lose = new JButton("认输");
    private JPanel paneUp = new JPanel();
    private ChessPanel chesspanel = new ChessPanel();
    private JPanel paneDown = new JPanel();
    private JLabel IPlabel = new JLabel("IP:");
    private JLabel otherPortlabel = new JLabel("目标端口");
    private JLabel imageicon = new JLabel();
    private JTextField ip_address = new JTextField("127.0.0.1");
    private JTextField otherPort = new JTextField("9999");

    private InetAddress myID;//自己id地址
    private InetAddress youID;//目标ID地址
    private int sendport;//发送端口
    private int receiveport = 8888;//接收端口


    public ChessFrame()//构造函数
    {
        paneDown.setLayout(new FlowLayout());
        IPlabel.setBounds(10, 10, 40, 20);
        ip_address.setBounds(new Rectangle(60,10,50,20));
        paneDown.add(IPlabel);
        paneDown.add(ip_address);
        paneDown.add(otherPortlabel);
        paneDown.add(otherPort);
        paneDown.add(start);
        paneDown.add(lose);
        paneDown.add(end);
        lose.setEnabled(false);

        imageicon.setBounds(new Rectangle(300,0,100,100));
        imageicon.setIcon(new ImageIcon("F:/Image/chess/0.png"));//标签加载图片
        paneUp.add(imageicon,BorderLayout.CENTER);

        Container con = this.getContentPane();
        con.add(paneUp,BorderLayout.NORTH);
        con.add(chesspanel,BorderLayout.CENTER);
        con.add(paneDown,BorderLayout.SOUTH);

        this.setTitle("8888网络象棋");
        this.setSize(new Dimension(600,700));
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        start.addMouseListener(new MouseAdapter()
        {
            public void mouseClicked(MouseEvent e)
            {
                try {
                    String ip = ip_address.getText();//获取当前目标ip地址
                    sendport = Integer.parseInt(otherPort.getText());//获取目标连接端口
                    myID = InetAddress.getLocalHost();//获取本地ip地址
                    youID = InetAddress.getByName(ip);//获取目标ip地址
                } catch (UnknownHostException e1) {
                    e1.printStackTrace();
                }
                chesspanel.startgame(youID,sendport,receiveport);
                lose.setEnabled(true);
            }
        });

        end.addMouseListener(new MouseAdapter()
        {
            public void mouseClicked(MouseEvent e)
            {
                try{
                    chesspanel.send("quit|",youID,sendport);//向对方发送离开信息,同时断开连接
                    System.exit(0);
                }catch(Exception ex)
                {
                    ex.printStackTrace();
                }
            }
        });

        lose.addMouseListener(new MouseAdapter()
        {
            public void mouseClicked(MouseEvent e)
            {
                try{
                    chesspanel.send("lose|",youID,sendport);//向对方发送认输信息
                }catch(Exception ex)
                {
                    ex.printStackTrace();
                }
            }
        });


        //加一个对方求和的按钮
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new ChessFrame();
    }

}

代码结果

几行代码实现简单的网络象棋游戏,看看Java大牛是怎么做到的?

 

几行代码实现简单的网络象棋游戏,看看Java大牛是怎么做到的?

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

几行代码实现简单的网络象棋游戏,看看Java大牛是怎么做到的? 的相关文章

  • ros中设置Global Options,以及rqt_tf_tree树讲解,TF树的理解,使用GUI插件,用于可视化ROS-TF的框架树

    一 设置Global Options 如图30 启动rviz界面后 首先要对Global Options进行设置 Global Options里面的参数是一些全局显示相关的参数 其中的Fixed Frame参数是全局显示区域依托的坐标系 我
  • jetson xavier和NX 以及nano如何通过sd卡启动,sdkManager刷机

    1 xff0c xavier可以通过迁移系统的方法进行 Jetson AGX Xavier从SD卡启动系统及系统移植 xavier AGX不能直接使用sdkManager刷机到SD卡 xff0c 所以需要用系统迁移的方法 2 xff0c N
  • Linux NameSpace (目录)

    1 User Namespace 详解 2 Pid Namespace 详解 3 Mnt Namespace 详解 4 UTS Namespace 详解 5 IPC Namespace 详解 6 Network Namespace 详解
  • Python Nose 自动化测试框架介绍

    文章目录 1 unittest 简介1 1 python 单元测试1 2 unittest 测试框架1 3 默认模式1 4 手工模式 2 nose 扩展框架2 1 96 nose 96 的安装和基本用法2 2 96 被测对象 96 的扩展2
  • TLSF 内存分配算法详解

    文章目录 1 DSA 背景介绍1 1 mmheap1 2 mmblk 2 TLSF 原理2 1 存储结构2 2 内存池初始化2 3 free2 4 malloc 参考资料 1 DSA 背景介绍 动态内存管理算法 DSA xff0c Dyna
  • 史上最全采样方法详细解读与代码实现

    项目github地址 xff1a bitcarmanlee easy algorithm interview and practice 欢迎大家star xff0c 留言 xff0c 一起学习进步 1 什么是采样 在信号系统 数字信号处理中
  • Linux Kdump 机制详解

    文章目录 1 简介1 1 安装1 2 触发 kdump1 3 调试 kdump1 3 1 安装 debuginfo vmlinux1 3 2 编译 kernel 1 4 kdump tools service 流程分析 2 原理分析2 1
  • Buildroot 用户手册 (中文)

    文章目录 I Getting started1 About Buildroot2 System requirements2 1 Mandatory packages2 2 Optional packages 3 Getting Buildr
  • 正则表达式 (学习笔记)

    正则表达式的难度不在于难懂 xff0c 而在于对它的表述没有恰当的分类和组织 xff0c 所以弄得很零散难以记忆 按照自己的理解和归纳记录一份笔记 xff0c 以备遗忘时查看 正则表达式 regular expressions 是一种用来匹
  • Linux usb 2. 协议分析

    文章目录 0 背景1 USB 协议传输格式1 1 Packet1 1 1 Token Packet1 1 2 Data Packet1 1 3 Handshake Packet1 1 4 Special Packet 1 2 Transac
  • RISCV 入门 (学习笔记)

    文章目录 1 risv 相关背景1 1 arm 授权费1 2 riscv 发展历史1 3 riscv 风险 2 指令集2 1 可配置的通用寄存器组2 2 规整的指令编码2 3 简洁的存储器访问指令2 4 高效的分支跳转指令2 5 简洁的子程
  • Linux usb 1. 总线简介

    文章目录 1 USB 发展历史1 1 USB 1 0 2 01 2 USB 3 01 3 速度识别1 4 OTG1 5 phy 总线1 6 传输编码方式 2 总线拓扑2 1 Device 内部的逻辑关系2 2 Compound Compos
  • Linux usb 3. Host 详解

    文章目录 1 简介2 Usb Core 驱动设备模型2 1 Usb Device Layer2 1 1 device struct usb device 2 1 2 driver struct usb device driver 2 1 3
  • Linux usb 4. Device 详解

    文章目录 1 简介2 Platform Layer2 1 Platform Device2 2 Platform Driver 3 UDC Gadget Layer3 1 Gadget Bus3 2 Gadget Device3 2 1 E
  • Linux USB (目录)

    1 USB 总线简介 2 USB 协议分析 3 USB Host 详解 4 USB Device 详解 5 usbip USB Over IP 使用实例 6 USB HC UDC 测试 7 Linux 配置 ADBD
  • Linux usb 5. usbip (USB Over IP) 使用实例

    文章目录 0 简介1 Server 配置2 Client 配置参考资料 0 简介 USB Over IP 是一种应用很多的场景 xff0c 目前已经有现成的解决方案 usbip linux 和 windows 环境下都有配套软件 xff0c
  • 最全随机抽样算法(从N个数中抽取M个等)集合

    项目github地址 xff1a bitcarmanlee easy algorithm interview and practice 欢迎大家star xff0c 留言 xff0c 一起学习进步 1 从N个数中等概率抽取M个数 从N个样本
  • Linux usb 6. HC/UDC 测试

    文章目录 1 背景介绍2 Device gadget zero 2 1 96 gadget zero 96 创建2 2 SourceSink Function2 3 Loopback Function 3 Host usbtest ko 3
  • Linux usb 7. Linux 配置 ADBD

    文章目录 1 简介2 ADBD 源码3 Gadget Device 配置3 1 functionfs3 2 legacy 方式配置 functionfs3 3 configfs 方式配置 functionfs3 4 adb 使用配置 参考资
  • HW-RTOS 概述

    文章目录 1 背景介绍1 1 OS 实时难题1 2 Linux 实时补丁1 3 Xenomai 43 Linux 双内核1 4 HW RTOS1 5 More 2 优化点1 xff1a API2 1 原理介绍2 1 1 Software A

随机推荐

  • RISCV MMU 概述

    1 背景简介 Linux 内存管理包含很多内容 xff0c 主要知识点可以参考 Linux Mem 本文只描述其中的一个知识点 Paging and MMU 本文以全志 D1 为例 xff0c 包含了平头哥出品的一颗 Riscv64 的 C
  • 主流 RTOS 评估

    1 RT Thread RT Thread 是国内出产的一款非常优秀的 RTOS 它和 FreeRTOS uCos 等经典 RTOS 最大的不同是 xff1a 它不仅仅是一个实时内核 xff0c 还具备丰富的中间层组件 它提供了一个完整的软
  • Linux mem 2.8 Kfence 详解

    1 原理介绍 Kfence Kernel Electric Fence 是 Linux 内核引入的一种低开销的内存错误检测机制 xff0c 因为是低开销的所以它可以在运行的生产环境中开启 xff0c 同样由于是低开销所以它的功能相比较 KA
  • Linux Phy 驱动解析

    文章目录 1 简介2 phy device2 1 mdio bus2 2 mdio device2 3 mdio driver2 4 poll task2 4 1 自协商配置2 4 2 link 状态读取2 4 3 link 状态通知 3
  • 程序媛工作几年后的感受!体验?

    黑客技术 点击右侧关注 xff0c 了解黑客的世界 xff01 Java开发进阶 点击右侧关注 xff0c 掌握进阶之路 xff01 Python开发 点击右侧关注 xff0c 探讨技术话题 xff01 作者 xff1a hq nuan 来
  • ubuntu 通过 apt-get 安装软件失败时的解决方案

    最近在 vmware上的ubuntu系统下安装 软件时出现安装失败情况 xff0c 在网上搜了一通 xff0c 终于找到了解决方案 遇到的问题和解决方案如下 xff1a 一 apt get install vim二 apt get upda
  • JAVA自学之路 三:要动手

    原创 尚学堂科技 马士兵老师 JAVA自学之路 三 要动手 转载请注明出处 http www bjsxt com zixue zixuezhilu 3 html 无论如何 xff0c 请坚持不懈的动手实验 xff01 学习Java要动手 x
  • Eigen库的安装

    运行命令 xff1a sudo apt get install libeigen3 dev 假设默认安装到 usr local include里 可在终端中输入locate eigen3查看位置 xff0c 若实际中默认安装到了 usr i
  • 搭建自己的简易服务器(公网)

    大部分时候做嵌入式开发的 xff0c 如果是wifi 可以工作在局域网 xff0c 至于物联网设备 xff0c 插手机卡的那种就需要公网ip 测试起来相对比较麻烦 xff0c 电信宽带用户有的可以映射使用 xff0c 但是ip会改变 xff
  • CPP服务器08--http请求响应实现

    http服务设计 对于静态页面服务器来说 xff0c 其工作流程如下 xff1a 接收客户端消息 解析出http请求报文 业务逻辑 xff0c 拼装响应报文 发送给客户端结果 http连接类 设计目标 xff1a 将客户端唯一文件描述符封装
  • Linux C Socket 编程

    以下内容转载自 https www cnblogs com PikapBai p 13964866 html 闪念基因2020 11 20 12 01 20 本文作者 xff1a 她爱喝水 本文链接 xff1a https www cnbl
  • Linux中ROS风格的物理PWM引脚控制,C++代码

    背景 xff1a 拿到一个舵机 xff0c 一个安装了linux和ROS的 小黑盒子 以及一个干干净净啥也不会的脑子 xff0c 然后我从零开始学的 xff0c 总算找到了个能操作舵机的程序 现在只是能跑的状态 xff0c 提供一种思路 x
  • ROS二次开发需要用到的大部分Linux命令

    背景 xff1a 拿到了一架有机载电脑的全部开源的无人机 xff0c 机载电脑安装了ubuntu20 04 xff0c ROS1 xff0c 上面已经在运行了一些程序 我以前只是听过linux xff0c 根本不知道ROS 那么现在需要快速
  • 【技巧】如何为开源社区做贡献

    预计阅读时间 xff1a 6 分钟 Github 这东西怎么用 xff1f 相信有很多人还没有自己操作过 xff0c 这下面给大家推荐一位大佬的文章 xff0c 希望有所帮助 之前有幸参与到一个开源项目中 xff0c 该项目是一个算法知识的
  • MLK | 机器学习采样方法大全

    MLK xff0c 即Machine Learning Knowledge xff0c 本专栏在于对机器学习的重点知识做一次梳理 xff0c 便于日后温习 xff0c 内容主要来自于 百面机器学习 一书 xff0c 结合自己的经验与思考做的
  • python爬虫实战:之爬取京东商城实例教程!(含源代码)

    前言 xff1a 本文主要介绍的是利用python爬取京东商城的方法 xff0c 文中介绍的非常详细 xff0c 下面话不多说了 xff0c 来看看详细的介绍吧 主要工具 scrapyBeautifulSouprequests 分析步骤 1
  • 明面上是个歌手!暗地里是个程序员的明星你只知道许嵩和潘玮柏?

    在5月9日 xff0c 知名演员刘涛在社交平台发文公布 xff1a 已正式入职聚划算成官方优选官了 xff0c 而且还有花名叫刘一刀 xff0c 以后就专职给大家挑好物了 当然 xff0c 刘涛在5 14号已经开始上班了 xff0c 还邀请
  • 如何使用Python实现支付宝在线支付?商家:我人傻了

    windows系统安装Python虚拟环境 首先保证你的系统已经安装好了Python 安装virtualenv C WINDOWS system32 gt pip3 install virtualenv Collecting virtual
  • Mavros Client md5sum Error

    Mavros Client md5sum Error 运行阿木实验室px4 commander包里vio fly sh的 roslaunch px4 command px4 pos estimator launch 时报错 xff1a ER
  • 几行代码实现简单的网络象棋游戏,看看Java大牛是怎么做到的?

    游戏规则 xff1a 1 将 帅 xff1a 不能出田字格 xff0c 不能走斜线 xff0c 只能前进后退向左向右 xff0c 每次只走一格 xff1b 2 士 仕 xff1a 不能出田字格 xff0c 只能走斜线 xff0c 每次只走一