java如何实现联机五子棋(java,开发技术)

时间:2024-05-03 06:58:53 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

下面是客户端运行的效果:

java如何实现联机五子棋

这里是代码包的结构:

java如何实现联机五子棋

接着我来依次说下这些类所完成的功能

Media包

Media包:主要是放了五子棋的背景图片和播放音乐的类以及音乐内容

播放音乐这个类是我从室友那拿的,所以我也不是很懂,瞄了一眼是用Applet完成的,只能处理.wav后缀的音乐

Net包

Net包:包含两个类,细心的小伙伴应该注意到客户端是没有主方法的。客户端中其实是包含与服务端进行通信的socket的,其中包含一些读和写的方法。服务端我采用的是线程池的方法来处理客户端的请求(线程池这部分我也不是特别了解,用起来和多线程感觉差不多)。

View包

View包:包含四个类,分别是ChessBoard,ChessPanel,Pieces和WhoWin 类

ChessBoard是一个包含Main方法的JFrame,命令面板和棋盘面板都是添加到这个JFrame中的。

ChessPanel是一个棋盘面板,里面完成了如:画19*19的棋盘线条,加载背景图片,不停的接收来自服务端的消息并处理(把棋子加到面板),处理每次点击后添加棋子到面板并发送棋子到服务器,判断胜负并且给出提示消息。

Pieces是一个棋子,其中有包含如颜色,棋子半径,棋子位置和命令(和前面的命令面板配合使用,默认是发送)等属性。

WhoWin就是五子棋中判断谁输谁赢的部分。每下一步就需要判断。

播放音乐的类:

packageMedia.Music;importjava.io.File;importjava.io.IOException;importjavax.sound.sampled.AudioInputStream;importjavax.sound.sampled.AudioSystem;importjavax.sound.sampled.Clip;importjavax.sound.sampled.LineUnavailableException;importjavax.sound.sampled.UnsupportedAudioFileException;publicclassPlayMusic{privateClipclip;publicPlayMusic(StringfilePath)throwsLineUnavailableException,UnsupportedAudioFileException,IOException{Filefile=newFile(filePath);AudioInputStreamaudioInputStream=AudioSystem.getAudioInputStream(file);clip=AudioSystem.getClip();clip.open(audioInputStream);}publicvoidplay(){clip.setFramePosition(1);clip.start();}publicvoidloop(){clip.loop(Clip.LOOP_CONTINUOUSLY);}publicvoidstop(){clip.stop();}}

TcpClient:

packagenet;importview.Pieces;importjava.io.*;importjava.net.Socket;publicclassTcpClient{privateSocketsocket;privateObjectInputStreamois;privateObjectOutputStreamoos;publicTcpClient(Socketsocket,ObjectInputStreamois,ObjectOutputStreamoos){this.socket=socket;this.ois=ois;this.oos=oos;}publicSocketgetSocket(){returnsocket;}publicvoidsetSocket(Socketsocket){this.socket=socket;}publicObjectInputStreamgetOis(){returnois;}publicvoidsetOis(ObjectInputStreamois){this.ois=ois;}publicObjectOutputStreamgetOos(){returnoos;}publicvoidsetOos(ObjectOutputStreamoos){this.oos=oos;}publicvoidsend(Piecespieces)throwsIOException{oos.writeObject(pieces);System.out.println(socket+"向服务器发送消息");}publicPiecesaccept()throwsIOException,ClassNotFoundException{Piecespieces=(Pieces)ois.readObject();System.out.println(socket+"从服务器读取消息");returnpieces;}publicvoidclose(){;}}

TcpServer:

packagenet;importview.Pieces;importjava.io.*;importjava.net.ServerSocket;importjava.net.Socket;importjava.net.SocketException;importjava.util.ArrayList;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclassTcpServer{publicstaticvoidmain(String[]args){//保存客户端处理的线程ArrayList<UserThread>userList=newArrayList<>();//固定大小的线程池只支持两个线程,用来处理客户端ExecutorServicees=Executors.newFixedThreadPool(2);try{ServerSocketserver=newServerSocket(10086);System.out.println("服务器已经启动,正在等待客户端连接......");while(true){//接收客户端的Socket,如果没有客户端连接就一直卡在这里Socketsocket=server.accept();//每来一个用户就创建一个线程UserThreaduser=newUserThread(socket,userList);//开启线程es.execute(user);}}catch(IOExceptione){e.printStackTrace();}}}classUserThreadimplementsRunnable{privateSocketsocket=null;privatestaticArrayList<UserThread>list;//客户端线程集合privateObjectOutputStreamoos;privateObjectInputStreamois;privatebooleanflag=true;//标记publicUserThread(Socketsocket,ArrayList<UserThread>list){this.socket=socket;this.list=list;list.add(this);//把当前线程加入list中}@Overridepublicvoidrun(){UserThreaduser=null;try{System.out.println("客户端:"+socket.getInetAddress().getHostAddress()+"已经连接");ois=newObjectInputStream(socket.getInputStream());oos=newObjectOutputStream(socket.getOutputStream());while(true){Piecespieces=(Pieces)ois.readObject();//客户端发给服务端的消息,把他写到其它套接字中去intsize=list.size();for(inti=0;i<size;i++){user=list.get(i);if(user.socket!=socket){user.oos.writeObject(pieces);System.out.println("从"+socket+"向"+user.socket+"发送消息");}}}}catch(SocketExceptione){//todo客户端掉线后,移除客户端。没想好{1.从客户端列表移除当前元素,关闭当前:socket,通知另一方:这一方已经掉线,然后关闭这一方的socket}try{inti=list.size();if(i==2){list.remove(user);System.out.println("已经删除了一个客户端");list.get(0).oos.writeObject(newPieces("对方掉线"));}elseif(i==1){list.remove(0);System.out.println("又移除了另一个客户端");}}catch(IOExceptionex){ex.printStackTrace();}}catch(IOExceptione){e.printStackTrace();}catch(ClassNotFoundExceptione){e.printStackTrace();}}}

ChessBoard:

/**1.变量值不变的问题*2.输入输出流先后顺序的问题(socket阻塞)*3.socket短连接不关闭输入输出流,为何看起来就像长连接一样(长短连接的区别是什么)**///todo一个提示框packageview;importMedia.Music.PlayMusic;importjavax.sound.sampled.LineUnavailableException;importjavax.sound.sampled.UnsupportedAudioFileException;importjavax.swing.*;importjava.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.io.IOException;publicclassChessBoardextendsJFrameimplementsActionListener{privateJButtonPlayMusic=newJButton("播放音乐");privateChessPanelchessPanel;privatePanelCommandPanel=newPanel();privateJButtonreStart=newJButton("重新开始");privateJButtonfail=newJButton("认输");privateJButtonRegret=newJButton("悔棋");privateStringcommand=null;//触发按钮后发送的命令privatePlayMusicmusic=null;privateintcount=1;//todo静态语句块{try{music=newPlayMusic("./src/Media/Music/bg3.wav");}catch(LineUnavailableExceptione){e.printStackTrace();}catch(UnsupportedAudioFileExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}}publicChessBoard(){this.setTitle("欢乐五子棋");chessPanel=newChessPanel();this.add(chessPanel,BorderLayout.CENTER);reStart.addActionListener(this);fail.addActionListener(this);Regret.addActionListener(this);PlayMusic.addActionListener(this);CommandPanel.add(reStart);CommandPanel.add(fail);CommandPanel.add(Regret);CommandPanel.add(PlayMusic);this.add(CommandPanel,BorderLayout.SOUTH);this.setBounds(10,10,800,800);this.setVisible(true);this.setResizable(false);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}publicstaticvoidmain(String[]args){ChessBoardBoard=newChessBoard();}@OverridepublicvoidactionPerformed(ActionEvente){if(e.getSource()==reStart){command="重新开始";chessPanel.canPlay=true;}elseif(e.getSource()==fail){command="认输";JOptionPane.showMessageDialog(chessPanel,"It'sapity,youhavefailthegame!");chessPanel.canPlay=false;}elseif(e.getSource()==Regret){command="悔棋";}elseif(e.getSource()==PlayMusic){//todo播放音乐,单数次播放;if(count%2==1){music.play();}else{music.stop();}count++;command=null;}if(command!=null){Piecespieces=newPieces(command);try{this.chessPanel.client.send(pieces);}catch(IOExceptionex){ex.printStackTrace();}}}}

ChessPanel:

packageview;//五子棋面板,就是在这里面画图。//todo背景图片,也许一个背景音乐importnet.TcpClient;importjavax.swing.*;importjava.awt.*;importjava.awt.event.MouseEvent;importjava.awt.event.MouseListener;importjava.io.IOException;importjava.io.ObjectInputStream;importjava.io.ObjectOutputStream;importjava.net.ConnectException;importjava.net.Socket;importjava.util.ArrayList;importjava.util.Iterator;publicclassChessPanelextendsJPanelimplementsMouseListener{//TODO从服务器接收来的棋子,值不变有问题//Piecesaccept_pieces=newPieces();//Piecessend_pieces=newPieces();whoWinifWin=newwhoWin();//是否胜利TcpClientclient=null;//客户端booleancanPlay=true;//是否能继续玩booleanisBlack=true;//是否黑子,黑1,白2ArrayList<Pieces>allPieces=newArrayList<>();//存储棋子对象,就是通过这个画图的int[][]allChess=newint[19][19];intPanelWidth;intPanelHeight;intwidth=600;intheight=600;inttemp=width/18;intxbase,ybase;Imageimage=Toolkit.getDefaultToolkit().getImage("./src/Media/bg.jpeg");//"./"表示当前项目下publicChessPanel(){this.addMouseListener(this);try{Socketsocket=newSocket("172.27.29.190",10086);//TODO构建输出输入流,输入输出流问题,先输出后输入ObjectOutputStreamoos=newObjectOutputStream(socket.getOutputStream());ObjectInputStreamois=newObjectInputStream(socket.getInputStream());client=newTcpClient(socket,ois,oos);newThread(newgetMessage()).start();//开启读取的线程}catch(ConnectExceptione){System.out.println("服务器拒绝连接!");}catch(IOExceptione){e.printStackTrace();}catch(Exceptione){e.printStackTrace();}}//画图部分publicvoidpaintComponent(Graphicsg){super.paintComponent(g);PanelWidth=this.getSize().width;//这两步骤PanelHeight=this.getSize().height;xbase=(PanelWidth-width)/2;ybase=(PanelHeight-height)/2;Graphics2Dg2d=(Graphics2D)g;//this.setBackground(newColor(246,186,114));g2d.drawImage(image,0,0,this.getWidth(),this.getHeight(),this);intx1,y1,x2,y2;//画线for(inti=0;i<19;i++){if(i==0||i==18){g2d.setStroke(newBasicStroke(3.0f));}elseg2d.setStroke(newBasicStroke(1.0f));x1=xbase+temp*i;y1=ybase;y2=ybase+18*temp;g2d.drawLine(x1,y1,x1,y2);x1=xbase;y1=ybase+temp*i;x2=xbase+temp*18;g2d.drawLine(x1,y1,x2,y1);}//开始画棋子intradius;intxPos,yPos;Iteratorit=allPieces.iterator();//迭代器遍历arraylistwhile(it.hasNext()){Piecespieces=(Pieces)it.next();radius=pieces.getRadius();xPos=pieces.getxPos();yPos=pieces.getyPos();System.out.println(pieces.getColor()+","+pieces.getxPos()+","+pieces.getyPos());if(pieces.getColor()==1){g2d.setColor(Color.black);g2d.fillOval(xPos*temp+xbase-radius/2,yPos*temp+ybase-radius/2,radius,radius);}elseif(pieces.getColor()==2){g2d.setColor(Color.white);g2d.fillOval(xPos*temp+xbase-radius/2,yPos*temp+ybase-radius/2,radius,radius);}}}@OverridepublicvoidmousePressed(MouseEvente){intx,y;if(canPlay){x=e.getX();y=e.getY();//判断鼠标点击位置if(x>=xbase&x<=(xbase+18*temp)&y>=ybase&y<(ybase+18*temp)){//判断是不是下在空的位置inttempX=(x-xbase)/temp,tempY=(y-ybase)/temp;//todo这里是关键判断这点坐标的数组下标是什么if((x-xbase)%temp>temp/2){x=tempX+1;}elsex=tempX;if((y-ybase)%temp>temp/2)y=tempY+1;elsey=tempY;//先判断有没有棋子,处理没有棋子的情况if(allChess[x][y]!=0){JOptionPane.showMessageDialog(this,"这里有棋子了");}else{Piecessend_pieces=newPieces();send_pieces.setxPos(x);send_pieces.setyPos(y);if(isBlack){send_pieces.setColor(1);allChess[x][y]=1;isBlack=false;}else{send_pieces.setColor(2);allChess[x][y]=2;isBlack=true;}allPieces.add(send_pieces);//向棋子队列加入当前棋子canPlay=false;//canPlay在true情况下,点击一次后不能点击了this.repaint();ifWin=newwhoWin(allChess,x,y);//如果赢了,就不能玩了,并且给出提示消息,你赢了;if(ifWin.isWin()){canPlay=false;JOptionPane.showMessageDialog(this,"Congratulationsyouhavewonthagame!");}try{if(client!=null){client.send(send_pieces);}}catch(IOExceptionex){ex.printStackTrace();}}}}}//读取来自服务器端的信息classgetMessageimplementsRunnable{privatebooleanflag=true;publicvoidsetFlag(booleanflag){this.flag=flag;}@Overridepublicvoidrun(){//循环读while(flag){if(client!=null){try{Piecesaccept_pieces=client.accept();Stringcommand=accept_pieces.getCommand();intcolor=accept_pieces.getColor();switch(command){case"发送":{canPlay=true;if(color==1){isBlack=false;//对方为黑我为白}else{isBlack=true;}allPieces.add(accept_pieces);allChess[accept_pieces.getxPos()][accept_pieces.getyPos()]=accept_pieces.getColor();ChessPanel.this.repaint();ifWin.setY(accept_pieces.getyPos());ifWin.setX(accept_pieces.getxPos());ifWin.setAllChess(allChess);if(ifWin.isWin()){canPlay=false;JOptionPane.showMessageDialog(ChessPanel.this,"It'sapityyouhavefailthegame!");}break;}case"悔棋":{inti=JOptionPane.showConfirmDialog(ChessPanel.this,"对方请求悔棋,是否同意!");//yes0,no1,cancel2,closed-1Piecespieces=newPieces();if(i==0){//同意悔棋:1.同意对方悔棋pieces.setCommand("同意悔棋");//arraylist去除末尾的两个值,对应allChess置0intsize=allPieces.size();for(intj=1;j<=2;j++){allChess[allPieces.get(size-j).getxPos()][allPieces.get(size-j).getyPos()]=0;allPieces.remove(size-j);}ChessPanel.this.repaint();}elseif(i==1){pieces.setCommand("不同意悔棋");}client.send(pieces);break;}case"认输":{//不能继续玩下去,你已经胜利JOptionPane.showMessageDialog(ChessPanel.this,"对方认输");canPlay=false;JOptionPane.showMessageDialog(ChessPanel.this,"Congratulationsyouhavewonthagame!");break;}case"重新开始":{//是否同意重新开始inti=JOptionPane.showConfirmDialog(ChessPanel.this,"对方请求重新开始,是否同意");Piecespieces=newPieces();if(i==0){//allChess和allPieces全部置0;pieces.setCommand("同意重新开始");intsize=allPieces.size();System.out.println("arraylist长度:"+size);for(intj=0;j<size;j++){//移除队首元素allChess[allPieces.get(0).getxPos()][allPieces.get(0).getyPos()]=0;allPieces.remove(0);}canPlay=true;ChessPanel.this.repaint();}elseif(i==1){pieces.setCommand("不同意重新开始");}client.send(pieces);break;}case"同意悔棋":{//allpieces和allchess回退JOptionPane.showMessageDialog(ChessPanel.this,"对方同意悔棋");intsize=allPieces.size();for(intj=1;j<=2;j++){allChess[allPieces.get(size-j).getxPos()][allPieces.get(size-j).getyPos()]=0;allPieces.remove(size-j);}ChessPanel.this.repaint();break;}case"不同意悔棋":{JOptionPane.showMessageDialog(ChessPanel.this,"对方不同意悔棋");break;}case"同意重新开始":{//全部置0,调用repaint方法JOptionPane.showMessageDialog(ChessPanel.this,"对方同意重新开始");intsize=allPieces.size();for(intj=0;j<size;j++){//todo移除队首元素arraylist长度改变;序列也发生改变allChess[allPieces.get(0).getxPos()][allPieces.get(0).getyPos()]=0;allPieces.remove(0);}canPlay=true;ChessPanel.this.repaint();break;}case"不同意重新开始":{JOptionPane.showMessageDialog(ChessPanel.this,"对方不同意重新开始");break;}case"对方掉线":{//对方已经掉线JOptionPane.showMessageDialog(ChessPanel.this,"不好意思,对方已经掉线!");canPlay=false;break;}}}catch(IOExceptione){e.printStackTrace();}catch(ClassNotFoundExceptione){e.printStackTrace();}}}}}@OverridepublicvoidmouseClicked(MouseEvente){}@OverridepublicvoidmouseReleased(MouseEvente){}@OverridepublicvoidmouseEntered(MouseEvente){}@OverridepublicvoidmouseExited(MouseEvente){}}

Pieces:

packageview;importjava.io.Serializable;//存储棋子的相关信息publicclassPiecesimplementsSerializable{privateintradius=16;privateintcolor=0;privateintxPos;privateintyPos;privateStringcommand="发送";publicStringgetCommand(){returncommand;}publicvoidsetCommand(Stringcommand){this.command=command;}publicPieces(intcolor,intxPos,intyPos){this.color=color;this.xPos=xPos;this.yPos=yPos;}publicPieces(){}publicPieces(Stringcommand){this.command=command;}publicintgetRadius(){returnradius;}publicvoidsetRadius(intradius){this.radius=radius;}publicintgetColor(){returncolor;}publicvoidsetColor(intcolor){this.color=color;}publicintgetxPos(){returnxPos;}publicvoidsetxPos(intxPos){this.xPos=xPos;}publicintgetyPos(){returnyPos;}publicvoidsetyPos(intyPos){this.yPos=yPos;}}

WhoWin:

packageview;publicclasswhoWin{//判断是谁赢了privateintallChess[][]=newint[19][19];privateintx=0;privateinty=0;publicwhoWin(){}publicwhoWin(intallChess[][],intx,inty){this.allChess=allChess;this.x=x;this.y=y;}publicvoidsetAllChess(intallChess[][]){this.allChess=allChess;}publicvoidsetX(intx){this.x=x;}publicvoidsetY(inty){this.y=y;}publicbooleanisWin(){intcolor=allChess[x][y];intcount;count=this.Count(1,0,color);//对横方向的判断if(count>=5){returntrue;}else{count=this.Count(0,1,color);//对竖方向的判断if(count>=5){returntrue;}else{count=this.Count(1,1,color);//对左上方向的判断if(count>=5)returntrue;else{count=this.Count(1,-1,color);//对右上方向的判断if(count>=5)returntrue;}}}returnfalse;}privateintCount(intxChange,intyChange,intcolor){intcount=1;inttempX=xChange,tempY=yChange;while(color==allChess[x+xChange][y+yChange]){count++;if(xChange!=0){xChange++;}if(yChange!=0){if(yChange>0)yChange++;elseyChange--;}}xChange=tempX;yChange=tempY;while(color==allChess[x-xChange][y-yChange]){count++;if(xChange!=0)xChange++;if(yChange!=0){if(yChange>0)yChange++;elseyChange--;}}returncount;}}
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:java如何实现联机五子棋的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:ASP.NET WebAPI怎么导出CSV下一篇:

25 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18