Java小程序之你画我猜


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;



评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值