`
981875739
  • 浏览: 7606 次
  • 性别: Icon_minigender_2
  • 来自: 长沙
社区版块
存档分类
最新评论

2012上半年总结

 
阅读更多

 

转眼间,2012年已经过去一半了,回想一下自己做了些什么呢?可保存的画图板—>弹球游戏 —> 连连看 —> 黄金矿工 —>哈弗曼压缩—>

小学期开始学通信方面的内容,做了简单的群聊

画图板的保存打开:原来画图板的基础上添加了一个FileUtil类

 

package 画图板可保存重绘;

 

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;

 

public class FileUtil implements Config {

 

/**

* 将图片数据保存到指定的位置

* @param path

*            : 要保存数据的位置

*/

public static void saveFile(String path) {

try {

// 创建文件输出流对象

FileOutputStream fos = new FileOutputStream(path);

// 将输出流包装成可写基本类型的数据流

DataOutputStream dos = new DataOutputStream(fos);

// 写图片的高度和宽度

dos.writeInt(DrawListener.data.length);

dos.writeInt(DrawListener.data[0].length);

 

// 遍历二维数组,写数据

for (int i = 0; i < DrawListener.data.length; i++) {

for (int j = 0; j < DrawListener.data[i].length; j++) {

int num = DrawListener.data[i][j];

// 写数据

dos.writeInt(num);

}

}

            //将输出流清空

dos.flush();

//将输出流关闭

fos.close();

 

} catch (Exception ef) {

ef.printStackTrace();

}

 

}

 

/**

* 读取文件中的数据

* @param path

*            要读取的文件

* @return 将读取到的数据作为二位数组返回

*/

public static int[][] readFile(String path) {

 

// 创建文件输入流

try {

//创建文件输入流对象

FileInputStream fis = new FileInputStream(path);

//将文件输入流包装成可写基本类型的数据流

DataInputStream dis = new DataInputStream(fis);

// 读取高度和宽度

int height = dis.readInt();

int width = dis.readInt();

 

// 定义二维数组

int[][] readData = new int[height][width];

//循环读取每个像素点

for (int i = 0; i < height; i++) {

for (int j = 0; j < width; j++) {

// 将数据读入数组

readData[i][j] = dis.readInt();

}

}

//关闭输入流

fis.close();

//返回二维数组

return readData;

} catch (Exception ef) {

ef.printStackTrace();

}

return null;

}

 

}

 

在界面上保存打开的按钮,并添加监听器

在DrawListener中添加了将drawPanel在屏幕上占据的区域的像素点保存成数组

 

        // 调用画图形的方法

shape.draw(g);

// 每绘制一次就将整个drawPanel区域内的所有像素点保存起来

// 得到事件源对象

Object obj = e.getSource();

JPanel drawPanel = (JPanel) obj;

 

// 得到drawPanel的左上角的点

Point point = drawPanel.getLocationOnScreen();

// 得到drawPanel的大小

Dimension dim = drawPanel.getPreferredSize();

 

// 创建矩形区域对象,刚好截取drawPanel在屏幕上所占据的区域

Rectangle rect = new Rectangle(point, dim);

// 从屏幕上获取像素区域,得到一个缓存区的图像对象

BufferedImage img = robot.createScreenCapture(rect);

 

data = new int[dim.height][dim.width];

// 将缓存区的图像对象中的每一个像素的颜色保存起来

for (int i = 0; i < data.length; i++) {

for (int j = 0; j < data[i].length; j++) {

// 得到每个点的颜色(用数字表示的颜色),存入二维数组

data[i][j] = img.getRGB(j, i);

}

}

 

 

连连看之囧事连连

这个游戏设计我认为界面比较可爱,代码部分没有新颖之处,剩余时间用了简单的线程来控制,代码量主要集中在对相同图片是否可以相互消掉的判断上,就是一些逻辑算法,自己的逻辑要清楚,否则会出现错误判断。

界面展示:



 

 

线程游戏—>黄金矿工

这是一个多线程游戏,仿照黄金矿工游戏进行模仿设计的

这个游戏实现经过了比较长的时间

用到了三个线程控制,每个线程只能操作自己的对象,不能对其他类的对象进行操作。

其中比较好的部分是运用rotate();方法对钩子进行摆动控制

以及一些boolean型变量的运用,使得各个阶段可以有效控制

 


 

钩子线程类

 

package 黄金矿工;

 

import javax.swing.ImageIcon;

import javax.swing.JOptionPane;

 

/**

 * 钩子的线程

 * 

 * @author Administrator

 * 

 */

public class HookThread extends Thread {

public static boolean isCatch = false;

public static boolean isWrite = false;

double xx, yy;// 金块或石头的坐标点

double x, y;// 钩子的坐标点

double xc, yc;// 钩子,金块石头每次移动的横纵坐标改变量

double arc = Math.PI / 4;// 钩子的角度.

double arcx = Math.PI / 16;

ImageIcon icon;

static int money = 0;// 金钱数

static int gameTime = 60;// 倒计时

public static int biggolden = 500;

public static int middlegolden = 200;

public static int smallgolden = 50;

public static int stone = 25;

public static int pocket = 250;

public static int num;

 

public boolean isDown = true;

 

boolean isStop = false;

 

public HookThread(ImageIcon icon, int x, int y) {

this.x = x;

this.y = y;

this.icon = icon;

}

 

public void run() {

 

tocatch();

// 设置一个布尔型变量,当时间为0时,toCatch()结束,开始执行下面的语句

if (HookThread.money < 1500) {

JOptionPane.showMessageDialog(null, "GAME OVER    未达到目标分数o(╯□╰)o");

isStop = true;

}

if (HookThread.money >= 1500) {

JOptionPane.showMessageDialog(null, "达到目标分数~~顺利完成任务O(∩_∩)O");

isStop = true;

}

}

 

// 钩子向下运动

public void tocatch() {

long time = 10;

 

xc = -Math.sin(arc);

yc = Math.abs(Math.cos(arc));

while (!isStop) {

if (gameTime == 0) {

isStop = true;

}

 

if (isCatch) {

 

if (isDown) {

// 钩子到达边界抓空

if (x < 4 || x > 625 || y > 440) {

System.out.println("碰边了");

xc = -xc;

yc = -yc;

num = -1;

isDown = false;

 

}

 

// 如果抓到金矿,则返回

if (isDown) {

 

// 鉤子向下運動時,遍历一遍金矿和石头

for (int i = 0; i < GameUI.gases.size(); i++) {

GoldenAndStoneThread gs = GameUI.gases.get(i);

 

// 钩子在运动的过程中,是否可以抓取到东西

// 可以抓取则将钩子的运动位移量赋给金块或石头

 

if (i == 1 || i == 5 || i == 6 || i == 10) {// biggolden

double a = x + 13 - gs.xx;

double b = Math.abs(gs.yy + 5 - y);

if (a > 6 && a < 88 && b < 5) {

xc = -xc;

yc = -yc;

gs.xxc = xc;

gs.yyc = yc;

num = i;

System.out.println("1,5,6,10");

isDown = false;

break;

}

}

if (i == 3 || i == 7 || i == 8 || i == 0 || i == 11) {// middllegolden

// stone

// pocket

double c = x + 13 - gs.xx;

double d = Math.abs(gs.yy + 5 - y);

if (c > 1 && c < 27 && d < 8) {

xc = -xc;

yc = -yc;

gs.xxc = xc;

gs.yyc = yc;

num = i;

System.out.println("3,7,8,0,11");

isDown = false;

break;

}

}

if (i == 2 || i == 4) {// middllegolden

double e = x + 13 - gs.xx;

double f = Math.abs(gs.yy + 5 - y);

if (e > 0 && e < 22 && f < 5) {

xc = -xc;

yc = -yc;

gs.xxc = xc;

gs.yyc = yc;

num = i;

System.out.println("2,4");

isDown = false;

break;

}

}

if (i == 9) {// stone

double g = x + 13 - gs.xx;

double h = Math.abs(gs.yy + 5 - y);

if (g > 0 && g < 57 && h < 5) {

xc = -xc;

yc = -yc;

gs.xxc = xc;

gs.yyc = yc;

num = i;

System.out.println("9");

isDown = false;

break;

}

}

 

}

}

 

}

 

if (!isDown) {

// 返回顶部时加分,金块消失,钩子 开始旋转

if (y < 65) {

 

// 判断金块石头的钱数,响应加分

HookThread.isCatch();

System.out.println(num);

if (num != -1) {

GameUI.gases.remove(num);

}

 

// 改变移动变量,使钩子可以继续伸出去

// 加分

if (num == 0) {// 1

money += pocket;

} else if (num == 1) {// 5

money += biggolden;

} else if (num == 2) {// 4

money += smallgolden;

} else if (num == 3) {// 3

money += middlegolden;

} else if (num == 4) {// 4

money += smallgolden;

} else if (num == 5) {// 5

money += biggolden;

} else if (num == 6) {// 5

money += biggolden;

} else if (num == 7) {// 3

money += middlegolden;

} else if (num == 8) {// 2

money += stone;

} else if (num == 9) {// 6

money += stone;

} else if (num == 10) {// 5

money += biggolden;

} else if (num == 11) {// 1

money += pocket;

} else if (num == 12) {

 

}

 

isDown = true;

}

}

 

// 钩子移动

x += xc;

y += yc;

 

time = 10;

} else {// 钩子旋转

arc += arcx;

xc = -Math.sin(arc);

yc = Math.abs(Math.cos(arc));

if (arc > Math.PI / 4) {

arcx = -arcx;

}

if (arc < -Math.PI / 4) {

arcx = -arcx;

}

time = 100;

}

 

try {

Thread.sleep(time);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

 

/**

* 钩子抓东西时停止转动恢復轉動的方法

*/

public static void isCatch() {

// TODO Auto-generated method stub

isCatch = !isCatch;

}

 

}

金块石头线程类

 

package 黄金矿工;

 

import java.util.ArrayList;

import java.util.Random;

 

import javax.swing.ImageIcon;

 

 

/**

 * 金块与石头的线程

 */

public class GoldenAndStoneThread extends Thread {

double xx, yy;// 金块与石头的坐标点

double xxc = 0, yyc = 0;// 金块与石头的位移量

ImageIcon icon;

int width,height;//图片的高宽

public static Random random = new Random();

public static ArrayList<GoldenAndStoneThread> gases = new ArrayList<GoldenAndStoneThread>();

    public GoldenAndStoneThread(ImageIcon icon,int xx,int yy){

    this.xx=xx;

    this.yy=yy;

    this.icon=icon;

    this.width = icon.getIconWidth();

    this.height = icon.getIconHeight();

   }

 

public void run() {

go();

}

 

public void go() {

while (true) {

xx+=xxc;

yy+=yyc;

try {

Thread.sleep(10);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}


 

时间线程类

 

package 黄金矿工;

 

 

/**

 * 时间线程

 * @author Administrator

 *

 */

public class TimeThread extends Thread {

public TimeThread(){

}

public void run() {

// TODO Auto-generated method stub

while(HookThread.gameTime!=0){

HookThread.gameTime--;//减一秒

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}


 

界面展示:非常感谢龙哥的抠图哦~~

 

里面那几个大金块是我自己扣的,貌似比较丑~~囧哪~~

哈弗曼压缩&解压

实现了压缩和解压的功能,但是经过检测,他的效率好低啊~~不过简单测试可以保证它压缩和解压是正确的

过程中最大功劳应该是Test类,每做一步都要对其进行检测,否则一股脑做到最后结果不正确,都不晓得自己是哪一步出错了。。。

压缩步骤

 

1.读取文件,统计每个字节出现的个数,存入到一个int[256]数组中

如:int[97]=1;(a出现一次)

    int[98]=2;(b出现两次)

2.TreeNode{

  byte b;//字节(a)

  int count;//权值(1)

  String str="";//左0右1

}

将数组中的次数作为权值构造节点,将节点放入优先队列

3.将字节出现的次数作为权值构造哈弗曼树

4.找到所有的叶子节点,得到每个叶子节点的哈弗曼01编码,将01编码存入到String[256]中(码表)

如:String[97]="110"

5.读取文件,将每个字节用相应的01编码表示,得到一个完整长01字符串s

如:s="11011111110101010000"

6.将字符串每八位转为一个整数,作为字节存入到byte[]b=new byte[length]中(length的大小由是否能被8整除决定)

length=20/8+2

最后一位存储补0的个数

倒数第二位存储除8后剩余的编码

7.将码表和byte数组写入到压缩文件中

 

解压步骤反向进行

 

 压缩和解压共同的TreeNode类

 

public class TreeNode {

Object obj;//节点中存储的元素

int value;//权值

String str;//左孩子0右孩子1

TreeNode parent;//父节点

TreeNode leftChild;//左孩子节点

TreeNode rightChild;//右孩子节点

/**

* 构造函数

* @param obj

* @param value

*/

public TreeNode(Object obj,int value,String str){

this.obj=obj;

this.value=value;

this.str=str="";

}

 

 

压缩Compress类

 

package 哈弗曼压缩;

 

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.Comparator;

import java.util.PriorityQueue;

 

/**

 * 压缩文件类

 * 

 * @author Administrator

 * 

 */

 

public class Compress {

 

// 创建文件输出流对象

FileOutputStream fos;

 

/**

* 1.统计指定文件中每个字节出现的次数

* @param path

*/

public int[] count(String path) {

int[] byteCount = new int[255];

try {

 

// 创建文件输出流对象

FileInputStream fis = new FileInputStream(path);

// 将输出流包装成可写的基本类型的流

DataInputStream dis = new DataInputStream(fis);

try {

while (dis.available() > 0) {

int i = dis.read();

byteCount[i]++;

// System.out.println(byteCount[i]);

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

return byteCount;

 

}

 

/**

* 将数组中的次数作为权值构造节点,将节点放入优先队列

* @param arr

* @return

*/

public PriorityQueue<TreeNode> array2Queue(int[] byteCount) {

// 创建排序队列对象,需要自己指定比较器

PriorityQueue<TreeNode> queue = new PriorityQueue<TreeNode>(11,

new MyComparator());

for (int i = 0; i < byteCount.length; i++) {

if (byteCount[i] != 0) {

// 循环创建节点对象

TreeNode node = new TreeNode(i, byteCount[i], "");

queue.add(node);

}

}

return queue;

}

 

/**

* 根据节点优先队列构造哈弗曼树

* @param queue

* @return

*/

public TreeNode creatHfmTree(PriorityQueue<TreeNode> queue) {

while (queue.size() > 1) {

// 取两个权值较小的节点

TreeNode node1 = queue.poll();

TreeNode node2 = queue.poll();

// 根据两个节点的权值和构造一个根节点

TreeNode root = new TreeNode(null, (node1.value + node2.value), "");

// 建立孩子节点与父节点的关系

root.leftChild = node1;

node1.str = "0";

root.rightChild = node2;

node2.str = "1";

node1.parent = root;

node2.parent = root;

 

// 将该根节点存入队列中

queue.add(root);

 

}

// 如果循环结束后,证明队列中还有一个节点,该节点为根节点

TreeNode root = queue.poll();

root.str = "";

 

return root;

}

 

/**

* 得到每一个叶子节点的哈弗曼编码

* @param child

* @param s

* @return

*/

 

public String[] getByteCode(TreeNode root, String s) {

// 码表

String[] SaveString = new String[256];

// 调用得到编码的方法

getCode(SaveString, root, s);

// 打印码表

for (int i = 0; i < SaveString.length; i++)

System.out.println(i + "<>" + SaveString[i]);

return SaveString;

}

 

// 从下向上找

private void getCode(String[] SaveString, TreeNode root, String s) {

if (root != null) {

if (root.obj != null) {

int index = (Integer) root.obj;

SaveString[index] = s;

}

TreeNode left = root.leftChild;

if (left != null)

getCode(SaveString, left,s+left.str);

 

TreeNode right = root.rightChild;

if (right != null)

getCode(SaveString, right, s+ right.str);

 

}

 

}

 

/*

* 读取文件,将文件中的内容转化为01字符串

*/

public String change(String SaveString[], String path) {

String string = "";

try {

// 创建文件输出流对象

FileInputStream fis = new FileInputStream(path);

// 将输出流包装成可写的基本类型的流

DataInputStream dis = new DataInputStream(fis);

try {

while (dis.available() > 0) {

int i = dis.read();

String a = SaveString[i];

string = string + a;

// System.out.println(byteCount[i]);

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return string;

}

 

/**

* 将一个八位的字符串转成一个整数

* @param s

* @return

*/

public byte changeString(String s) {

return (byte) (((byte) s.charAt(0) - 48) * 128

+ ((byte) s.charAt(1) - 48) * 64 + ((byte) s.charAt(2) - 48)

* 32 + ((byte) s.charAt(3) - 48) * 16

+ ((byte) s.charAt(4) - 48) * 8 + ((byte) s.charAt(5) - 48) * 4

+ ((byte) s.charAt(6) - 48) * 2 + ((byte) s.charAt(7) - 48));

}

 

/**

* 将字符串每八位转为一个整数后,作为字节存入到byte[]b=new byte[length]中

* @param string

* @return

*/

public byte[] StringToByteArray(String string) {

// 得到01字符串的长度

char[] c = string.toCharArray();// 将字节串str转化为字符数组c

int len = c.length;// 字符串字符的个数

int more = len % 8;// 余数

int length = len / 8;// 商

byte[] b;

String x = "";// 每八个01的编码

// 如果可以被8整除

if (more == 0) {

b = new byte[length+1];

 

for (int i = 0; i < length; i++) {

for (int j = i * 8; j < (i + 1) * 8; j++) {

x = x + c[j];

}

System.out.println("===================" + x);

b[i] = changeString(x);

x="";

}

b[length]=0;//补了零个0;

} else {//不可以被8整除

b = new byte[length + 2];

for(int i=0;i<length;i++){

for(int j=i*8;j<(i+1)*8;j++){

x=x+c[j];

}

System.out.println(">>>>>>>>>>>>>>>>>>>>"+x);

b[i]=changeString(x);

x="";

}

for(int a=0;a<more;a++){

x=x+c[length*8+a];

}

for(int d=more;d<8;d++){

x=x+"0";

}

System.out.println(">>>==========>>>>>>>"+x);

b[length]=changeString(x);

b[length+1]=(byte)(8-more);

}

 

return b;

}

/**

* 将码表和byte数组写入到压缩文件中 SaveString 和b

* @param path

* @param SaveString

* @param b

*/

public void writeIn(String path,String [] SaveString,byte[] b,TreeNode root) {

try {

// 创建文件输出流对象

FileOutputStream fos = new FileOutputStream(path);

// 将输出流包装成可写基本类型的数据流

DataOutputStream dos = new DataOutputStream(fos);

// //写入哈弗曼树

// printTree(root);

// dos.writeBytes(root);

//写入SaveString有多少字节不是空的

int num = 0;

for(int i=0;i<255;i++){

if(SaveString[i]!=null){

num++;

}

}

System.out.println("_____________________________________________________________________"+num);

dos.writeInt(num);

//先写入SaveString

for(int i=0;i<255;i++){

if(SaveString[i]!=null){

System.out.println("OK"+SaveString[i].length());

int l=SaveString[i].length();

//写入97,3,110

dos.writeByte(i);

dos.writeInt(l);

dos.writeBytes(SaveString[i]);

System.out.println("HAHA"+i+" "+l+" "+SaveString[i]);

}

}

//写入 b

   for(int j=0;j<b.length;j++){

    dos.writeByte(b[j]);

    System.out.println("GOGO"+b[j]);

   }

 

            //将输出流清空

dos.flush();

//将输出流关闭

fos.close();

 

} catch (Exception ef) {

ef.printStackTrace();

}

 

}

 

 

/**

* 实现的比较器类

* @author Administrator

*/

class MyComparator implements Comparator<TreeNode> {

 

@Override

public int compare(TreeNode o1, TreeNode o2) {

// TODO Auto-generated method stub

return o1.value - o2.value;

}

 

}

 

/**

* 遍历树的方法(先序遍历)

* @param root

*/

public void printTree(TreeNode root) {

// 只要数不空就执行

if (root != null) {

// 得到根节点的元素

int va = root.value;

System.out.println(va + "<>" + root.str);

// 得到根节点的左孩子节点

TreeNode leftNode = root.leftChild;

// 递归左树

printTree(leftNode);

// 得到根节点的右孩子节点

TreeNode rightNode = root.rightChild;

// 递归右树

printTree(rightNode);

 

}

}

 

}

 

解压Decompress类

 

package Decompress解压1;

 

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.util.Comparator;

import java.util.HashMap;

import java.util.PriorityQueue;

 

public class Decompress {

 

/**

* 读取byte[] b

*/

 

public byte[] readBytes(String path) {

byte[] b = null;

try {

// 创建文件输出流对象

FileInputStream fis = new FileInputStream(path);

// 将输出流包装成可写的基本类型的流

DataInputStream dis = new DataInputStream(fis);

 

int lenZ = dis.available();

System.out.println();

// 先跳过256个Int

dis.skip(256 * 4);

 

int len = dis.available();

 

b = new byte[len];

 

for (int i = 0; i < b.length; i++) {

b[i] = dis.readByte();

}

 

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return b;

}

 

/**

* 读取码表

* @param path

* @return

*/

public int[] readCount(String path) {

int[] byteCount = new int[256];

try {

// 创建文件输出流对象

FileInputStream fis = new FileInputStream(path);

// 将输出流包装成可写的基本类型的流

DataInputStream dis = new DataInputStream(fis);

 

// System.out.println("WOW");

for (int i = 0; i < 256; i++) {

byteCount[i] = dis.readInt();

}

 

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return byteCount;

}

 

/**

* 将8位10字符串前面缺0的补上0

* @param str

* @return

*/

public String addZero(String str) {

int strLen = str.length();

int zeroNum;

if (strLen < 8) {// 若字符串长度小于8则补0

zeroNum = 8 - strLen;

for (int i = 0; i < zeroNum; i++) {

str = "0" + str;

}

}

return str;

}

 

/**

* 将整型数组还原成之前的10串,即文件内容的哈夫曼编码

* @param n

* @return

*/

public String InttoBinaryString(byte[] bs) {

 

String BinaryStr = "";

for (int i = 0; i < bs.length - 1; i++) {

String str = Integer.toBinaryString(bs[i]);

if (str.length() < 8) {

 

for (int j = 0; j < 8 - str.length(); j++) {

str = "0" + str;

}

 

} else if (str.length() > 8) {

 

str=str.substring(str.length()-8);

}

 

BinaryStr = BinaryStr + str;

}

int BinaryStrLen = BinaryStr.length();// 得到为减0前的字符串大小

byte zeroSub = bs[bs.length - 1];// 之前在末尾补0的个数,现在减去

System.out.println(bs[bs.length - 1]);

BinaryStr = BinaryStr.substring(0, BinaryStrLen - zeroSub);

System.out.println("<BinaryStr>"+BinaryStr);

return BinaryStr;

}

 

/**

* @param path

*            解压的路径

* @param BinaryStr

*            01串

* @param SaveString

*            码表

*/

public void writeIn(String path, String BinaryStr,

HashMap<String, Integer> SaveString) {

// 创建文件输出流对象

 

try {

FileOutputStream fos = new FileOutputStream(path);

DataOutputStream dos = new DataOutputStream(fos);

String str = "";

int index = 0;

// System.out.println(BinaryStr);

while (index < BinaryStr.length()) {

str += BinaryStr.charAt(index);

// 如果码表中包含该01串

if (SaveString.containsKey(str)) {

// System.out.println(">>"+str);

// 就得到01传对应的字节

int b = SaveString.get(str);

dos.write(b);

str = "";

}

index++;

 

}

// 将输出流清空

dos.flush();

// 将输出流关闭

fos.close();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

// 将输出流包装成可写基本类型的数据流

 

}

 

/**

* 将数组中的次数作为权值构造节点,将节点放入优先队列

* @param arr

* @return

*/

public PriorityQueue<TreeNode> array2Queue(int[] byteCount) {

// 创建排序队列对象,需要自己指定比较器

PriorityQueue<TreeNode> queue = new PriorityQueue<TreeNode>(11,

new MyComparator());

for (int i = 0; i < byteCount.length; i++) {

if (byteCount[i] != 0) {

// 循环创建节点对象

TreeNode node = new TreeNode(i, byteCount[i], "");

queue.add(node);

}

}

return queue;

}

 

/**

* 根据节点优先队列构造哈弗曼树

* @param queue

* @return

*/

public TreeNode creatHfmTree(PriorityQueue<TreeNode> queue) {

while (queue.size() > 1) {

// 取两个权值较小的节点

TreeNode node1 = queue.poll();

TreeNode node2 = queue.poll();

// 根据两个节点的权值和构造一个根节点

TreeNode root = new TreeNode(null, (node1.value + node2.value), "");

// 建立孩子节点与父节点的关系

root.leftChild = node1;

node1.str = "0";

root.rightChild = node2;

node2.str = "1";

node1.parent = root;

node2.parent = root;

 

// 将该根节点存入队列中

queue.add(root);

 

}

// 如果循环结束后,证明队列中还有一个节点,该节点为根节点

TreeNode root = queue.poll();

root.str = "";

 

return root;

}

 

/**

* 得到每一个叶子节点的哈弗曼编码

* @param child

* @param s

* @return

*/

 

public HashMap<String, Integer> getByteCode(TreeNode root, String s) {

// 码表

HashMap<String, Integer> SaveString = new HashMap<String, Integer>();

// 调用得到编码的方法

getCode(SaveString, root, s);

return SaveString;

}

 

// 从下向上找

private void getCode(HashMap<String, Integer> SaveString, TreeNode root,

String s) {

if (root != null) {

if (root.obj != null) {

int index = (Integer) root.obj;

SaveString.put(s, index);

}

TreeNode left = root.leftChild;

if (left != null)

getCode(SaveString, left, s + left.str);

 

TreeNode right = root.rightChild;

if (right != null)

getCode(SaveString, right, s + right.str);

 

}

 

}

 

/**

* 实现的比较器类

* @author Administrator

*/

class MyComparator implements Comparator<TreeNode> {

 

@Override

public int compare(TreeNode o1, TreeNode o2) {

// TODO Auto-generated method stub

return o1.value - o2.value;

}

 

}

 

/**

* 遍历树的方法(先序遍历)

* @param root

*/

public void printTree(TreeNode root) {

// 只要数不空就执行

if (root != null) {

// 得到根节点的元素

int va = root.value;

System.out.println(va + "<>" + root.str);

// 得到根节点的左孩子节点

TreeNode leftNode = root.leftChild;

// 递归左树

printTree(leftNode);

// 得到根节点的右孩子节点

TreeNode rightNode = root.rightChild;

// 递归右树

printTree(rightNode);

 

}

}

 

}

通信群聊

要分清客户端与服务器之间的关系,以及各自方法的使用



服务器

ChatServer类

 

package tx0630服务器2;

 

import java.net.ServerSocket;

import java.net.Socket;

import java.util.ArrayList;

 

public class ChatServer {

 

// 保存处理进处连结的线程对象

public static ArrayList<ServerThread> cts = new ArrayList<ServerThread>();

 

/**

* 在指定端口上创建服务器

* @param port

*            服务器所在的端口号

*/

public void setServer(int port) {

 

try {

// 创建一个服务器对象

ServerSocket s = new ServerSocket(port);

while (true) {

// 等待连结进入

Socket chatClient = s.accept();


// 创建线程对象,去处理

ServerThread ct = new ServerThread(chatClient);

ct.start();

cts.add(ct);// 保存到队列中

}

 

} catch (Exception ef) {

ef.printStackTrace();

}

 

}

 

/**

* @param args

*/

public static void main(String[] args) {

ChatServer ss = new ChatServer();

ss.setServer(1000);

 

}

 

}


 

 

ServerThread类

 

package tx0630服务器2;

 

import java.io.InputStream;

import java.io.OutputStream;

import java.net.Socket;

import java.util.ArrayList;

import java.util.Date;

 

//处理进入的连结对象的线程,:每进入一个连结,就创建一个处理线程对象

//每个客户端,在服务器端,都由一个处理线程对象代表

public class ServerThread extends Thread {

public static native long currentTimeMillis();

 

private Socket socket;

private OutputStream ous;

 

public ServerThread(Socket socket) {

try {

this.socket = socket;

ous = socket.getOutputStream();

} catch (Exception ef) {

ef.printStackTrace();

}

}

 

// 给我所代表的客户机发送一条消息

public void sendMsg2Me(String msg) {

try {

msg += "\r\n";

ous.write(msg.getBytes());

 

} catch (Exception ef) {

ef.printStackTrace();

}

 

}

 

// 服务器统计在线人数

public int Count() {

int num = ChatServer.cts.size();

return num;

}

 

public void run() {

// 处理通信过程:

processChat(this.socket);

}

 

/**

* 处理进入的客户端连结对象:处理通信流程

* @param client

*/

private void processChat(Socket chatClient) {

try {

// 得取输入输出流,读写数据

InputStream ins = chatClient.getInputStream();

 

// 通信流程实现阶段:最简流程

String msg = "hello!欢迎进入QQChat";// 发给连结上来的客户机

sendMsg2Me(msg);

int num = Count();

for (int i = 0; i < ChatServer.cts.size(); i++) {

ServerThread ct = ChatServer.cts.get(i);

ct.sendMsg2Me("当前在线人数" + num);

}

 

String inMsg = "";

while (!"*".equals(inMsg)) {

inMsg = readMsg(ins);

System.out.println("recive Msg:" + inMsg);

 

// 遍历cts中的每一个对象,发送消息

for (int i = 0; i < ChatServer.cts.size(); i++) {

ServerThread ct = ChatServer.cts.get(i);

Date d = new Date();

// 在默认时区下输出日期和时间值

System.out.println(d);

ct.sendMsg2Me(d + inMsg);

}

if(inMsg=="over"){

msg = "有人要下线了,通信结束!";// 发给连结上来的客户机

sendMsg2Me(msg);

ins.close();

ous.close();

chatClient.close();

}

}

 

} catch (Exception ef) {

ef.printStackTrace();

}

}

 

 

/**

* 从输入流上读取字节,直到读到以*字节结尾的,将读到的字节转为字符串返回

* @param ins

*            :读取的输入流对象

* @return 读到的字符串

*/

private String readMsg(InputStream ins) {

try {

// 读取:

int t = ins.read();

ArrayList<Byte> ds = new ArrayList();

while (t != '~') {

System.out.println("读取的字节是: " + t);

ds.add((byte) t);

t = ins.read();

}

// 将前面收到的字节,都转成一个字符串:

byte[] dd = new byte[ds.size()];

for (int i = 0; i < dd.length; i++) {

dd[i] = ds.get(i);

}

// 转为字符串

String inMsg = new String(dd);

return inMsg;

} catch (Exception ef) {

ef.printStackTrace();

System.out.println("从输入流上读取字符串时出错!");

}

return "error";

}

 

}

客户机

MainClientUI()界面设计代码略

 

 

package tx0630客户机2;

 

import java.awt.TextArea;

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.Socket;

 

 

/**

 * 客户端

 */

public class NetClient extends Thread {

private String UserName;

private String serverIP;//服务器IP

private int port;//服务器端口

private OutputStream out;//到服务器的输出流

private BufferedReader brd;//到服务器的输入流,以\r\n结尾

private TextArea jta_recived;//从界面上传来的显示接收到的消息的组件

/**

* 构造函数,传入服务器的IP和端口和显示组件

* @param serverIP

* @param port

* @param jta_input

*/

public NetClient(String UserName,String serverIP,int port,TextArea jta_input){

this.UserName=UserName;

this.serverIP=serverIP;

this.port=port;

this.jta_recived=jta_input;

}

public String getUserName(){

return UserName;

}

/**

* 连接并判断连接服务器是否成功

* @return

*/

public boolean conn2Server(){

try{

//创建一个服务端的SOCKET对象

Socket client=new Socket(this.serverIP,this.port);

//获取输入输出流

InputStream ins=client.getInputStream();

brd=new BufferedReader(new InputStreamReader(ins));

out=client.getOutputStream();

return true;

}catch(Exception ef){

ef.printStackTrace();

}

return false;

}

/**

* 注册服务器

*/

public boolean registerServer(String name,String pwd){

 

try{

//发送登陆

out.write("register\r\n".getBytes());

//发送用户名

name+="\r\n";

out.write(name.getBytes());

out.flush();

//发送密码

pwd+="\r\n";

out.write(pwd.getBytes());

out.flush();

String register=brd.readLine();

if(register.equals("false")){

return false;

}else{

return true;

}

}catch(Exception ef){

ef.printStackTrace();

}

return false;

}

/**

* 登陆服务器

* @param name

* @param pwd

* @return

*/

public boolean loginServer(String name,String pwd){

try{

//发送登陆

out.write("login\r\n".getBytes());

//发送用户名

name+="\r\n";

out.write(name.getBytes());

out.flush();

//发送密码

pwd+="\r\n";

out.write(pwd.getBytes());

out.flush();

String login=brd.readLine();

if(login.equals("false")){

return false;

}else{

return true;

}

}catch(Exception ef){

ef.printStackTrace();

}

return false;

}

/**

* 找回密码

*/

public String backpwd(String name){

try{

//发送登陆

out.write("backpwd\r\n".getBytes());

//发送用户名

name+="\r\n";

out.write(name.getBytes());

out.flush();

String backpwd=brd.readLine();

return backpwd;

}catch(Exception ef){

ef.printStackTrace();

}

return "用户名不存在";

}

/**

* 线程处理读取服务器的阻塞问题

*/

public void run(){

while(true){

this.readFromServer();

}

}

/**

* 读消息

*/

public void readFromServer(){

try{

String input=brd.readLine();

//将收到的消息显示到界面上

jta_recived.append(input+"\r\n");

//jta_recived.setLineWrap(true);

}catch(Exception ef){

ef.printStackTrace();

}

}

/**

* 发消息

*/

public void sendMsg(String msg){

try{

msg=msg+"~\r\n";

this.out.write(msg.getBytes());

this.out.flush();

}catch(Exception ef){

ef.printStackTrace();

}

}

 

}


 


 

这段时间自己独立完成的东西比较少,很多都是在老师的帮助指导下完成的,以后我会自己多动脑,一步步锻炼自己,挖掘自己的潜力,独立完成一个项目。


 

  • 大小: 137.2 KB
  • 大小: 145.8 KB
  • 大小: 60.2 KB
  • 大小: 59.4 KB
  • 大小: 128.6 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics