Java小程序之你画我猜

    xiaoxiao2021-03-26  18

    Java小程序之你画我猜 一、前言: 你画我猜是一款休闲益智的游戏,可以考验双方的默契,当然,画功也是一个方面;昨天我们写了个简单的网络画板,能够将一个客户端上画的图形实时传递给另一个客户端;其实 你画我猜也是基于同样的原理将图形进行传递,但是,你画我猜还需要能够进行通信,即某一客户端能够输入猜的信息,并在画的客户端显示出来,当猜对的时候,会有提示信息; 二、项目简要分析: 该项目主要利用我们前面那学习的Java网络画板的知识进行图形的实时传递,然后,利用Java通信,能够使两个客户端进行交互(一个使画的客户端,一个是猜的客户端);这个项目综合了前面的高级画板、网络画板和Java通信项目的知识;同时,为了随机显示要猜的一条记录,我们利用文件的相关操作进行模拟数据库的过程; 三、项目思路整理: 模块1:首先完成利用文件将记录进行保存,模拟数据库的功能; 模块2:完成画的客户端的猜和画的客户端的界面; 模块3:完成服务器端和客户端的交互; 四、项目源代码: Util包:(这里只用到Util包下的MyDataBase类,其他两个类是为了扩展登录界面的校验的) package Util; import java.util.ArrayList; import java.util.Random; public class MyDataBase { //随机产生数 private static Random r = new Random(); //猜的数据库,装要猜的信息 private static ArrayList<String> list = new ArrayList<String>(); //数据库 static{ list.add("乌龟#一种爬行动物,两个字"); list.add("梨子#一种水果,两个字"); list.add("胡萝卜#一种蔬菜,三个字"); list.add("菜鸟#一种动物,两个字"); list.add("大树#一种植物,两个字"); list.add("猪#一种动物,一个字"); list.add("葡萄#一种水果,两个字"); list.add("辣条#一种食品,两个字"); list.add("苹果#一种水果,两个字"); list.add("蜜蜂#一种动物,两个字"); list.add("岑祚江#一条大河,三个字"); list.add("华信教育#教育机构,四个字"); list.add("程序员#一种职业,三个字"); list.add("笔记本电脑#一种电子设备,五个字"); list.add("鼠标#配件,两个字"); list.add("三只松鼠#零食品牌,四个字"); list.add("马拉松#一项运动名称,三个字"); list.add("跳远#一项运动,两个字"); list.add("兔子#一种动物,两个字"); list.add("凤凰#一种鸟类,两个字"); } //随机从数据库中获取一条消息 public String getInfo() { int i=r.nextInt(list.size()); System.out.println("suijishu wei "+i); return list.get(i); } } com.huaxin.server包: package com.huaxin.server; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import Util.MyDataBase; public class Myserver { //线程容器 public static ArrayList<ServerThread> list =new ArrayList<ServerThread>(); //从数据库中获取猜的信息 public static String []infos; public void initServer() { try { //创建服务器对象 ServerSocket server=new ServerSocket(9090); System.out.println("服务器已经启动......."); while(true){ //循环接收客户端的连入 Socket socket=server.accept(); System.out.println("客户端已连入......"); //创建一个新的线程处理 ServerThread st = new ServerThread(socket); list.add(st); //当有两个客户端连入进来时,开始游戏 if(list.size()==2){ MyDataBase db = new MyDataBase(); //从数据库中获取一条记录 String guessinfo=db.getInfo(); infos=guessinfo.split("#"); //第一个连入的是画 list.get(0).name="draw"; //第二个连入进来的是猜 list.get(1).name="guess"; //第三个连入进来的是猜 // list.get(2).name="guess"; list.get(0).start(); list.get(1).start(); // list.get(2).start(); System.out.println("启动线程......"); } } } catch (IOException e) { e.printStackTrace(); } } } package com.huaxin.server; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import Util.MyDataBase; public class ServerThread extends Thread { public Socket socket; //线程名字 public String name; //输入输出流 public DataInputStream dis; public DataOutputStream dos; public ServerThread(Socket socket) { this.socket = socket; } public void run() { try { //获取输入输出流 InputStream ins=socket.getInputStream(); OutputStream ous =socket.getOutputStream(); //开启线程以后,从数据库中取一条消息 dis =new DataInputStream(ins); dos = new DataOutputStream(ous); //如果是画的客户端 if("draw".equals(name)){ //发送画的消息给客户端 sendMsg(socket.getOutputStream(), "draw"); // System.out.println("已发送draw"); //发送要画的信息给画的客户端 dos.writeUTF( Myserver.infos[0]); //循环收客户端画的消息 while(true){ int x1=dis.readInt(); int y1=dis.readInt(); int x2=dis.readInt(); int y2=dis.readInt(); int color =dis.readInt(); int width=dis.readInt(); //将该信息转发给猜的客户端 for (int i = 0; i <Myserver.list.size(); i++) { ServerThread st =Myserver.list.get(i); if(st!=this){ //发送头部数据信息 sendMsg(st.socket.getOutputStream(), "data"); //发送坐标信息 sendMsg1(st.socket.getOutputStream(), x1, y1, x2, y2,color,width); } } } } if("guess".equals(name)){ //发送猜消息给客户端 sendMsg(ous, "guess"); System.out.println("已发送guess"); //将提示信息发送给猜的客户端 dos.writeUTF(Myserver.infos[1]); while(true){ //不断接收猜的客户端发送过来的消息 String msg=dis.readUTF(); System.out.println("服务器端接受的信息为:"+msg); //给每个客户端发送消息头部数据 for (int i = 0; i <Myserver.list.size(); i++) { ServerThread st =Myserver.list.get(i); sendMsg(st.socket.getOutputStream(), "msg"); } //如果某个猜线程猜对了 if(Myserver.infos[0].equals(msg)){ Myserver.list.get(0).dos.writeUTF("yes"); this.dos.writeUTF("yes"); this.dos.writeUTF("我说:"+msg); System.out.println("已经发送yes"); }else{ for (int i = 0; i <Myserver.list.size(); i++) { ServerThread st =Myserver.list.get(i); if(st==this){ st.dos.writeUTF("我说:"+msg); } else{ st.dos.writeUTF("他说:"+msg); } } System.out.println("服务器端已发送数据"+msg); } } } }catch (Exception e) { e.printStackTrace(); } } // 发送消息的函数 public void sendMsg(OutputStream os, String s) throws IOException { // 向客户端输出信息 // System.out.println(s); byte[] bytes = s.getBytes(); os.write(bytes); os.write(13); os.write(10); os.flush(); } // 读取客户端输入数据的函数 public String readMsg(InputStream ins) throws Exception { // 读取客户端的信息 int value = ins.read(); // 读取整行 读取到回车(13)换行(10)时停止读 String str = ""; while (value != 10) { // 点击关闭客户端时会返回-1值 if (value == -1) { throw new Exception(); } str = str + ((char) value); value = ins.read(); } str = str.trim(); return str; } // 发送坐标的函数 public void sendMsg1(OutputStream os, int x1, int y1, int x2, int y2,int color ,int width) throws IOException { DataOutputStream dos = new DataOutputStream(os); dos.writeInt(x1); dos.writeInt(y1); dos.writeInt(x2); dos.writeInt(y2); dos.writeInt(color); dos.writeInt(width); dos.flush(); } } package com.huaxin.server; public class ServerTest { //测试类,函数入口 public static void main(String[] args) { Myserver ms = new Myserver(); ms.initServer(); } } com.huaxin.client包: package com.huaxin.client; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Label; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; public class ClientUI extends JFrame { public JButton sendBtn; public JLabel contant; public JPanel drawPanel; public JPanel colorPanel; public JPanel waitPanel; public JPanel drawLeftPanel; public JPanel centerPanel; public JTextField jtf; public JTextArea jta; public Graphics2D g; public Color color; public ClientCtroller control; public Socket socket; public int x1, y1; public BasicStroke strock; public JComboBox<Integer> box; //初始化界面的时候开始创建客户端对象 public ClientUI() { try { socket = new Socket("localhost", 9090); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { ClientUI ui = new ClientUI(); ui.initFrame(); } public void initFrame() { this.setTitle("你画我猜"); this.setSize(700, 500); this.setDefaultCloseOperation(3); this.setLocationRelativeTo(null); // 总的面板 // JPanel panel = new JPanel(); // panel.setBackground(Color.red); // 等待面板 waitPanel = new JPanel(); waitPanel.setBackground(Color.red); JLabel label = new JLabel("正在为您寻找房间......"); waitPanel.add(label); this.add(waitPanel); // 画的面板 // addDrawPanel(); // addGuessPanel(); this.setVisible(true); // 创建客户端控制器对象 control = new ClientCtroller(socket, this); control.dealwith(); } //添加画面板的函数 public void addDrawPanel() { drawPanel = new JPanel(); drawPanel.setLayout(new BorderLayout()); // 画面板的左右子面板 drawLeftPanel = new JPanel(); drawLeftPanel.setLayout(new BorderLayout()); //左边板的中间面板 centerPanel = new JPanel(); centerPanel.setBackground(Color.WHITE); //左面板下的颜色面板 colorPanel = new JPanel(); //给颜色面板设置空布局 colorPanel.setLayout(null); colorPanel.setBackground(Color.gray); colorPanel.setPreferredSize(new Dimension(0,60)); //颜色面板的颜色按钮 Color [] colors={Color.red,Color.black,Color.orange,Color.green, Color.pink,Color.blue,Color.cyan,Color.magenta,Color.YELLOW}; //颜色按钮添加 ActionListener btnlistener = new ActionListener() { public void actionPerformed(ActionEvent e) { JButton bt =(JButton)e.getSource(); color =bt.getBackground(); } }; for (int i = 0; i < colors.length; i++) { JButton btn = new JButton(); btn.setBackground(colors[i]); btn.addActionListener(btnlistener); btn.setBounds(40+i*30, 15, 30, 30); colorPanel.add(btn); } //添加画笔粗细 box =new JComboBox<Integer>(); box.setBounds(380, 15, 80, 30); for (int i = 0; i < 10; i++) { Integer intdata = new Integer(i+1); box.addItem(intdata); } colorPanel.add(box); JPanel drawRightPanel = new JPanel(); drawRightPanel.setLayout(new BorderLayout()); drawRightPanel.setPreferredSize(new Dimension(200, 0)); // 右面板的的下面板 JPanel buttonPanel = new JPanel(); buttonPanel.setPreferredSize(new Dimension(0, 50)); jta = new JTextArea(); jta.setLineWrap(true); JScrollPane jsp = new JScrollPane(jta); jtf = new JTextField(11); contant = new JLabel(); sendBtn = new JButton(); sendBtn.setText("发送"); sendBtn.addActionListener(al); buttonPanel.add(jtf); buttonPanel.add(sendBtn); drawRightPanel.add(jsp); drawRightPanel.add(buttonPanel, BorderLayout.SOUTH); contant.setPreferredSize(new Dimension(0, 20)); drawLeftPanel.add(contant, BorderLayout.NORTH); drawLeftPanel.add(centerPanel, BorderLayout.CENTER); drawLeftPanel.add(colorPanel, BorderLayout.SOUTH); drawPanel.add(drawLeftPanel); drawPanel.add(drawRightPanel, BorderLayout.EAST); this.add(drawPanel); centerPanel.addMouseListener(ma); centerPanel.addMouseMotionListener(ma); this.setVisible(true); g = (Graphics2D)centerPanel.getGraphics(); } //添加猜面板的函数 public void addGuessPanel() { contant.setText("猜的提示信息"); sendBtn.setEnabled(false); drawLeftPanel.remove(colorPanel); drawLeftPanel.repaint(); this.setVisible(true); } //鼠标监听器 MouseAdapter ma = new MouseAdapter() { public void mousePressed(MouseEvent e) { x1 = e.getX(); y1 = e.getY(); }; public void mouseEntered(MouseEvent e) { if(color==null){ color=Color.black; } // System.out.println(i); g.setColor(color); }; public void mouseDragged(MouseEvent e) { int width=(int)box.getSelectedItem(); strock = new BasicStroke(width); g.setStroke(strock); int x2 = e.getX(); int y2 = e.getY(); g.drawLine(x1, y1, x2, y2); // x1 = x2; // y1 = y2; try { control.sendMsg1(socket.getOutputStream(), x1, y1, x2, y2,g.getColor().getRGB(),width); x1 = x2; y1 = y2; } catch (IOException e1) { } }; }; //发送监听器 ActionListener al =new ActionListener() { public void actionPerformed(ActionEvent e) { //获取发送框的内容 String str = jtf.getText(); if(str==null || str.equals("")){ JOptionPane.showMessageDialog(null, "发送内容不能为空!"); }else{ try { control.dos.writeUTF(str); jtf.setText(""); } catch (IOException e1) { e1.printStackTrace(); } } } }; } package com.huaxin.client; import java.awt.BasicStroke; import java.awt.Color; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import javax.swing.JFrame; import javax.swing.JOptionPane; public class ClientCtroller { public Socket socket; public ClientUI ui; public DataInputStream dis; public DataOutputStream dos; // public ClientCtroller(Socket socket) { // this.socket=socket; // } // public ClientCtroller(Socket socket, JFrame ui) { this.socket = socket; this.ui =(ClientUI) ui; } public void dealwith() { try { InputStream ins =this.socket.getInputStream(); OutputStream ous =this.socket.getOutputStream(); dis=new DataInputStream(ins); dos = new DataOutputStream(ous); String msg = readMsg(socket.getInputStream()); if ("draw".equals(msg)) { // 如果是draw,则客户端显示画的界面 ui.remove(ui.waitPanel); ui.addDrawPanel(); ui.sendBtn.setEnabled(false); ui.repaint(); // System.out.println("draw界面完毕比"); //接收要画的信息 String drawinfo=dis.readUTF(); //将要画的信息添加到面板上 ui.contant.setText("画的东西为:"+drawinfo); while(true){ String s=readMsg(ins); System.out.println("draw 接受到的信息:"+s); // System.out.println(s); //接收服务器端发送的猜的客户端猜的消息 if(!"data".equals(s)){ String s1=dis.readUTF(); System.out.println("s1:"+s); //如果猜对了,则在画的客户端显示猜对了 if("yes".equals(s1)){ // JOptionPane.showMessageDialog(null, "你猜对了!"); ui.jta.append("对方猜对了"+"\r\n"); } //否则画的客户端显示猜的客户单端的消息 else{ ui.jta.append(s1+"\r\n"); } } } } if ("guess".equals(msg)) { // 如果是猜,则显示猜的客户端 String guessinfo=dis.readUTF(); ui.remove(ui.waitPanel); ui.addDrawPanel(); ui.addGuessPanel(); ui.contant.setText(guessinfo); ui.sendBtn.setEnabled(true); // ui.repaint(); // System.out.println("guess界面完毕比"); while(true){ //接收服务器端的数据 String info =readMsg(ins); //如果是数据消息 // System.out.println("猜客户端接收的消息为:"+info); if("data".equals(info)){ readMsg1(socket.getInputStream()); } //如果是自己发送的猜的消息 else if("msg".equals(info)){ //再次读取一条消息 String info2=dis.readUTF(); System.out.println("info2"+info2); if("yes".equals(info2)){ info2=dis.readUTF(); ui.jta.append(info2+"\r\n"); ui.jta.append("恭喜你猜对了......"); } else{ System.out.println("接收到的信息为:"+info2); ui.jta.append(info2+"\r\n"); } } // else{ // String info3=dis.readUTF(); // } } } } catch (Exception e) { e.printStackTrace(); } } // 发送消息的函数 public void sendMsg(OutputStream os, String s) throws IOException { // 向客户端输出信息 // // System.out.println(s); byte[] bytes = s.getBytes(); os.write(bytes); os.write(13); os.write(10); os.flush(); } // 读取客户端输入数据的函数 public String readMsg(InputStream ins) throws Exception { // 读取客户端的信息 int value = ins.read(); // 读取整行 读取到回车(13)换行(10)时停止读 String str = ""; while (value != 10) { // 点击关闭客户端时会返回-1值 if (value == -1) { throw new Exception(); } str = str + ((char) value); value = ins.read(); } str = str.trim(); return str; } // 发送消息的函数 public void sendMsg1(OutputStream os, int x1, int y1, int x2, int y2,int color,int width) throws IOException { DataOutputStream dos = new DataOutputStream(os); // dos.writeUTF("data"); dos.writeInt(x1); dos.writeInt(y1); dos.writeInt(x2); dos.writeInt(y2); dos.writeInt(color); dos.writeInt(width); dos.flush(); } public void readMsg1(InputStream is) throws IOException { DataInputStream dis = new DataInputStream (is); int x1=dis.readInt(); int y1=dis.readInt(); int x2=dis.readInt(); int y2=dis.readInt(); int color =dis.readInt(); int width=dis.readInt(); Color c =new Color(color); BasicStroke strock = new BasicStroke(width); ui.g.setColor(c); ui.g.setStroke(strock); // System.out.println("ui:"+ui); ui.g.drawLine(x1, y1, x2, y2); // System.out.println("x1:"+x1+"y1:"+y1+"x2:"+x2+"y2:"+y2); } } package com.huaxin.client; public class ClientTest { public static void main(String[] args) { ClientUI ui = new ClientUI(); ui.initFrame(); } } 五、项目运行结果: 六、项目总结: 1、还是要把所学的知识整理,融汇贯通,才能按照思路一步一步来; 2、不能太着急,可以先分模块来完成,没完成一个模块,可以测试一下该模块是否可以正常运行; 3、报错不要怕,要学会抓bug;
    转载请注明原文地址: https://ju.6miu.com/read-450096.html

    最新回复(0)