java实现简单网络象棋游戏
本文实例为大家分享了java实现网络象棋游戏的具体代码,供大家参考,具体内容如下
游戏规则:
1.将/帅:不能出田字格,不能走斜线,只能前进后退向左向右,每次只走一格;
2.士/仕:不能出田字格,只能走斜线,每次只走一格;
3.象/相:只能走田字格,中间防止蹩脚,不能有棋;
4.马:只能走日,(这个比较麻烦,且看下图标识)
5.车:车只能走直线,这个很好理解,不细说了;
6.炮:
情况一:纯走路—->中间和目的地都不能有棋
情况二:吃棋—–>中间要有一颗棋,目标也有棋,且是敌方的棋,毕竟不能自己吃自己哈
7.卒/兵:
河这边:只能前进不能后退,不能横着走!!!
河对面:可以前进,可以横着走,不能后退!!!
面板设计
看上去一定很挫!哈哈,别急,听我细细道来!
一般的界面设计我们都知道横纵坐标是这样的:
但是我选择背道而行,不是因为别的,是为了更好的去让初学者理解,我们把原本的x坐标看成数组的列(col),把y坐标看成我们数组的行(row),这样是不是更好理解一点呢,当然了我就是这么理解的,哈哈,接下来的游戏代码编程我们会把横坐标用y*width,纵坐标用x*height你们应该就能理解为什么了,因为x是数组的行,也就是坐标纵坐标(y)的体现,同理数组中的y也是如此。
数据传输:这里我们采用UDP协议来进行通讯,所以你们也要先去了解一下UDP协议的一些基本方法,这里就不细讲了。
通讯协议:这里我们自定义通讯协议啊:
“play|”——–以此开头代表一端发出了游戏邀请,等待另一端的回应;
“connect|”——-以此开头代表另一端收到邀请并且同意建立连接通讯!如果邀请者受到这条消息就代表通讯建立成功,可以开始游戏了;
“move|”——以此开头代表移动数据传输,如果一端移动了棋子,那么另一端也要收到信息,重新绘制界面;
“lose|”——–以此开头代表一方认输,如果有一方认输就会向另一方发送该信息;
“quit|”——-以此开头代表一方退出游戏,任意一方离开都会向对方发送该信息,以提示对方;
“success|”—–以此开头代表胜利,某一方胜利就向对方发出信息,通知对方;
“regret|”——以此开头表示悔棋,这个不用讲了吧,大家都明白,但是本次编程中我没有把这个加进去,这个你们可以自己根据自己需要去添加。
(肯定有人问我这个协议是谁定义的,啊哈哈,让你们失望了,这是我自己定义的,这个通讯协议只适用于你们写的这个代码,和使用这个代码的两个人通讯使用,所以协议如何自己可以定义的哦)
代码实现
1.Chess类:
packageinternet_chess;
importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.Point;
importjava.awt.Toolkit;
importjava.awt.image.ImageObserver;
importjavax.swing.JPanel;
publicclassChess{
publicintRow=12;
publicintCol=11;
publicStringchessName;//当前棋子对象的名字
publicintowner;//当前棋子对象的所有者--黑方还是红方
publicPointpoint;//当前棋子对象的位置
publicImagechessImage;//当前棋子对象的图像
privateintBLACKCHESS=1;
privateintREDCHESS=0;//红方0,黑方1
privateintwidth=40;
privateintheight=40;
publicChess(Stringname,intown,Pointpoint)//获取每一个棋子对象名字,所有者,位置,和图片信息
{
this.chessName=name;
this.owner=own;
this.point=point;
if(owner==BLACKCHESS)//如果所有者是黑方
{
if(chessName.equals("将"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/0.png");
}
elseif(chessName.equals("士"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/1.png");
}
elseif(chessName.equals("象"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/3.png");
}
elseif(chessName.equals("马"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/5.png");
}
elseif(chessName.equals("车"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/7.png");
}
elseif(chessName.equals("炮"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/9.png");
}
elseif(chessName.equals("卒"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/11.png");
}
}
else//如果所有者是红方
{
if(chessName.equals("帅"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/16.png");
}
elseif(chessName.equals("仕"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/17.png");
}
elseif(chessName.equals("相"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/19.png");
}
elseif(chessName.equals("马"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/21.png");
}
elseif(chessName.equals("车"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/23.png");
}
elseif(chessName.equals("炮"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/25.png");
}
elseif(chessName.equals("兵"))
{
chessImage=Toolkit.getDefaultToolkit().getImage("F:/Image/chess/27.png");
}
}
}
protectedvoidpaint(Graphicsg,JPaneli)//画棋子
{
g.drawImage(chessImage,point.y*width-width/2,point.x*height-height/2,width,height,(ImageObserver)i);
}
protectedvoidpaintSeclected(Graphicsg)//画鼠标选择了以后的棋子对象的边框
{
g.drawRect(point.y*width-width/2,point.x*height-height/2,width,height);
}
publicvoidSetPos(intx,inty)//重新设置移动以后的棋子对象的位置坐标
{
point.x=x;
point.y=y;
}
publicvoidReversePos()//将该对象的位置坐标逆置输出,用于方便显示信息情况
{
point.x=Row-1-point.x;
point.y=Col-1-point.y;
}
}
2.ChessPanel类:
packageinternet_chess;
importjava.awt.Color;
importjava.awt.Font;
importjava.awt.Graphics;
importjava.awt.Point;
importjava.awt.event.MouseAdapter;
importjava.awt.event.MouseEvent;
importjava.io.IOException;
importjava.net.DatagramPacket;
importjava.net.DatagramSocket;
importjava.net.InetAddress;
importjava.net.SocketException;
importjava.net.UnknownHostException;
importjavax.swing.JOptionPane;
importjavax.swing.JPanel;
publicclassChessPanelextendsJPanelimplementsRunnable{
privateintBLACKCHESS=1;
privateintREDCHESS=0;//黑棋是1,红旗是0
publicChesschess[]=newChess[32];//创建了32个棋子对象
privateintwidth=40;
privateintheight=40;
publicintRow=12;
publicintCol=11;//11行10列
publicintmap[][]=newint[Row][Col];
publicintplayer;//设置当前玩家对象
privatebooleanisFirst=false;//判断是否是第一次点击的棋子,以此分开两次点击棋子的碰撞矛盾
privateintx1,y1,x2,y2;//用来保存第一次第二次选中的坐标的
privatebooleanflag=true;//用来控制线程的运行
privatebooleanisPlay=false;
privateChessfirstChess=null;
privateChesssecondChess=null;//设置第一次点击的棋子和第二次选中的棋子对象
privateInetAddressmyID;//自己id地址
privateInetAddressyouID;//目标ID地址
privateintsendport;//发送端口
privateintreceiveport=8888;//接收端口
publicChessPanel()//构造函数
{
init_map();//初始化棋盘
//给这个面板添加鼠标监听机制
this.addMouseListener(newMouseAdapter()
{
publicvoidmouseClicked(MouseEvente)
{
if(isPlay==true)//判断是否该本方下棋
{
SelectChess(e.getPoint());//选择要移动的棋子
repaint();
}
}
publicvoidSelectChess(Pointpos)
{
intx=pos.x;
inty=pos.y;//获取此时此刻鼠标点击的位置坐标
System.out.println("选择要移动的棋子坐标:x->"+x+"y->"+y);
if(x>0&&x<(Col-1)*width&&y>0&&y<(Row-1)*height)//判断鼠标是否在合理的范围,不在就直接退出
{
Pointpoint=ReSetID(x,y);
if(isFirst)//判断是否是第一次选中的棋子
{
x1=point.x;
y1=point.y;
//判断第一次选中的棋子是不是自己的棋子或者是不是无效棋子,不是就失败
intid=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;
intid=map[x2][y2];
if(id!=-1&&chess[id].owner!=player)//第二次选择了敌方棋子,将敌方棋子保存起来
{
isFirst=true;
secondChess=chess[id];
//开始判断是否可以移动棋子,如果可以就将棋子移动,并发信息给对方我们已经移动的棋子信息
//判断是否可以移动棋子
if(IsMoveChess(firstChess,x2,y2))//可以移动-吃棋
{
intidx1=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;
}
elseif(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;
}
}
elseif(id!=-1&&chess[id].owner==player)//第二次又选择了自己的棋子,那么就将第二次选择的棋子当做第一次选择的棋子
{
firstChess=chess[id];
x1=x2;
y1=y2;
isFirst=false;
}
else//第二次选择的棋子是空,那么就是单纯的移动棋子
{
secondChess=null;
if(IsMoveChess(firstChess,x2,y2))//可以移动-吃棋
{
intidx1=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;
}
}
}
}
}
});
}
publicbooleanIsMoveChess(Chesschess,intx,inty)//判断是否可以移动棋子----移动棋子的规则
{
if(chess.chessName.equals("将")||chess.chessName.equals("帅"))//只能走一步
{
intx0=chess.point.x;
inty0=chess.point.y;
if(x>=8&&x<=10&&y>=4&&y<=6)
{
//intx0=chess.point.x;
//inty0=chess.point.y;
if(Math.abs(x-x0)>1||Math.abs(y-y0)>1)
returnfalse;
elseif(Math.abs(x-x0)*Math.abs(y-y0)!=0)//不能走斜线
returnfalse;
else
returntrue;
}
if(this.chess[map[x][y]].chessName.equals("将")||this.chess[map[x][y]].chessName.equals("帅")&&(y0==y))//判断两个将领之间吃棋
{
intmin=xx0?x:x0;
for(min=min+1;min=8&&x<=10&&y>=4&&y<=6)
{
intx0=chess.point.x;
inty0=chess.point.y;
if(Math.abs(x-x0)*Math.abs(y-y0)!=1)
{
returnfalse;
}
else
returntrue;
}
else//越界
returnfalse;
}
elseif(chess.chessName.equals("象")||chess.chessName.equals("相"))//相走田字,且不能过河
{
if(x>=6&&x!=11&&y>=1&&y<=9)
{
intx0=chess.point.x;
inty0=chess.point.y;
if(Math.abs(x-x0)*Math.abs(y-y0)!=4)
{
returnfalse;
}
elseif(Math.abs(x-x0)==2&&Math.abs(y-y0)==2)
{
intxm,ym;//求取中间值,防止中间有值不能走棋
xm=x>x0?x-1:x0-1;
ym=y>y0?y-1:y0-1;
if(map[xm][ym]!=-1)//表示中间有棋
returnfalse;
returntrue;
}
else//防止1*4==4的情况出现
returnfalse;
}
else
returnfalse;
}
elseif(chess.chessName.equals("马"))//马走日,防止蹩脚的情况出现
{
if(x>=1&&x<=10&&y>=1&&y<=9)
{
intx0=chess.point.x;
inty0=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&&yx0)//下边
{
returnfalse;
}
returntrue;
}
}
else
returnfalse;
}
else
returnfalse;
}
elseif(chess.chessName.equals("车"))//车走直线
{
if(x>=1&&x<=10&&y>=1&&y<=9)
{
intx0=chess.point.x;
inty0=chess.point.y;
if(x==x0)//水平移动
{
inti=yy0?y:y0;
for(i=i+1;ix0?x:x0;
for(i=i+1;i=1&&x<=10&&y>=1&&y<=9)
{
intx0=chess.point.x;
inty0=chess.point.y;
intcountx=0;
intcounty=0;
if(x==x0)//水平移动
{
inti=yy0?y:y0;
for(i=i+1;ix0?x:x0;
for(i=i+1;i=1&&y>=1&&y<=9)
{
intx0=chess.point.x;
inty0=chess.point.y;
if(x==x0&&Math.abs(y-y0)==1)//横向只走一步,判断是否在河的这边还是那边
{
//如果是河的这边就不能走横向
if(x==6)
returnfalse;
else
returntrue;
}
if(y==y0&&x-x0==-1)//纵向只走一步,且必须向前走
{
returntrue;
}
returnfalse;
}
else
returnfalse;
}
returnfalse;
}
publicPointReSetID(intx,inty)//重置id,将id转化成可辨识的坐标信息
{
intposx=(y+height/2)/height;
intposy=(x+width/2)/width;
returnnewPoint(posx,posy);
}
publicvoidinit_map()//初始化棋盘
{
for(inti=0;i"+indx);
intposx=Integer.parseInt(s[2]);
System.out.println("posx->"+posx);
intposy=Integer.parseInt(s[3]);
System.out.println("posy->"+posy);
intx=chess[indx].point.x;
inty=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;
}
elseif(s[0].equals("quit"))//对方退出
{
JOptionPane.showConfirmDialog(null,"提示","对方离开,游戏结束!",JOptionPane.OK_OPTION);
isPlay=false;
flag=false;//退出线程
}
}
}catch(SocketExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}finally
{
if(sock!=null)
{
sock.close();
}
}
}
}
3.ChessFrame类:
packageinternet_chess;
importjava.awt.BorderLayout;
importjava.awt.Container;
importjava.awt.Dimension;
importjava.awt.FlowLayout;
importjava.awt.Rectangle;
importjava.awt.event.MouseAdapter;
importjava.awt.event.MouseEvent;
importjava.net.InetAddress;
importjava.net.UnknownHostException;
importjavax.swing.ImageIcon;
importjavax.swing.JButton;
importjavax.swing.JFrame;
importjavax.swing.JLabel;
importjavax.swing.JPanel;
importjavax.swing.JTextField;
publicclassChessFrameextendsJFrame{
privateJButtonstart=newJButton("开始");
privateJButtonend=newJButton("结束");
privateJButtonlose=newJButton("认输");
privateJPanelpaneUp=newJPanel();
privateChessPanelchesspanel=newChessPanel();
privateJPanelpaneDown=newJPanel();
privateJLabelIPlabel=newJLabel("IP:");
privateJLabelotherPortlabel=newJLabel("目标端口");
privateJLabelimageicon=newJLabel();
privateJTextFieldip_address=newJTextField("127.0.0.1");
privateJTextFieldotherPort=newJTextField("9999");
privateInetAddressmyID;//自己id地址
privateInetAddressyouID;//目标ID地址
privateintsendport;//发送端口
privateintreceiveport=8888;//接收端口
publicChessFrame()//构造函数
{
paneDown.setLayout(newFlowLayout());
IPlabel.setBounds(10,10,40,20);
ip_address.setBounds(newRectangle(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(newRectangle(300,0,100,100));
imageicon.setIcon(newImageIcon("F:/Image/chess/0.png"));//标签加载图片
paneUp.add(imageicon,BorderLayout.CENTER);
Containercon=this.getContentPane();
con.add(paneUp,BorderLayout.NORTH);
con.add(chesspanel,BorderLayout.CENTER);
con.add(paneDown,BorderLayout.SOUTH);
this.setTitle("8888网络象棋");
this.setSize(newDimension(600,700));
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
start.addMouseListener(newMouseAdapter()
{
publicvoidmouseClicked(MouseEvente)
{
try{
Stringip=ip_address.getText();//获取当前目标ip地址
sendport=Integer.parseInt(otherPort.getText());//获取目标连接端口
myID=InetAddress.getLocalHost();//获取本地ip地址
youID=InetAddress.getByName(ip);//获取目标ip地址
}catch(UnknownHostExceptione1){
e1.printStackTrace();
}
chesspanel.startgame(youID,sendport,receiveport);
lose.setEnabled(true);
}
});
end.addMouseListener(newMouseAdapter()
{
publicvoidmouseClicked(MouseEvente)
{
try{
chesspanel.send("quit|",youID,sendport);//向对方发送离开信息,同时断开连接
System.exit(0);
}catch(Exceptionex)
{
ex.printStackTrace();
}
}
});
lose.addMouseListener(newMouseAdapter()
{
publicvoidmouseClicked(MouseEvente)
{
try{
chesspanel.send("lose|",youID,sendport);//向对方发送认输信息
}catch(Exceptionex)
{
ex.printStackTrace();
}
}
});
//加一个对方求和的按钮
}
publicstaticvoidmain(String[]args){
//TODOAuto-generatedmethodstub
newChessFrame();
}
}
代码结果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。