github地址https://github.com/HWenTing/MyChatRoom
在學(xué)習(xí)了半年java基礎(chǔ)知識(shí)后敛滋,在上學(xué)期我們完成了java課設(shè)屡谐,現(xiàn)在正好想起來(lái)魂爪,順便整理一下滓侍。代碼總行數(shù)約2400行撩笆,涉及知識(shí):java基礎(chǔ)捺球,socket套接字連接,一部分與數(shù)據(jù)庫(kù)連接知識(shí)夕冲,GUI氮兵,多線程,文件io等歹鱼。代碼部分參考過(guò)他人代碼泣栈。
該課設(shè)主要包括登錄,注冊(cè)弥姻,聊天室南片,貪吃蛇,截屏五大板塊庭敦。
大體界面就是這樣子啦(原諒我的審美23333)
***
沒(méi)錯(cuò)疼进,總體就是這個(gè)樣子的,以下附上代碼颠悬,還有設(shè)計(jì)文檔總結(jié)報(bào)告等,需要的小伙伴可以聯(lián)系我哇~
CatBean
這個(gè)類主要用于封裝
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
public class CatBean implements Serializable {
private int type; // 1私聊 0上下線更新 -1下線請(qǐng)求 2請(qǐng)求發(fā)送文件 3.確定接收文件
private HashSet<String> clients; // 存放選中的客戶
private HashSet<String> to;
public HashMap<String, ClientBean> onlines;
private String info;
private String timer;
private String name;
private String fileName;
private int size;
private String ip;
private int port;
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public HashSet<String> getTo() {
return to;
}
public void setTo(HashSet<String> to) {
this.to = to;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public HashSet<String> getClients() {
return clients;
public void setClients(HashSet<String> clients) {
this.clients = clients;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public String getTimer() {
return timer;
}
public void setTimer(String timer) {
this.timer = timer;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public HashMap<String, ClientBean> getOnlines() {
return onlines;
}
public void setOnlines(HashMap<String, ClientBean> onlines) {
this.onlines = onlines;
}
}
CatChatroom
聊天室的主頁(yè)面刊苍,包含GUI與后臺(tái)邏輯
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javax.swing.AbstractListModel;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
/**
* 用戶列表中每個(gè)用戶顯示狀態(tài)
* @author HP
*
*/
class CellRenderer extends JLabel implements ListCellRenderer {
CellRenderer() {
setOpaque(true);
}
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));// 加入寬度為5的空白邊框
if (value != null) {
setText(value.toString());
setIcon(new ImageIcon("images//tou1.png"));//設(shè)置頭像
}
//設(shè)置用戶被選中和為被選中兩種前景與背景顏色狀態(tài)表示
if (isSelected) {
//被選中時(shí)
setBackground(new Color(255, 255, 153));// 設(shè)置背景色
setForeground(Color.black);//設(shè)置字體色
} else {
//未被選中
setBackground(Color.white); // 設(shè)置背景色
setForeground(Color.black);//設(shè)置字體色
}
setEnabled(list.isEnabled());
setFont(new Font("sdf", Font.ROMAN_BASELINE, 13));
setOpaque(true);
return this;
}
}
class UUListModel extends AbstractListModel{
private Vector vs;
public UUListModel(Vector vs){
this.vs = vs;
}
@Override
public Object getElementAt(int index) {
// TODO Auto-generated method stub
return vs.get(index);
}
@Override
public int getSize() {
// TODO Auto-generated method stub
return vs.size();
}
}
public class CatChatroom extends JFrame {
private static final long serialVersionUID = 6129126482250125466L;
private static JPanel contentPane;
private static Socket clientSocket;
private static ObjectOutputStream oos;
private static ObjectInputStream ois;
private static String name;
private static JTextArea textArea;
private static AbstractListModel listmodel;
private static JList list;
private static String filePath;
private static JLabel lblNewLabel;
private static JProgressBar progressBar;
private static Vector onlines;
private static boolean isSendFile = false;
private static boolean isReceiveFile = false;
// 聲音
private static File file, file2;
private static URL cb, cb2;
private static AudioClip aau, aau2;
private File contentFile;
/**
* Create the frame.
*/
public CatChatroom(String u_name, Socket client) {
// 賦值
name = u_name;
clientSocket = client;
onlines = new Vector();
SwingUtilities.updateComponentTreeUI(this);
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");//改變窗口顯示風(fēng)格
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InstantiationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalAccessException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (UnsupportedLookAndFeelException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
setTitle(name);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
setBounds(440, 200, 896, 796);
contentPane = new JPanel() {
private static final long serialVersionUID = 1L;
@Override//加載背景圖片
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(new ImageIcon("images\\q1.jpg").getImage(), 0, 0,
getWidth(), getHeight(), null);
}
};
try {
contentFile=new File(name);
} catch (Exception e) {
// TODO: handle exception
}
setContentPane(contentPane);
contentPane.setLayout(null);
// 聊天信息顯示區(qū)域
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 10, 490, 510);
getContentPane().add(scrollPane);
//聊天信息顯示框
textArea = new JTextArea();
textArea.setEditable(false);
textArea.setLineWrap(true);//激活自動(dòng)換行功能
textArea.setWrapStyleWord(true);//激活斷行不斷字功能
textArea.setFont(new Font("sdf", Font.BOLD, 17));
//將以往聊天記錄顯示在聊天信息顯示框
try {
BufferedReader br=new BufferedReader(new FileReader(contentFile));
String tempString = null;
textArea.setFont(new Font("sdf", Font.BOLD, 13));
while((tempString=br.readLine())!=null){
textArea.append(tempString+"\n");
}
textArea.setFont(new Font("sdf", Font.BOLD, 17));
br.close();
} catch ( IOException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
scrollPane.setViewportView(textArea);
// 打字區(qū)域
JScrollPane scrollPane_1 = new JScrollPane();
scrollPane_1.setBounds(10, 557, 498, 137);
getContentPane().add(scrollPane_1);
//輸入信息顯示框
final JTextArea textArea_1 = new JTextArea();
textArea_1.setLineWrap(true);//激活自動(dòng)換行功能
textArea_1.setWrapStyleWord(true);//激活斷行不斷字功能
textArea_1.setFont(new Font("sdf", Font.PLAIN, 18));
scrollPane_1.setViewportView(textArea_1);
// 關(guān)閉按鈕
final JButton btnNewButton = new JButton("關(guān)閉");
btnNewButton.setBounds(270, 700, 100, 40);
getContentPane().add(btnNewButton);
// 發(fā)送按鈕
JButton btnNewButton_1 = new JButton("發(fā)送");
btnNewButton_1.setBounds(224+180, 700, 100, 40);
getRootPane().setDefaultButton(btnNewButton_1);
getContentPane().add(btnNewButton_1);
//貪吃蛇按鈕
JButton btnNewButton_2 = new JButton("貪吃蛇");
btnNewButton_2.setBounds(344+230, 700, 100, 40);
//貪吃蛇按鈕增添事件監(jiān)聽(tīng)
btnNewButton_2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 啟動(dòng)貪吃蛇小游戲
GreedSnake gs;
try {
gs = new GreedSnake();
} catch (Exception e2) {
// TODO: handle exception
}
}
});
getContentPane().add(btnNewButton_2);
//截屏按鈕
JButton btnNewButton_3 = new JButton("截屏");
btnNewButton_3.setBounds(466+255, 700, 100, 40);
//截屏按鈕增添事件監(jiān)聽(tīng)
btnNewButton_3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Sreen ss=new Sreen();
//啟動(dòng)截屏功能
ss.doStart();
}
});
getContentPane().add(btnNewButton_3);
//清屏按鈕
JButton btnNewButton_4 = new JButton("清屏");
btnNewButton_4.setBounds(414,523, 100, 34);
//增加時(shí)間監(jiān)聽(tīng)
btnNewButton_4.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
textArea.setText(null);
}
});
getContentPane().add(btnNewButton_4);
// 在線客戶列表
listmodel = new UUListModel(onlines) ;
list = new JList(listmodel);
list.setCellRenderer(new CellRenderer());
list.setOpaque(false);
Border etch = BorderFactory.createEtchedBorder();
list.setBorder(BorderFactory.createTitledBorder(etch, "<"+u_name+">"
+ "在線客戶:", TitledBorder.LEADING, TitledBorder.TOP, new Font(
"sdf", Font.BOLD, 20), Color.green));//標(biāo)題欄設(shè)置
//在線用戶滾動(dòng)區(qū)域
JScrollPane scrollPane_2 = new JScrollPane(list);
scrollPane_2.setBounds(530, 10, 345,575);
scrollPane_2.setOpaque(false);
scrollPane_2.getViewport().setOpaque(false);
getContentPane().add(scrollPane_2);
// 文件傳輸欄 progressBar 它可以 簡(jiǎn)單地輸出進(jìn)度的變化情況
progressBar = new JProgressBar();
progressBar.setBounds(530, 650, 345, 25);
progressBar.setMinimum(1);
progressBar.setMaximum(100);
getContentPane().add(progressBar);
// 文件傳輸提示
lblNewLabel = new JLabel(
"文件傳輸信息欄:");
lblNewLabel.setFont(new Font("SimSun", Font.PLAIN, 15));
lblNewLabel.setBackground(Color.WHITE);
lblNewLabel.setBounds(530, 610,345, 25);
getContentPane().add(lblNewLabel);
try {
oos = new ObjectOutputStream(clientSocket.getOutputStream());
// 記錄上線客戶的信息在catbean中,并發(fā)送給服務(wù)器
CatBean bean = new CatBean();
bean.setType(0);
bean.setName(name);
bean.setTimer(CatUtil.getTimer());
oos.writeObject(bean);
oos.flush();
// 消息提示聲音
file = new File("sounds\\消息.wav");
cb = file.toURL();
aau = Applet.newAudioClip(cb);
// 上線提示聲音
file2 = new File("sounds\\上線.wav");
cb2 = file2.toURL();
aau2 = Applet.newAudioClip(cb2);
// 啟動(dòng)客戶接收線程
new ClientInputThread().start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 發(fā)送按鈕事件監(jiān)聽(tīng)
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String info = textArea_1.getText();
List to = list.getSelectedValuesList();//獲取所選擇對(duì)象
//若未選擇對(duì)象
if (to.size() < 1) {
JOptionPane.showMessageDialog(getContentPane(), "請(qǐng)選擇聊天對(duì)象");
return;
}
//若選擇對(duì)象為自己
if (to.toString().contains(name+"(我)")) {
JOptionPane
.showMessageDialog(getContentPane(), "不能向自己發(fā)送信息");
return;
}
//若發(fā)送信息為空
if (info.equals("")) {
JOptionPane.showMessageDialog(getContentPane(), "不能發(fā)送空信息");
return;
}
//正常情況下,建立連接,發(fā)送數(shù)據(jù)
CatBean clientBean = new CatBean();
clientBean.setType(1);
clientBean.setName(name);
String time = CatUtil.getTimer();
clientBean.setTimer(time);
clientBean.setInfo(info);
HashSet set = new HashSet();
set.addAll(to);
clientBean.setClients(set);
sendMessage(clientBean);
// 自己發(fā)的內(nèi)容也要現(xiàn)實(shí)在自己的屏幕上面
textArea.append(time + " 我對(duì)" + to + "說(shuō):\r\n" + info + "\r\n");
//將發(fā)送信息保存在本地文件中,作為聊天記錄
try {
FileWriter fw=new FileWriter(contentFile,true);
BufferedWriter bw=new BufferedWriter(fw);
bw.write(time + "我對(duì)<" + to + ">說(shuō):\r\n" + info + "\r\n");
bw.close();
fw.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//清空發(fā)送消息欄并重新獲取焦點(diǎn)
textArea_1.setText(null);
textArea_1.requestFocus();
}
});
// 關(guān)閉按鈕事件監(jiān)聽(tīng)
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//在文件傳輸時(shí)不能關(guān)閉窗口
if(isSendFile || isReceiveFile){
JOptionPane.showMessageDialog(contentPane,
"正在傳輸文件中志鞍,您不能離開(kāi)...",
"Error Message", JOptionPane.ERROR_MESSAGE);
}else{
//發(fā)送下線消息
btnNewButton.setEnabled(false);
CatBean clientBean = new CatBean();
clientBean.setType(-1);
clientBean.setName(name);
clientBean.setTimer(CatUtil.getTimer());
sendMessage(clientBean);
}
}
});
// 窗口事件監(jiān)聽(tīng)
this.addWindowListener(new WindowAdapter() {
@Override
//離開(kāi)
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
if(isSendFile || isReceiveFile){
JOptionPane.showMessageDialog(contentPane,
"正在傳輸文件中仙蚜,您不能離開(kāi)...",
"Error Message", JOptionPane.ERROR_MESSAGE);
}else{
int result = JOptionPane.showConfirmDialog(getContentPane(),
"您確定要離開(kāi)聊天室");//取得用戶選擇
//若用戶選擇確定離開(kāi)贾节,發(fā)送下線消息
if (result == 0) {
CatBean clientBean = new CatBean();
clientBean.setType(-1);
clientBean.setName(name);
clientBean.setTimer(CatUtil.getTimer());
sendMessage(clientBean);
}
}
}
});
// 在線用戶列表監(jiān)聽(tīng)
list.addMouseListener(new MouseAdapter() {
@Override//鼠標(biāo)事件監(jiān)聽(tīng)
public void mouseClicked(MouseEvent e) {
List to = list.getSelectedValuesList();
//雙擊事件代表發(fā)送文件
if (e.getClickCount() == 2) {
//如過(guò)發(fā)送對(duì)象為自己
if (to.toString().contains(name+"(我)")) {
JOptionPane
.showMessageDialog(getContentPane(), "不能向自己發(fā)送文件");
return;
}
// 雙擊打開(kāi)文件文件選擇框
JFileChooser chooser = new JFileChooser();
chooser.setDialogTitle("選擇文件框"); // 標(biāo)題
chooser.showDialog(getContentPane(), "選擇"); // 按鈕的名字
// 判定是否選擇了文件
if (chooser.getSelectedFile() != null) {
// 獲取路徑
filePath = chooser.getSelectedFile().getPath();
File file = new File(filePath);
// 如果文件為空
if (file.length() == 0) {
JOptionPane.showMessageDialog(getContentPane(),
filePath + "文件為空,不允許發(fā)送.");
return;
}
//正常狀態(tài)斤程,建立連接墨吓,發(fā)送請(qǐng)求
CatBean clientBean = new CatBean();
clientBean.setType(2);// 請(qǐng)求發(fā)送文件
clientBean.setSize(new Long(file.length()).intValue());
clientBean.setName(name);
clientBean.setTimer(CatUtil.getTimer());
clientBean.setFileName(file.getName()); // 記錄文件的名稱
clientBean.setInfo("請(qǐng)求發(fā)送文件");
// 判斷要發(fā)送給誰(shuí)
HashSet<String> set = new HashSet<String>();
set.addAll(list.getSelectedValuesList());
clientBean.setClients(set);
sendMessage(clientBean);
}
}
}
});
}
/**
* 線程接收類
* @author HP
*
*/
class ClientInputThread extends Thread {
@Override
public void run() {
try {
// 不停的從服務(wù)器接收信息
while (true) {
ois = new ObjectInputStream(clientSocket.getInputStream());
final CatBean bean = (CatBean) ois.readObject();
//分析接受到catbean的類型
switch (bean.getType()) {
case 0: {
// 更新列表
onlines.clear();//清空列表
HashSet<String> clients = bean.getClients();
Iterator<String> it = clients.iterator();
//重新加載
while (it.hasNext()) {
String ele = it.next();
if (name.equals(ele)) {
onlines.add(ele + "(我)");
} else {
onlines.add(ele);
}
}
listmodel = new UUListModel(onlines);
list.setModel(listmodel);
aau2.play();//上線聲音
textArea.append(bean.getInfo() + "\r\n");
textArea.selectAll();
break;
}
case -1: {
//直接下線
return;
}
case 1: {
//獲取發(fā)送信息
String info = bean.getTimer() + " " +bean.getName()
+ "對(duì) " +bean.getClients() + "說(shuō):\r\n";
//將對(duì)方發(fā)送消息中自己的名字替換成“我”
if (info.contains(name) ) {
info = info.replace(name, "我");
}
aau.play();
textArea.append(info+bean.getInfo() + "\r\n");
//將對(duì)方發(fā)送的消息寫(xiě)入聊天記錄中
try {
FileWriter fw=new FileWriter(contentFile,true);
BufferedWriter bw=new BufferedWriter(fw);
bw.write(info+bean.getInfo() + "\r\n");
bw.close();
fw.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
textArea.selectAll();
break;
}
case 2: {
// 由于等待目標(biāo)客戶確認(rèn)是否接收文件是個(gè)阻塞狀態(tài)式矫,所以這里用線程處理
new Thread(){
public void run() {
//顯示是否接收文件對(duì)話框
int result = JOptionPane.showConfirmDialog(
getContentPane(), bean.getInfo());
//對(duì)用戶做出的選擇做出反應(yīng)
switch(result){
case 0:{ //接收文件
JFileChooser chooser = new JFileChooser();
chooser.setDialogTitle("保存文件框"); // 標(biāo)題
//默認(rèn)文件名稱還有放在當(dāng)前目錄下
chooser.setSelectedFile(new File(bean
.getFileName()));
chooser.showDialog(getContentPane(), "保存"); // 設(shè)置按鈕名字
//保存路徑
String saveFilePath =chooser.getSelectedFile().toString();
//創(chuàng)建客戶CatBean
CatBean clientBean = new CatBean();
clientBean.setType(3);
clientBean.setName(name); //接收文件的客戶名字
clientBean.setTimer(CatUtil.getTimer());
clientBean.setFileName(saveFilePath);
clientBean.setInfo("確定接收文件");
// 判斷要發(fā)送給誰(shuí)
HashSet<String> set = new HashSet<String>();
set.add(bean.getName());
clientBean.setClients(set); //文件來(lái)源
clientBean.setTo(bean.getClients());//給這些客戶發(fā)送文件
// 創(chuàng)建新的tcp socket 接收數(shù)據(jù)
try {
ServerSocket ss = new ServerSocket(0); // 0可以獲取空閑的端口號(hào)
clientBean.setIp(clientSocket.getInetAddress().getHostAddress());
clientBean.setPort(ss.getLocalPort());
sendMessage(clientBean); // 先通過(guò)服務(wù)器告訴發(fā)送方, 你可以直接發(fā)送文件到我這里了
isReceiveFile=true;
//等待文件來(lái)源的客戶板熊,輸送文件....目標(biāo)客戶從網(wǎng)絡(luò)上讀取文件,并寫(xiě)在本地上
Socket sk = ss.accept();
textArea.append(CatUtil.getTimer() + " " + bean.getFileName()
+ "文件保存中.\r\n");
DataInputStream dis = new DataInputStream( //從網(wǎng)絡(luò)上讀取文件
new BufferedInputStream(sk.getInputStream()));
DataOutputStream dos = new DataOutputStream( //寫(xiě)在本地上
new BufferedOutputStream(new FileOutputStream(
saveFilePath)));
int count = 0;
int num = bean.getSize() / 100;
int index = 0;
while (count < bean.getSize()) {
int t = dis.read();
dos.write(t);
count++;
if(num>0){
if (count % num == 0 && index < 100) {
progressBar.setValue(++index);
}
lblNewLabel.setText("下載進(jìn)度:" + count
+ "/" + bean.getSize() + " 整體" + index
+ "%");
}else{
lblNewLabel.setText("下載進(jìn)度:" + count
+ "/" + bean.getSize() +" 整體:"+new Double(new Double(count).doubleValue()/new Double(bean.getSize()).doubleValue()*100).intValue()+"%");
if(count==bean.getSize()){
progressBar.setValue(100);
}
}
}
//給文件來(lái)源客戶發(fā)條提示竭贩,文件保存完畢
PrintWriter out = new PrintWriter(sk.getOutputStream(),true);
out.println(CatUtil.getTimer() + " 發(fā)送給"+name+"的文件[" + bean.getFileName()+"]"
+ "文件保存完畢.\r\n");
out.flush();
dos.flush();
dos.close();
out.close();
dis.close();
sk.close();
ss.close();
textArea.append(CatUtil.getTimer() + " " + bean.getFileName()
+ "文件保存完畢.存放位置為:"+saveFilePath+"\r\n");
isReceiveFile = false;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}default: {
//用戶選擇取消接收
CatBean clientBean = new CatBean();
clientBean.setType(4);
clientBean.setName(name); //接收文件的客戶名字
clientBean.setTimer(CatUtil.getTimer());
clientBean.setFileName(bean.getFileName());
clientBean.setInfo(CatUtil.getTimer() + " "
+ name + "取消接收文件["
+ bean.getFileName() + "]");
// 判斷要發(fā)送給誰(shuí)
HashSet<String> set = new HashSet<String>();
set.add(bean.getName());
clientBean.setClients(set); //文件來(lái)源
clientBean.setTo(bean.getClients());//給這些客戶發(fā)送文件
sendMessage(clientBean);
break;
}
}
};
}.start();
break;
}
case 3: { //目標(biāo)客戶愿意接收文件肪获,源客戶開(kāi)始讀取本地文件并發(fā)送到網(wǎng)絡(luò)上
textArea.append(bean.getTimer() + " "+ bean.getName() + "確定接收文件" + ",文件傳送中..\r\n");//在聊天面板顯示信息
new Thread(){
public void run() {
try {
isSendFile = true;
//創(chuàng)建要接收文件的客戶套接字
Socket s = new Socket(bean.getIp(),bean.getPort());
DataInputStream dis = new DataInputStream(
new FileInputStream(filePath)); //本地讀取該客戶剛才選中的文件
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(s
.getOutputStream())); //網(wǎng)絡(luò)寫(xiě)出文件
int size = dis.available();
int count = 0; //讀取次數(shù)
int num = size / 100;
int index = 0;
while (count < size) {
int t = dis.read();
dos.write(t);
count++; //每次只讀取一個(gè)字節(jié)
//顯示傳輸進(jìn)度
if(num>0){
if (count % num == 0 && index < 100) {
progressBar.setValue(++index);
}
lblNewLabel.setText("上傳進(jìn)度:" + count + "/"
+ size + " 整體" + index
+ "%");
}else{
lblNewLabel.setText("上傳進(jìn)度:" + count + "/"
+ size +" 整體:"+new Double(new Double(count).doubleValue()/new Double(size).doubleValue()*100).intValue()+"%"
);
if(count==size){
progressBar.setValue(100);
}
}
}
dos.flush();
dis.close();
//讀取目標(biāo)客戶的提示保存完畢的信息
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
textArea.append( br.readLine() + "\r\n");
isSendFile = false;
br.close();
s.close();
} catch (Exception ex) {
ex.printStackTrace();
}
};
}.start();
break;
}
case 4: {
textArea.append(bean.getInfo() + "\r\n");
break;
}
default: {
break;
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (clientSocket != null) {
try {
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.exit(0);
}
}
}
/**
* 傳輸信息方法
* @param clientBean
*/
private void sendMessage(CatBean clientBean) {
try {
oos = new ObjectOutputStream(clientSocket.getOutputStream());
oos.writeObject(clientBean);
oos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
CatLogin
用于實(shí)現(xiàn)登錄
import java.awt.Color;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.sql.Connection;
import java.sql.DriverManager;
//import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
/**
* 登錄界面窗口
* 實(shí)現(xiàn)用戶登錄功能
* @author DH
*
*/
public class CatLogin extends JFrame {
private static final long serialVersionUID = 1L;
private JButton btnNewButton;
private JButton btnNewButton_1;
private JLabel lblNewLabel;
private JPanel contentPane;
private JTextField textField;
private JPasswordField passwordField;
public static HashMap<String, ClientBean> onlines;
boolean loginCheck = false;
boolean exist = false;
boolean valid = false;
boolean regsuccess = false;
// MySQL URL declaration
final String URL = "jdbc:mysql://localhost:3306/sys?useSSL=true";
final String USERNAME = "root";
final String PASSWORD = "123456";
private Connection conn = null;
private Statement state = null;
/**
* Launch the application.
*
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
// 啟動(dòng)登陸界面
CatLogin frame = new CatLogin();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public CatLogin() {
setTitle("聊天室登錄界面");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(472, 235, 967, 681);
contentPane = new JPanel() {
private static final long serialVersionUID = 1L;
@Override//鋪設(shè)背景圖片
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(new ImageIcon(
"images/圖片1.png").getImage(), 0,
0, getWidth(), getHeight(), null);
}
};
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
//用戶名輸入框
textField = new JTextField();
textField.setFont(new Font( "Serif", 1, 25));//設(shè)置字體
textField.setBounds(197, 376, 190, 50);
textField.setOpaque(false);//此方法是設(shè)置控件是否透明的。true表示不透明虹蒋,false表示透明。文本區(qū)域設(shè)為透明
contentPane.add(textField);
textField.setColumns(10);
//密碼輸入框
passwordField = new JPasswordField();
passwordField.setFont(new Font( "Serif", 1, 25));//設(shè)置字體
passwordField.setEchoChar('*');//設(shè)置顯示字符
passwordField.setOpaque(false);//文本區(qū)域設(shè)為透明
passwordField.setBounds(197, 464, 190, 50);
contentPane.add(passwordField);
//登錄按鈕
btnNewButton = new JButton();
btnNewButton.setIcon(new ImageIcon("images\\登錄1.png"));//設(shè)置圖標(biāo)背景
btnNewButton.setBounds(459, 537, 108, 54);
btnNewButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));//設(shè)置鼠標(biāo)在該區(qū)域顯示狀態(tài)變化
getRootPane().setDefaultButton(btnNewButton);//設(shè)置回車(chē)響應(yīng)
contentPane.add(btnNewButton);
//注冊(cè)按鈕
btnNewButton_1 = new JButton();
btnNewButton_1.setIcon(new ImageIcon("images\\圖片2.png"));//設(shè)置圖標(biāo)背景
btnNewButton_1.setBounds(773, 276, 111, 56);
btnNewButton_1.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));//設(shè)置鼠標(biāo)在該區(qū)域顯示狀態(tài)變化
contentPane.add(btnNewButton_1);
// 提示信息
lblNewLabel = new JLabel();
lblNewLabel.setBounds(220, 521, 190, 30);
lblNewLabel.setFont(new Font("Dialog", 1, 15));
lblNewLabel.setForeground(Color.red);
contentPane.add(lblNewLabel);
// 監(jiān)聽(tīng)登陸按鈕
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String u_name = textField.getText();//獲取用戶輸入的用戶名
String u_pwd = new String(passwordField.getPassword());//獲取用戶輸入的密碼
try {
//調(diào)用用戶登錄方法
LoginDatabase(u_name, u_pwd);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
//注冊(cè)按鈕監(jiān)聽(tīng)
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
btnNewButton_1.setEnabled(false);
CatResign frame = new CatResign();
frame.setVisible(true);// 顯示注冊(cè)界面
setVisible(false);// 隱藏掉登陸界面
}
});
}
/**
* 登錄數(shù)據(jù)庫(kù)方法哲银,傳入用戶名和用戶密碼
* @param u_name
* @param u_pwd
* @throws SQLException
*/
protected void LoginDatabase(String u_name, String u_pwd) throws SQLException {
ResultSet result = null;
try {
// 連接到MySQL
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
state = conn.createStatement();
// 從MySQL中讀取數(shù)據(jù)
result = state.executeQuery("SELECT * FROM test WHERE `name` =" + "'" + u_name + "'");
// 檢查用戶名是否存在
if (result.next()) {
// 進(jìn)行數(shù)據(jù)比對(duì)
if (result.getString(1).equals(u_name)) {
if (result.getString(2).equals(u_pwd)) {
try {
Socket client = new Socket("localhost", 8520);//建立端口號(hào)連接
btnNewButton.setEnabled(false);
CatChatroom frame = new CatChatroom(u_name,
client);
frame.setVisible(true);// 顯示聊天界面
this.setVisible(false);// 隱藏掉登陸界面
} catch (UnknownHostException e1) {
errorTip("The connection with the server is interrupted, please login again");
} catch (IOException e1) {
errorTip("The connection with the server is interrupted, please login again");
}
}else{
//給出用戶提示信息草巡,并清空信息欄
lblNewLabel.setText("您輸入的密碼有誤!");
textField.setText("");
passwordField.setText("");
textField.requestFocus();
}
}else{
//給出用戶提示信息玛迄,并清空信息欄
lblNewLabel.setText("您輸入昵稱不存在讥蟆!");
textField.setText("");
passwordField.setText("");
textField.requestFocus();
}
}
} catch (SQLException ex) {
System.out.println("SQLException:" + ex.getMessage());
System.out.println("SQLState:" + ex.getSQLState());
System.out.println("VendorError:" + ex.getErrorCode());
} catch (ClassNotFoundException ex) {
System.out.println("Not Found:" + ex.toString());
}finally {
}
}
protected void errorTip(String str) {
// TODO Auto-generated method stub
//顯示錯(cuò)誤信息,清空信息欄
JOptionPane.showMessageDialog(contentPane, str, "Error Message",
JOptionPane.ERROR_MESSAGE);
textField.setText("");
passwordField.setText("");
textField.requestFocus();
}
}
CatResign
實(shí)現(xiàn)新用戶注冊(cè)
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
/**
* 注冊(cè)界面
* @author DH
*
*/
public class CatResign extends JFrame {
//界面基礎(chǔ)組件
private JPanel contentPane;
private JTextField textField;
private JPasswordField passwordField;
private JPasswordField passwordField_1;
private JLabel lblNewLabel;
private JButton btnNewButton_1;
private JButton btnNewButton;
//數(shù)據(jù)庫(kù)信息
final String URL = "jdbc:mysql://localhost:3306/sys?useSSL=true";
final String USERNAME = "root";
final String PASSWORD = "123456";
private Connection conn = null;
private Statement state = null;
private PreparedStatement ptmt = null;
/**
* 初始化注冊(cè)界面
*/
public CatResign() {
setTitle("聊天室注冊(cè)界面");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(560, 300, 700,500);
contentPane = new JPanel() {
private static final long serialVersionUID = 1L;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//加載背景圖片
g.drawImage(new ImageIcon("images\\注冊(cè)頁(yè)面2.png").getImage(), 0,0, getWidth(), getHeight(), null);
}
};
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
//用戶名輸入框
textField = new JTextField();
textField.setBounds(260, 162, 170, 38);
textField.setOpaque(false);//文本區(qū)域設(shè)為透明
contentPane.add(textField);
textField.setColumns(10);
//密碼輸入框
passwordField = new JPasswordField();
passwordField.setEchoChar('*');
passwordField.setOpaque(false);//文本區(qū)域設(shè)為透明
passwordField.setBounds(257, 238, 174, 37);
contentPane.add(passwordField);
//密碼確認(rèn)輸入框
passwordField_1 = new JPasswordField();
passwordField_1.setBounds(255, 301, 180, 41);
passwordField_1.setOpaque(false);//文本區(qū)域設(shè)為透明
contentPane.add(passwordField_1);
//注冊(cè)按鈕
btnNewButton_1 = new JButton();
btnNewButton_1.setIcon(new ImageIcon("images\\注冊(cè)1.jpg"));//加圖標(biāo)
btnNewButton_1.setBounds(446, 376, 86, 46);
btnNewButton_1.setContentAreaFilled(false);
btnNewButton_1.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));//設(shè)置鼠標(biāo)在該區(qū)域顯示狀態(tài)變化
contentPane.add(btnNewButton_1);
//返回按鈕
btnNewButton = new JButton("");
btnNewButton.setBounds(311, 374, 83, 48);
btnNewButton.setContentAreaFilled(false);
btnNewButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));//設(shè)置鼠標(biāo)在該區(qū)域顯示狀態(tài)變化
contentPane.add(btnNewButton);
//提示信息
lblNewLabel = new JLabel();
lblNewLabel.setBounds(260, 125, 170, 38);
lblNewLabel.setFont(new Font("SimSun", Font.BOLD, 17));
lblNewLabel.setForeground(Color.red);
contentPane.add(lblNewLabel);
//返回按鈕監(jiān)聽(tīng)
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
btnNewButton.setEnabled(false);
//返回登陸界面
CatLogin frame = new CatLogin();
frame.setVisible(true);//顯示登錄界面
setVisible(false);//隱藏注冊(cè)界面
}
});
//注冊(cè)按鈕監(jiān)聽(tīng)
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//獲取用戶輸入的信息
String u_name = textField.getText();
String u_pwd = new String(passwordField.getPassword());
String u_pwd_ag = new String(passwordField_1.getPassword());
try {
//調(diào)用注冊(cè)方法進(jìn)行用戶注冊(cè)
Registerer(u_name ,u_pwd,u_pwd_ag);
} catch (SQLException e1) {
e1.printStackTrace();
}
}}
);
}
/**
* 注冊(cè)方法
* @param username
* @param password
* @param confirm
* @throws SQLException
*/
protected void Registerer(String username, String password, String confirm) throws SQLException {
ResultSet result = null;
try {
// 連接到數(shù)據(jù)庫(kù)
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
state = conn.createStatement();
// Check if password is correctly set
if (username.length() != 0) {
//判斷兩輸入次密碼是否一致
if (password.equals(confirm)) {
result = state.executeQuery("SELECT * FROM test WHERE `name` =" + "'" + username + "'");
if (result.next()) {
//檢測(cè)是否用戶名已存在
if (result.getString(1).equals(username)) {
lblNewLabel.setText("用戶名已存在!");
}
} else {
// 將信息寫(xiě)入到數(shù)據(jù)庫(kù)
ptmt = conn.prepareStatement("INSERT INTO test ( name , keyword ) VALUES ( ? , ? )");
ptmt.setString(1, username);
ptmt.setString(2, password);
int check = ptmt.executeUpdate();
// 檢查數(shù)據(jù)庫(kù)注冊(cè)是否成功
if (check > 0){
btnNewButton_1.setEnabled(false);
//返回登陸界面
CatLogin frame = new CatLogin();
frame.setVisible(true);//顯示登錄界面
setVisible(false);//隱藏注冊(cè)界面
}
}
}else{
lblNewLabel.setText("密碼不一致!");
}
}else{
lblNewLabel.setText("密碼不能為空瘟则!");
}
} catch (SQLException ex) {
System.out.println("SQLException:" + ex.getMessage());
System.out.println("SQLState:" + ex.getSQLState());
System.out.println("VendorError:" + ex.getErrorCode());
} catch (ClassNotFoundException ex) {
System.out.println("Not Found:" + ex.toString());
}
}
}
CatServer
服務(wù)器程序
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* 服務(wù)器端,用于接受發(fā)送各種數(shù)據(jù)
* @author DH
*
*/
public class CatServer {
private static ServerSocket ss;
public static HashMap<String, ClientBean> onlines;
static {
try {
//建立端口號(hào)
ss = new ServerSocket(8520);
onlines = new HashMap<String, ClientBean>();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 線程內(nèi)部類
* @author HP
*
*/
class CatClientThread extends Thread {
private Socket client;
private CatBean bean;
private ObjectInputStream ois;
private ObjectOutputStream oos;
public CatClientThread(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
// 不停的從客戶端接收信息
while (true) {
ois = new ObjectInputStream(client.getInputStream());//獲取輸入流
bean = (CatBean)ois.readObject();// 讀取從客戶端接收到的catbean信息
// 對(duì)catbean中的類型進(jìn)行分析,分別作出回應(yīng)
switch (bean.getType()) {
// 上下線更新
case 0: { // 上線
// 記錄上線客戶的用戶名和端口在clientbean中
ClientBean cbean = new ClientBean();
cbean.setName(bean.getName());
cbean.setSocket(client);
// 用戶列表中添加在線用戶
onlines.put(bean.getName(), cbean);
// 創(chuàng)建服務(wù)器的catbean,并發(fā)送給客戶端
CatBean serverBean = new CatBean();
serverBean.setType(0);
serverBean.setInfo(bean.getTimer() + " "
+ bean.getName() + "上線了");//設(shè)置在聊天面板顯示的上線提示
// 給所有在線用戶發(fā)出有人上線消息
HashSet<String> set = new HashSet<String>();
set.addAll(onlines.keySet());//刷新在線用戶列表
serverBean.setClients(set);
sendAll(serverBean);
break;
}
case -1: { // 下線
// 創(chuàng)建服務(wù)器的catbean策幼,并發(fā)送給客戶端
CatBean serverBean = new CatBean();
serverBean.setType(-1);
try {
oos = new ObjectOutputStream(
client.getOutputStream());
oos.writeObject(serverBean);
oos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//移除下線用戶
onlines.remove(bean.getName());
// 向剩下的在線用戶發(fā)送有人離開(kāi)的通知
CatBean serverBean2 = new CatBean();
serverBean2.setInfo(bean.getTimer() + " "
+ bean.getName() + " " + " 下線了");//下線信息
serverBean2.setType(0);
HashSet<String> set = new HashSet<String>();
set.addAll(onlines.keySet());
serverBean2.setClients(set);
sendAll(serverBean2);
return;
}
case 1: { // 聊天
// 創(chuàng)建服務(wù)器的catbean唐含,并發(fā)送給客戶端
CatBean serverBean = new CatBean();
serverBean.setType(1);
serverBean.setClients(bean.getClients());
serverBean.setInfo(bean.getInfo());
serverBean.setName(bean.getName());
serverBean.setTimer(bean.getTimer());
// 向選中的客戶發(fā)送數(shù)據(jù)
sendMessage(serverBean);
break;
}
case 2: { // 請(qǐng)求接受文件
// 創(chuàng)建服務(wù)器的catbean件缸,并發(fā)送給客戶端
CatBean serverBean = new CatBean();
String info = bean.getTimer() + " " + bean.getName()
+ "向你傳送文件,是否需要接受";
serverBean.setType(2);
serverBean.setClients(bean.getClients()); // 這是發(fā)送的目的地
serverBean.setFileName(bean.getFileName()); // 文件名稱
serverBean.setSize(bean.getSize()); // 文件大小
serverBean.setInfo(info);//提示信息內(nèi)容
serverBean.setName(bean.getName()); // 來(lái)源
serverBean.setTimer(bean.getTimer());
// 向選中的客戶發(fā)送數(shù)據(jù)
sendMessage(serverBean);
break;
}
case 3: { // 確定接收文件
CatBean serverBean = new CatBean();
serverBean.setType(3);
serverBean.setClients(bean.getClients()); // 文件來(lái)源
serverBean.setTo(bean.getTo()); // 文件目的地
serverBean.setFileName(bean.getFileName()); // 文件名稱
serverBean.setIp(bean.getIp());
serverBean.setPort(bean.getPort());
serverBean.setName(bean.getName()); // 接收的客戶名稱
serverBean.setTimer(bean.getTimer());
// 通知文件來(lái)源的客戶痊末,對(duì)方確定接收文件
sendMessage(serverBean);
break;
}
case 4: {
CatBean serverBean = new CatBean();
serverBean.setType(4);
serverBean.setClients(bean.getClients()); // 文件來(lái)源
serverBean.setTo(bean.getTo()); // 文件目的地
serverBean.setFileName(bean.getFileName());
serverBean.setInfo(bean.getInfo());
serverBean.setName(bean.getName());// 接收的客戶名稱
serverBean.setTimer(bean.getTimer());
sendMessage(serverBean);
break;
}
default: {
break;
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
close();
}
}
/**
* 向用戶發(fā)送數(shù)據(jù)
* @param serverBean
*/
private void sendMessage(CatBean serverBean) {
// 首先取得所有的values
Set<String> cbs = onlines.keySet();
Iterator<String> it = cbs.iterator();
// 選中客戶
HashSet<String> clients = serverBean.getClients();
while (it.hasNext()) {
// 在線客戶
String client = it.next();
// 選中的客戶中若是在線的盒件,就發(fā)送serverbean
if (clients.contains(client)) {
Socket c = onlines.get(client).getSocket();
ObjectOutputStream oos;
try {
oos = new ObjectOutputStream(c.getOutputStream());
oos.writeObject(serverBean);
oos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 向所有用戶發(fā)送數(shù)據(jù)
* @param serverBean
*/
public void sendAll(CatBean serverBean) {
Collection<ClientBean> clients = onlines.values();
Iterator<ClientBean> it = clients.iterator();
ObjectOutputStream oos;
while (it.hasNext()) {
Socket c = it.next().getSocket();
try {
//進(jìn)行數(shù)據(jù)傳送
oos = new ObjectOutputStream(c.getOutputStream());
oos.writeObject(serverBean);
oos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 關(guān)閉各種流
*/
private void close() {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (client != null) {
try {
client.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void start() {
try {
//不停接受來(lái)自客戶端的請(qǐng)求
while (true) {
//建立連接罗心,線程處理
Socket client = ss.accept();
new CatClientThread(client).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 主方法
* @param args
*/
public static void main(String[] args) {
new CatServer().start();
}
}
CatUtil
可以用來(lái)封裝一些使用方法
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
/**
* 方法類
* @author DH
*
*/
public class CatUtil {
@SuppressWarnings("unused")
public static String getTimer() {
//獲取時(shí)間格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date());
}
}
ClientBean
import java.net.Socket;
public class ClientBean {
private String name;
private Socket socket;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
}
GreedSnake
貪吃蛇代碼的實(shí)現(xiàn)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
//Main Class
public class GreedSnake extends KeyAdapter {
JFrame mainFrame;
Canvas paintCanvas;
JLabel labelScore;// 計(jì)分牌
SnakeModel snakeModel = null;// 蛇
public static final int DEFAULT_WIDTH = 500;
public static final int DEFAULT_HEIGHT = 300;
public static final int nodeWidth = 10;
public static final int nodeHeight = 10;
// GreedSnake():初始化游戲界面
public GreedSnake() {
// 設(shè)置界面元素
mainFrame = new JFrame("貪吃蛇游戲");
Container cp = mainFrame.getContentPane();
mainFrame.setBounds(600,400,400,300);
//得分牌
labelScore = new JLabel("所得分?jǐn)?shù)為:", JLabel.CENTER);
cp.add(labelScore, BorderLayout.NORTH);
//畫(huà)布
paintCanvas = new Canvas();
paintCanvas.setSize(DEFAULT_WIDTH + 1, DEFAULT_HEIGHT + 1);
paintCanvas.addKeyListener(this);
cp.add(paintCanvas, BorderLayout.CENTER);
JPanel panelButtom = new JPanel();
panelButtom.setLayout(new BorderLayout());
JLabel labelHelp;
// 幫助信息
labelHelp = new JLabel("按 PageUP 或 PageDown 鍵改變速度", JLabel.CENTER);
panelButtom.add(labelHelp, BorderLayout.NORTH);
labelHelp = new JLabel("按 Enter 或 S 鍵重新開(kāi)始游戲", JLabel.CENTER);
panelButtom.add(labelHelp, BorderLayout.CENTER);
labelHelp = new JLabel("按 SPACE 鍵或 P 鍵暫停游戲", JLabel.CENTER);
panelButtom.add(labelHelp, BorderLayout.SOUTH);
cp.add(panelButtom, BorderLayout.SOUTH);
mainFrame.addKeyListener(this);
mainFrame.pack();
mainFrame.setResizable(false);// 設(shè)置窗口大小不能變化
//窗口監(jiān)聽(tīng)器
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
snakeModel.s.stop();
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
});
mainFrame.setVisible(true);
begin();
}
// keyPressed():按鍵檢測(cè)
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();//得到按鍵的值
if (snakeModel.running)//在蛇運(yùn)動(dòng)時(shí)生效
switch ( e.getKeyCode()) {
//改變方向
case KeyEvent.VK_UP:
snakeModel.changeDirection(SnakeModel.UP);
break;
case KeyEvent.VK_DOWN:
snakeModel.changeDirection(SnakeModel.DOWN);
break;
case KeyEvent.VK_LEFT:
snakeModel.changeDirection(SnakeModel.LEFT);
break;
case KeyEvent.VK_RIGHT:
snakeModel.changeDirection(SnakeModel.RIGHT);
break;
//改變速度
case KeyEvent.VK_ADD:
case KeyEvent.VK_PAGE_UP:
snakeModel.speedUp();// 加速
break;
case KeyEvent.VK_SUBTRACT:
case KeyEvent.VK_PAGE_DOWN:
snakeModel.speedDown();// 減速
break;
//改變暫筒购叮或繼續(xù)狀態(tài)
case KeyEvent.VK_SPACE:
case KeyEvent.VK_P:
snakeModel.changePauseState();// 暫停或繼續(xù)
break;
default:
}
// 重新開(kāi)始
if (keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_ENTER) {
snakeModel.running = false;
begin();
}
}
// repaint():繪制游戲界面(包括蛇和食物)
void repaint() {
Graphics g = paintCanvas.getGraphics();
// 加載背景
g.drawImage(new ImageIcon("images\\q1.jpg").getImage(), 0, 0,
DEFAULT_WIDTH, DEFAULT_HEIGHT, null);
// 畫(huà)出蛇
g.setColor(Color.BLACK);
LinkedList<Node> na = snakeModel.nodeArray;
Iterator<Node> it = na.iterator();
while (it.hasNext()) {
Node n = (Node) it.next();
drawNode(g, n);
}
// 畫(huà)出食物
g.setColor(Color.RED);
Node n = snakeModel.food;
drawNode(g, n);
updateScore();
}
// drawNode():繪畫(huà)某一結(jié)點(diǎn)(蛇身或食物)
private void drawNode(Graphics g, Node n) {
g.fillRect(n.x * nodeWidth, n.y * nodeHeight, nodeWidth - 1, nodeHeight - 1);
}
// updateScore():改變計(jì)分牌
public void updateScore() {
String s = "所得分?jǐn)?shù)為: " + snakeModel.score;
labelScore.setText(s);//將得分設(shè)置到得分版
}
// begin():游戲開(kāi)始削饵,放置貪吃蛇
void begin() {
if (snakeModel == null || !snakeModel.running) {
//啟動(dòng)貪吃蛇
snakeModel = new SnakeModel(this, DEFAULT_WIDTH / nodeWidth, DEFAULT_HEIGHT / nodeHeight);
(new Thread(snakeModel)).start();
}
}
}
/**
* 節(jié)點(diǎn)類
* @author HP
*
*/
class Node {
int x;
int y;
//初始化
Node(int x, int y) {
this.x = x;
this.y = y;
}
}
/**
* SnakeModel:貪吃蛇模型
*
*/
class SnakeModel implements Runnable {
GreedSnake gs;
boolean[][] matrix;// 界面數(shù)據(jù)保存在數(shù)組里
LinkedList<Node> nodeArray = new LinkedList<Node>();
Node food;
int maxX;// 最大寬度
int maxY;// 最大長(zhǎng)度
int direction = 2;// 方向
boolean running = false;
int timeInterval = 200;// 間隔時(shí)間(速度)
double speedChangeRate = 0.75;// 速度改變程度
boolean paused = false;// 游戲狀態(tài)
int score = 0;
int countMove = 0;
// UP和DOWN是偶數(shù)岩瘦,RIGHT和LEFT是奇數(shù)
public static final int UP = 2;
public static final int DOWN = 4;
public static final int LEFT = 1;
public static final int RIGHT = 3;
Sound s=new Sound();
// 初始化界面
public SnakeModel(GreedSnake gs, int maxX, int maxY) {
this.gs = gs;
this.maxX = maxX;
this.maxY = maxY;
matrix = new boolean[maxX][];
for (int i = 0; i < maxX; ++i) {
matrix[i] = new boolean[maxY];
Arrays.fill(matrix[i], false);// 沒(méi)有蛇和食物的地區(qū)置false
}
// 初始化貪吃蛇
int initArrayLength = maxX > 20 ? 10 : maxX / 2;
for (int i = 0; i < initArrayLength; ++i) {
int x = maxX / 2 + i;
int y = maxY / 2;
nodeArray.addLast(new Node(x, y));
matrix[x][y] = true;// 蛇身處置true
}
food = createFood();
matrix[food.x][food.y] = true;// 食物處置true
}
// 改變運(yùn)動(dòng)方向
public void changeDirection(int newDirection) {
//上與下都為偶數(shù),左與右都為奇數(shù)窿撬,若方向的值除以2的余數(shù)相等启昧,則方向沖突
if (direction % 2 != newDirection % 2) {// 避免沖突
direction = newDirection;
}
}
// 貪吃蛇運(yùn)動(dòng)函數(shù)
public boolean moveOn() {
Node n = (Node) nodeArray.getFirst();//頭node確定方向
int x = n.x;
int y = n.y;
//頭node的移動(dòng)
switch (direction) {
case UP:
y--;
break;
case DOWN:
y++;
break;
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
}
if ((0 <= x && x < maxX) && (0 <= y && y < maxY)) {
if (matrix[x][y]) {// 吃到食物或者撞到身體
if (x == food.x && y == food.y) {// 吃到食物
nodeArray.addFirst(food);// 在頭部加上一結(jié)點(diǎn)
// 計(jì)分規(guī)則與移動(dòng)長(zhǎng)度和速度有關(guān)
int scoreGet = (10000 - 200 * countMove) / timeInterval;
score += (scoreGet > 0 ? scoreGet : 10);
countMove = 0;
food = createFood();
matrix[food.x][food.y] = true;
return true;
} else
return false;// 撞到身體
} else {// 什么都沒(méi)有碰到
nodeArray.addFirst(new Node(x, y));// 加上頭部
matrix[x][y] = true;
n = (Node) nodeArray.removeLast();// 去掉尾部
matrix[n.x][n.y] = false;
countMove++;
return true;
}
}
return false;// 越界(撞到墻壁)
}
// run():貪吃蛇運(yùn)動(dòng)線程
public void run() {
running = true;
s.play();
while (running) {
try {
Thread.sleep(timeInterval);
} catch (Exception e) {
s.stop();
break;
}
if (!paused) {
if (moveOn()) {// 未結(jié)束
gs.repaint();
} else {// 游戲結(jié)束
s.stop();
JOptionPane.showMessageDialog(null, "GAME OVER", "Game Over", JOptionPane.INFORMATION_MESSAGE);
break;
}
}else{
// s.stop();
}
}
running = false;
}
// createFood():生成食物及放置地點(diǎn)
private Node createFood() {
int x = 0;
int y = 0;
do {
Random r = new Random();
x = r.nextInt(maxX);
y = r.nextInt(maxY);
} while (matrix[x][y]);
return new Node(x, y);
}
// speedUp():加快蛇運(yùn)動(dòng)速度
public void speedUp() {
timeInterval *= speedChangeRate;
}
// speedDown():放慢蛇運(yùn)動(dòng)速度
public void speedDown() {
timeInterval /= speedChangeRate;
}
// changePauseState(): 改變游戲狀態(tài)(暫停或繼續(xù))
public void changePauseState() {
if(paused){
s.play();
}else{
s.stop();
}
paused = !paused;
}
}
Sound
封裝一些對(duì)聲音的處理方法
import java.applet.AudioClip;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.JApplet;
public class Sound{
AudioClip christmas = loadSound("sounds\\貪吃蛇.wav");
public static AudioClip loadSound(String filename) {
URL url = null;
try {
url = new URL("file:" + filename);
}
catch (MalformedURLException e) {;}
return JApplet.newAudioClip(url);
}
public void play() {
christmas.loop();
}
public void stop() {
christmas.stop();
}
}