📄 hangman.java
字号:
import java.awt.*;
import java.applet.*;
import java.io.*;
import java.net.*;
public class Hangman extends java.applet.Applet implements Runnable {
/* 猜错的最大次数*/
final int maxTries = 5;
/* 保密单词的最大长度 */
final int maxWordLen = 20;
/* 用来存放保密单词的缓存 */
char secretWord[];
/* 保密单词的长度 */
int secretWordLen;
/* 用来存放用户输入的错误字母的缓存,这些字母不在屏幕上显示 */
char wrongLetters[];
/* 当前的猜错次数 */
int wrongLettersCount;
/* 用来存放用户猜对的字母的缓存 */
char word[];
/* 在'word'中的正确字母数量. */
int wordLen;
/* 用来显示猜对字母的字体颜色 */
Font wordFont;
FontMetrics wordFontMetrics;
/* Duke在绞刑架上的一系列图像 */
Image hangImages[];
final int hangImagesWidth = 39;
final int hangImagesHeight = 58;
// 与Duke跳舞相关的变量
/* 该线程使Duke跳舞 */
Thread danceThread;
/* 完成跳舞动作所需的图片 */
Image danceImages[];
private int danceImageWidths[] = { 70, 85, 87, 90, 87, 85, 70 };
/* 整个跳舞图片的最大宽度和最大高度*/
int danceHeight = 68;
/* 该变量存放跳舞动画的有效图片*/
int danceImagesLen = 0;
/* 动画坐标,因为产生动画的图片大小不一致,需要进行调整 */
private int danceImageOffsets[] = { 8, 0, 0, 8, 18, 21, 27 };
/* 该变量代表图片的播放顺序,从而产生跳舞动画效果 */
private int danceSequence[] = { 3, 4, 5, 6, 6, 5, 6, 6, 5, 4, 3,
2, 1, 0, 0, 1, 2, 2, 1, 0, 0, 1, 2 };
/* 这是当前的图片次序,其中-1表示Duke还没有开始跳舞*/
int danceSequenceNum = -1;
/* 该变量用来调整Duke跳舞时的x位置 */
int danceX = 0;
/* 该变量指定Duke当前在x上的跳舞移动方向. 1=>right and -1=>left. */
int danceDirection = 1;
/* 跳舞时的尖叫声*/
AudioClip danceMusic;
/**
* 初始化applet. 重新设置大小,载入所需图片
*/
public void init() {
int i;
// 载入跳舞动画
danceMusic = getAudioClip(getCodeBase(), "rsrc/dance.au");
danceImages = new Image[40];
for (i = 1; i < 8; i++) {
Image im = getImage(getCodeBase(), "rsrc/dancing-duke/T" + i + ".gif");
if (im == null) {
break;
}
danceImages[danceImagesLen++] = im;
}
// 载入一系列图形
hangImages = new Image[maxTries];
for (i=0; i<maxTries; i++) {
hangImages[i] = getImage(getCodeBase(), "rsrc/hanging-duke/h"+(i+1)+".gif");
}
// 初始化各个单词缓存
wrongLettersCount = 0;
wrongLetters = new char[maxTries];
secretWordLen = 0;
secretWord = new char[maxWordLen];
word = new char[maxWordLen];
wordFont = new java.awt.Font("Courier", Font.BOLD, 24);
wordFontMetrics = getFontMetrics(wordFont);
resize((maxWordLen+1) * wordFontMetrics.charWidth('M') + maxWordLen * 3,
hangImagesHeight * 2 + wordFontMetrics.getHeight());
}
/**
* 在屏幕上绘制图像.
*/
public void paint(Graphics g) {
int imageW = hangImagesWidth;
int imageH = hangImagesHeight;
int baseH = 10;
int baseW = 30;
Font font;
FontMetrics fontMetrics;
int i, x, y;
// 绘制绞刑架
g.drawLine(baseW/2, 0, baseW/2, 2*imageH - baseH/2);
g.drawLine(baseW/2, 0, baseW+imageW/2, 0);
// 绘制绞绳
g.drawLine(baseW+imageW/2, 0, baseW+imageW/2, imageH/3);
// 绘制绞刑架地基
g.fillRect(0, 2*imageH-baseH, baseW, baseH);
// 错误字母列表
font = new java.awt.Font("Courier", Font.PLAIN, 15);
fontMetrics = getFontMetrics(font);
x = imageW + baseW;
y = fontMetrics.getHeight();
g.setFont(font);
g.setColor(Color.red);
for (i=0; i<wrongLettersCount; i++) {
g.drawChars(wrongLetters, i, 1, x, y);
x += fontMetrics.charWidth(wrongLetters[i])
+ fontMetrics.charWidth(' ');
}
if (secretWordLen > 0) {
// 为给出的保密单词画下划线
int Mwidth = wordFontMetrics.charWidth('M');
int Mheight = wordFontMetrics.getHeight();
g.setFont(wordFont);
g.setColor(Color.black);
x = 0;
y = size().height - 1;
for (i=0; i<secretWordLen; i++) {
g.drawLine(x, y, x + Mwidth, y);
x += Mwidth + 3;
}
// 将猜对的字母显示在屏幕上
x = 0;
y = size().height - 3;
g.setColor(Color.blue);
for (i=0; i<secretWordLen; i++) {
if (word[i] != 0) {
g.drawChars(word, i, 1, x, y);
}
x += Mwidth + 3;
}
if (wordLen < secretWordLen && wrongLettersCount > 0) {
// 绘制在绞刑架上的Duke
g.drawImage(hangImages[wrongLettersCount-1],
baseW, imageH/3, this);
}
}
}
public void update(Graphics g) {
if (wordLen == 0) {
g.clearRect(0, 0, size().width, size().height);
paint(g);
} else if (wordLen == secretWordLen) {
if (danceSequenceNum < 0) {
g.clearRect(0, 0, size().width, size().height);
paint(g);
danceSequenceNum = 0;
}
updateDancingDuke(g);
} else {
paint(g);
}
}
void updateDancingDuke(Graphics g) {
int baseW = 30;
int imageH = hangImagesHeight;
int danceImageNum = danceSequence[danceSequenceNum];
// 首先清理Duke当前的图形
g.clearRect(danceX+baseW, imageH*2 - danceHeight,
danceImageOffsets[danceImageNum]+danceImageWidths[danceImageNum],
danceHeight);
// 更新跳舞的位置
danceX += danceDirection;
if (danceX < 0) {
danceX = danceDirection = (int)Math.floor(Math.random() * 12) + 5;
} else if (danceX + baseW > size().width / 2) {
danceDirection *= -1;
} else if (Math.random() > .9f) {
danceDirection *= -1;
}
// 更新跳舞动画
danceSequenceNum++;
if (danceSequenceNum >= danceSequence.length) {
danceSequenceNum = 0;
}
// 现在开始画Duke的新图像
danceImageNum = danceSequence[danceSequenceNum];
if ((danceImageNum < danceImagesLen) && (danceImages[danceImageNum] != null)) {
g.drawImage(danceImages[danceImageNum],
danceX+baseW+danceImageOffsets[danceImageNum],
imageH*2 - danceHeight, this);
}
}
public boolean keyDown(java.awt.Event evt, int key) {
int i;
boolean found = false;
// 如果用户已经胜利或者失败,就开始新游戏.
if (secretWordLen == wordLen || wrongLettersCount == maxTries) {
newGame();
return true;
}
// 判断输入的是否为有效字母
if (key < 'a' || key > 'z') {
play(getCodeBase(), "rsrc/beep.au");
return true;
}
// 判断用户输入的字母是否已经在正确字母列表中存在
for (i=0; i<secretWordLen; i++) {
if (key == word[i]) {
found = true;
play(getCodeBase(), "rsrc/ding.au");
return true;
}
}
// 判断用户输入的字母是否早就在错误字母列表中
if (!found) {
for (i=0; i<maxTries; i++) {
if (key == wrongLetters[i]) {
found = true;
play(getCodeBase(), "rsrc/ding.au");
return true;
}
}
}
// 是否为保密单词中的字母?
if (!found) {
for (i=0; i<secretWordLen; i++) {
if (key == secretWord[i]) {
word[i] = (char)key;
wordLen++;
found = true;
}
}
if (found) {
if (wordLen == secretWordLen) {
play(getCodeBase(), "rsrc/whoopy.au");
startDukeDancing();
} else {
play(getCodeBase(), "rsrc/ah.au");
}
}
}
// 错误字母,将它添加到wrongLetters中
if (!found) {
if (wrongLettersCount < wrongLetters.length) {
wrongLetters[wrongLettersCount++] = (char)key;
if (wrongLettersCount < maxTries) {
play(getCodeBase(), "rsrc/ooh.au");
} else {
// 给出正确答案
for (i=0; i<secretWordLen; i++) {
word[i] = secretWord[i];
}
play(getCodeBase(), "rsrc/scream.au");
}
}
}
if (wordLen == secretWordLen) {
danceSequenceNum = -1;
}
repaint();
return true;
}
/**
* 获取焦点并且重新开始游戏.
*/
public boolean mouseDown(java.awt.Event evt, int x, int y) {
int i;
// 获取鼠标键按下事件
requestFocus();
if (secretWordLen > 0 &&
(secretWordLen == wordLen || wrongLettersCount == maxTries)) {
newGame();
} else {
play(getCodeBase(), "rsrc/beep.au");
}
return true;
}
/**
* 开始新游戏.挑选一个新的保密单词,
* 并且清除所有的缓存
*/
public void newGame() {
int i;
// 停止动画线程
danceThread = null;
// 随机给出一个保密单词
String s = wordlist[(int)Math.floor(Math.random() * wordlist.length)];
secretWordLen = Math.min(s.length(), maxWordLen);
for (i=0; i<secretWordLen; i++) {
secretWord[i] = s.charAt(i);
}
// 清除word缓存
for (i=0; i<maxWordLen; i++) {
word[i] = 0;
}
wordLen = 0;
for (i=0; i<maxTries; i++) {
wrongLetters[i] = 0;
}
wrongLettersCount = 0;
repaint();
}
/**
* 开始applet.
*/
public void start() {
requestFocus();
// 当用户胜利或者失败时,开始新游戏;否则继续原来的游戏
if (secretWordLen == wordLen || wrongLettersCount == maxTries) {
newGame();
}
}
/**
* 停止applet.停止跳舞线程.
*/
public void stop() {
danceThread = null;
}
/**
* 运行Duke的跳舞线程.该方法被类线程调用.
*/
public void run() {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
// 启动跳舞的音乐
danceMusic.loop();
// 开始技术并且激活paint()方法
while (size().width > 0 && size().height > 0 && danceThread != null) {
repaint();
try {Thread.sleep(100);} catch (InterruptedException e){}
}
//当跳舞完毕时,停止音乐
danceMusic.stop();
}
/**
* 启动跳舞动画
*/
private void startDukeDancing () {
if (danceThread == null) {
danceThread = new Thread(this);
danceThread.start();
}
}
/* 本程序的保密单词库 */
String wordlist[] = {
"abstraction",
"ambiguous",
"arithmetic",
"backslash",
"bitmap",
"circumstance",
"combination",
"consequently",
"consortium",
"decrementing",
"dependency",
"disambiguate",
"dynamic",
"encapsulation",
"equivalent",
"expression",
"facilitate",
"fragment",
"hexadecimal",
"implementation",
"indistinguishable",
"inheritance",
"internet",
"java",
"localization",
"microprocessor",
"navigation",
"optimization",
"parameter",
"patrick",
"pickle",
"polymorphic",
"rigorously",
"simultaneously",
"specification",
"structure",
"lexical",
"likewise",
"management",
"manipulate",
"mathematics",
"hotjava",
"vertex",
"unsigned",
"traditional"};
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -