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 list = new ArrayList();
//数据库
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 list =new ArrayList();
//从数据库中获取猜的信息
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
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 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();
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;