import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.util.Vector;
import javax.swing.JFrame;
/**
* 打字游戏
* @author
*
*/
public class WordGame extends Window implements KeyListener, Runnable {
//保存屏幕的宽和高
int width, height;
//内存位图对象
BufferedImage buf;
//创建图形对象用来绘制窗体
Graphics gc;
//游戏是否继续
boolean play = true;
//创建一个集合来保存当前屏幕上的字母
Vector<WordFactory> keys = new Vector<WordFactory>();
//线程中循环执行的次数
int count;
//当前窗体的字体
Font fontSize = new Font("楷体", 0, 60);
//程序的入口点
public static void main(String[] args){
//创建一个窗体对象
JFrame help = new JFrame("打字练习");
//显示窗体
help.setVisible(true);
//设置窗体的关闭为默认关闭
help.setDefaultCloseOperation(3);
//给当前窗体添加一个键盘按键监听器
help.addKeyListener(new WordGame(help));
}
/*
* 当前类的Constructor中初始化窗体对象
*/
private WordGame(Frame f) {
super(f);
//此对象封装了当前窗体的宽度和高度
Dimension s = getToolkit().getScreenSize();
width = (int) s.getWidth();
height = (int) s.getHeight();
//设置当前窗体的大小
this.setBounds(0, 0, width, height);
//创建一个和当前窗体一样大小的位图
this.buf = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//通过位图创建一个图形
gc = buf.getGraphics();
//显示窗体
this.setVisible(true);
//当前始终保持在最前端
this.setAlwaysOnTop(true);
//开启线程用来创建字母
new Thread(this).start();
}
public void keyTyped(KeyEvent e) {
}
/*
* 键盘按下事件(线程同步)
*/
public synchronized void keyPressed(KeyEvent e) {
//判断用户是否按下了Esc键
if (e.getKeyCode() == 27) {
//游戏结束
play = false;
//释放当前窗口
this.dispose();
//系统退出
System.exit(0);
}
//获取用户按下的键
char inputWord = e.getKeyChar();
//如果键的范围在'a'-'z'之间,就消除屏幕上的字母
if (inputWord >= 'a' && inputWord <= 'z') {
String l = "" + inputWord;
//遍历集合
for (int i = 0; i < keys.size(); i++) {
//判断用户输入的字母在集合中是否存在
if (l.equals(((WordFactory) keys.elementAt(i)).word)) {
//从集合中删除用户输入的字母
keys.removeElementAt(i);
return;
}
}
}
}
public void keyReleased(KeyEvent e) {
}
/**
* 窗体的刷新方法,用来控制字母的下落
*/
@Override
public void update(Graphics g) {
//重新绘制屏幕的背景
gc.setColor(Color.BLACK);
//重绘大小
gc.fillRect(0, 0, width, height);
//重绘字体
gc.setFont(fontSize);
//定义一个字母对象
WordFactory o;
//遍历当前集合中的所有对象
for (int i = 0; i < keys.size(); i++) {
//取出对象
o = keys.elementAt(i);
//并判断当前字母的纵坐标是否小于当前窗体的高度
if (o.y > height - 10) {
//从集合中删除该字母
keys.removeElementAt(i);
}
//重绘该字母的颜色
gc.setColor(o.color);
//重绘该字母的值和横坐标以及纵坐标加上6个像素
gc.drawString(o.word, o.x, o.y += 6);
}
//重新以位图渲染当前图形
g.drawImage(buf, 0, 0, null);
}
//重写Runnable接口的run方法,用来添加新的字母
public void run() {
while (play) {
try {
count++;
//每800毫秒添加一个新的字母
if (count % 10 == 0) {
//向当前集合中添加一个新的字母
keys.add(WordFactory.getinstance(width));
}
//当前运行的线程睡眠80毫秒
Thread.sleep(80);
//重新绘制当前组件
repaint();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
/**
* 字母工厂
* @author 林志霄
*
*/
class WordFactory {
//字母出现的横坐标和纵坐标
int x, y;
//字母的随机颜色
Color color;
//字母的值
String word;
//创建一个随机数对象
static java.util.Random r = new java.util.Random();
//根据屏幕的宽度创建字母新的字母
public static WordFactory getinstance(int maxX) {
//创建一个新的字母
WordFactory a = new WordFactory();
//一个有26个字母,生成1-26之间的
int b = r.nextInt(26);
//将刚才生成的整数加上'a'的ASCII码生成一个随机的字母,范围在'a'-'z'之间
a.word = "" + (char) (b + 'a');
//随机生成一个字母的位置,当前屏幕宽度减掉30个像素
a.x = r.nextInt(maxX-30);
//使用随机数,生成随机的颜色分量,创建一个颜色对象
a.color = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
return a;
}
}
|
|