五子棋人机对战java,java五子棋网络对战
做完java单机五子棋,开始尝试写网络五子棋(在局域网,因为没有公开IP)。上次五子棋写的很乱,都是一个班写的。这一次,我使用了面向对象的思想,将特定的函数和属性编写到一个类中。代码分为两部分,客户端和服务器端。客户端用AWT编写,主要由五子棋面板和功能键面板组成。网络使用TCP,通过序列化和反序列化来读写消息。运行时,先运行服务器程序,再运行两个客户端。代码放在文章的末尾。
下面是客户端运行的效果:
下面是代码包的结构:
然后我再依次说说这几个类的作用。
Media包
媒体包:主要包括五子棋的背景图片、播放音乐的类别以及音乐内容。
我是跟室友上的音乐演奏课,所以不太懂。我扫了一眼,是用Applet做的,只能用处理音乐。wav后缀。
Net包
Net:它包含两个类。细心的朋友要注意,客户端没有main方法。客户端实际上包含了与服务器通信的套接字,其中包含了一些读写方法。我在服务器端使用线程池的方法来处理客户端的请求(我对线程池不是很了解,类似于多线程)。
View包
套装:包含四个类,即棋盘,棋盘,棋子和谁查看。
棋盘是一个包含主方法的JFrame,命令面板和棋盘面板都被添加到这个JFrame中。
ChessPanel是一个棋盘面板,完成绘制19*19棋盘线、加载背景图片、不断接收和处理来自服务器的消息(给面板添加棋子)、给面板添加棋子和每次点击后给服务器发送棋子、判断胜负并给出提示消息等任务。
棋子是棋子,包含颜色、棋子半径、棋子位置、命令等属性(与前面的命令面板配合使用,默认为发送)。
谁是五子棋中判断谁胜谁负的那一部分。每一步都需要判断。
播放音乐的类:
包装媒体。音乐;导入Java . io . file;导入Java . io . io exception;导入javax . sound . sampled . audio inputstream;导入javax . sound . sampled . audio system;导入javax . sound . sampled . clip;导入javax . sound . sampled . lineunavailableexception;import javax . sound . sampled . unsupportdaudiofileexception;公开课PlayMusic { private Clip clippublic PlayMusic(String filePath)抛出LineUnavailableException,UnsupportedAudioFileException,io exception { File File=new File(File path);audio inputstream audio inputstream=audio system . getaudioinputstream(file);clip=audio system . get clip();clip . open(audio inputstream);} public void play(){ clip . setframeposition(1);clip . start();} public void loop(){ Clip . loop(Clip。循环_连续);} public void stop(){ clip . stop();}}TcpClient:
包网;导入视图。件;导入Java . io . *;导入Java . net . socket;公共类TcpClient { private Socket socket私有ObjectInputStream ois私有ObjectOutputStream oospublic TcpClient(Socket socket,ObjectInputStream ois,ObjectOutputStream OOS){ this . Socket=Socket;this.ois=ois这
.oos = oos; } public Socket getSocket() { return socket; } public void setSocket(Socket socket) { this.socket = socket; } public ObjectInputStream getOis() { return ois; } public void setOis(ObjectInputStream ois) { this.ois = ois; } public ObjectOutputStream getOos() { return oos; } public void setOos(ObjectOutputStream oos) { this.oos = oos; } public void send(Pieces pieces) throws IOException { oos.writeObject(pieces); System.out.println(socket+"向服务器发送消息"); } public Pieces accept() throws IOException, ClassNotFoundException { Pieces pieces = (Pieces) ois.readObject(); System.out.println(socket+"从服务器读取消息"); return pieces; } public void close(){ ; }}TcpServer:
package net;import view.Pieces;import java.io.*;import java.net.ServerSocket;import java.net.Socket;import java.net.SocketException;import java.util.ArrayList;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class TcpServer { public static void main(String[] args) { // 保存客户端处理的线程 ArrayList<UserThread> userList = new ArrayList<>(); // 固定大小的线程池只支持两个线程,用来处理客户端 ExecutorService es = Executors.newFixedThreadPool(2); try { ServerSocket server = new ServerSocket(10086); System.out.println("服务器已经启动,正在等待客户端连接......"); while (true) { //接收客户端的Socket,如果没有客户端连接就一直卡在这里 Socket socket = server.accept(); // 每来一个用户就创建一个线程 UserThread user = new UserThread(socket, userList); // 开启线程 es.execute(user); } } catch (IOException e) { e.printStackTrace(); } }} class UserThread implements Runnable { private Socket socket = null; private static ArrayList<UserThread> list; // 客户端线程集合 private ObjectOutputStream oos; private ObjectInputStream ois; private boolean flag = true;// 标记 public UserThread(Socket socket, ArrayList<UserThread> list) { this.socket = socket; this.list = list; list.add(this); // 把当前线程加入list中 } @Override public void run() { UserThread user = null; try { System.out.println("客户端:" + socket.getInetAddress().getHostAddress() + "已经连接"); ois = new ObjectInputStream(socket.getInputStream()); oos = new ObjectOutputStream(socket.getOutputStream()); while(true){ Pieces pieces = (Pieces) ois.readObject(); // 客户端发给服务端的消息,把他写到其它套接字中去 int size = list.size(); for (int i = 0; i < size; i++) { user = list.get(i); if (user.socket != socket) { user.oos.writeObject(pieces); System.out.println("从"+socket+"向"+user.socket+"发送消息"); } } } } catch(SocketException e){ // todo 客户端掉线后,移除客户端。没想好{1.从客户端列表移除当前元素,关闭当前:socket,通知另一方:这一方已经掉线,然后关闭这一方的socket} try { int i = list.size(); if (i ==2){ list.remove(user); System.out.println("已经删除了一个客户端"); list.get(0).oos.writeObject(new Pieces("对方掉线")); }else if (i==1){ list.remove(0); System.out.println("又移除了另一个客户端"); } } catch (IOException ex) { ex.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }}
ChessBoard:
/** 1.变量值不变的问题* 2.输入输出流先后顺序的问题(socket阻塞)* 3.socket 短连接不关闭输入输出流,为何看起来就像长连接一样(长短连接的区别是什么)* */// todo 一个提示框package view;import Media.Music.PlayMusic;import javax.sound.sampled.LineUnavailableException;import javax.sound.sampled.UnsupportedAudioFileException;import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.IOException;public class ChessBoard extends JFrame implements ActionListener { private JButton PlayMusic = new JButton("播放音乐"); private ChessPanel chessPanel; private Panel CommandPanel = new Panel(); private JButton reStart = new JButton("重新开始"); private JButton fail = new JButton("认输"); private JButton Regret = new JButton("悔棋"); private String command=null; // 触发按钮后发送的命令 private PlayMusic music = null; private int count = 1; // todo 静态语句块 { try { music = new PlayMusic("./src/Media/Music/bg3.wav"); } catch (LineUnavailableException e) { e.printStackTrace(); } catch (UnsupportedAudioFileException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public ChessBoard() { this.setTitle("欢乐五子棋"); chessPanel = new ChessPanel(); 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); } public static void main(String[] args) { ChessBoard Board = new ChessBoard(); } @Override public void actionPerformed(ActionEvent e) { if(e.getSource()==reStart){ command ="重新开始"; chessPanel.canPlay = true; }else if(e.getSource()==fail){ command ="认输"; JOptionPane.showMessageDialog(chessPanel,"Its a pity,you have fail the game!"); chessPanel.canPlay = false; }else if (e.getSource()==Regret){ command ="悔棋"; }else if (e.getSource()==PlayMusic){ // todo 播放音乐,单数次播放; if (count%2==1){ music.play(); }else { music.stop(); } count++; command = null; } if(command!=null){ Pieces pieces = new Pieces(command); try { this.chessPanel.client.send(pieces); } catch (IOException ex) { ex.printStackTrace(); } } }}
ChessPanel:
package view;// 五子棋面板,就是在这里面画图。// todo 背景图片 ,也许一个背景音乐import net.TcpClient;import javax.swing.*;import java.awt.*;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.ConnectException;import java.net.Socket;import java.util.ArrayList;import java.util.Iterator;public class ChessPanel extends JPanel implements MouseListener{ // TODO 从服务器接收来的棋子 ,值不变有问题// Pieces accept_pieces = new Pieces();// Pieces send_pieces = new Pieces(); whoWin ifWin =new whoWin() ; // 是否胜利 TcpClient client = null; // 客户端 boolean canPlay = true; // 是否能继续玩 boolean isBlack = true; // 是否黑子,黑1,白2 ArrayList<Pieces> allPieces = new ArrayList<>(); // 存储棋子对象,就是通过这个画图的 int [][] allChess = new int[19][19]; int PanelWidth; int PanelHeight; int width = 600; int height = 600; int temp = width / 18; int xbase,ybase; Image image = Toolkit.getDefaultToolkit().getImage("./src/Media/bg.jpeg"); // "./"表示当前项目下 public ChessPanel(){ this.addMouseListener(this); try { Socket socket = new Socket("172.27.29.190", 10086); //TODO 构建输出输入流,输入输出流问题,先输出后输入 ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); client = new TcpClient(socket,ois,oos); new Thread(new getMessage()).start(); // 开启读取的线程 } catch (ConnectException e){ System.out.println("服务器拒绝连接!"); } catch (IOException e) { e.printStackTrace(); }catch(Exception e ){ e.printStackTrace(); } } // 画图部分 public void paintComponent(Graphics g) { super.paintComponent(g); PanelWidth = this.getSize().width; // 这两步骤 PanelHeight = this.getSize().height; xbase = (PanelWidth - width) / 2; ybase = (PanelHeight - height) / 2; Graphics2D g2d = (Graphics2D) g;// this.setBackground(new Color(246, 186, 114)); g2d.drawImage(image,0,0,this.getWidth(),this.getHeight(),this); int x1, y1, x2, y2; // 画线 for (int i = 0; i < 19; i++) { if (i == 0 i == 18) {  
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。