1
22
23 package com.liferay.applets.hangman;
24
25 import java.applet.Applet;
26 import java.applet.AudioClip;
27
28 import java.awt.Color;
29 import java.awt.Font;
30 import java.awt.FontMetrics;
31 import java.awt.Graphics;
32 import java.awt.Image;
33 import java.awt.MediaTracker;
34 import java.awt.event.KeyEvent;
35 import java.awt.event.KeyListener;
36
37 import java.util.ArrayList;
38 import java.util.List;
39 import java.util.StringTokenizer;
40
41
47 public class Hangman extends Applet implements KeyListener {
48
49 private static final int MEDIA_TRACKER_HANG = 0;
50
51 private static final int MEDIA_TRACKER_DANCE = 1;
52
53 private static final int TOTAL_IMAGES_HANG = 5;
54
55 private static final int TOTAL_IMAGES_DANCE = 5;
56
57 private static final int HANG_WIDTH = 42;
58
59 private static final int HANG_HEIGHT = 64;
60
61 private static final int DANCE_WIDTH = 100;
62
63 private static final int DANCE_HEIGHT = 80;
64
65 private static final int[] DANCE_STEP = new int[] {
66 12, 28, 8, -6, -20, 12, -10, -6, -10, -20, 8, 8, 12, -8, -4
67 };
68
69 public void init() {
70 _initValues();
71 _buildWordList();
72 _loadResources();
73
74 addKeyListener(this);
75 _newGame();
76 }
77
78 public void paint(Graphics g) {
79 g.setColor(new Color(128, 64, 0));
81 g.fillRect(10, HANG_HEIGHT * 2 + 10, HANG_WIDTH + 3, 3);
82 g.fillRect(HANG_WIDTH / 2 + 10, 10, 3, HANG_HEIGHT * 2);
83 g.fillRect(HANG_WIDTH / 2 + 10, 10, HANG_WIDTH / 2 + HANG_WIDTH / 2, 3);
84 g.fillRect(HANG_WIDTH * 3 / 2 + 9, 10, 3, HANG_HEIGHT / 3 + 1);
85
86 if (_wrongGuess.length() != 0) {
88 g.drawImage(
89 _hangImages[_wrongGuess.length()-1],
90 HANG_WIDTH + 10, HANG_HEIGHT / 3, this);
91
92 g.setColor(Color.RED);
93 g.setFont(_wrongFont);
94 g.drawChars(
95 _wrongGuess.toUpperCase().toCharArray(), 0,
96 _wrongGuess.length(), HANG_WIDTH * 2,
97 _wrongMetrics.getHeight() + 1);
98 }
99
100 g.setColor(Color.BLACK);
102 g.setFont(_rightFont);
103 int width = _rightMetrics.charWidth(' ');
104 char [] wordChars = _getWord().toCharArray();
105 for (int i = 0; i < wordChars.length; i++) {
106 if (wordChars[i] != ' ') {
107 g.drawLine(
108 HANG_WIDTH * 2 + 2 * i * width + 1, HANG_HEIGHT * 2 + 1,
109 HANG_WIDTH * 2 + 2 * (i+1) * width - 1,
110 HANG_HEIGHT * 2 + 1);
111
112 if (_gameOver() || _rightGuess.indexOf(wordChars[i]) != -1) {
113 g.drawChars(
114 _getWord().toUpperCase().toCharArray(), i, 1,
115 HANG_WIDTH * 2 + 2 * i * width + width / 2,
116 HANG_HEIGHT * 2);
117 }
118 }
119 }
120
121 g.clearRect(_danceX, _danceY, DANCE_WIDTH, DANCE_HEIGHT);
123 if (_danceIndex != -1) {
124 _danceX += DANCE_STEP[_danceIndex % DANCE_STEP.length];
125 _danceX = Math.max(_danceX, _danceXLo);
126 _danceX = Math.min(_danceX, _danceXHi);
127
128 g.drawImage(
129 _danceImages[_danceIndex % TOTAL_IMAGES_DANCE],
130 _danceX, _danceY, this);
131 }
132 }
133
134 public void keyPressed(KeyEvent e) { }
135
136 public void keyReleased(KeyEvent e) {
137 char key = e.getKeyChar();
138
139 if (!_gameOver()) {
140 if ((key < 'a' || key > 'z') ||
141 (_rightGuess.indexOf(key) != -1) ||
142 (_wrongGuess.indexOf(key) != -1)) {
143
144 play(getCodeBase(), "audio/ding.au");
145 }
146 else {
147 Character letter = new Character(key);
148 if (_getWord().indexOf(key) != -1) {
149 _rightGuess += letter;
150
151 for (int i = 0; i < _getWord().length(); i++) {
152 if (_getWord().charAt(i) == key) {
153 _guessLength++;
154 }
155 }
156
157 if (_guessLength == _getWord().length()) {
158 play(getCodeBase(), "audio/whoopy.au");
159 _startDance();
160 }
161 else {
162 play(getCodeBase(), "audio/ah.au");
163 }
164 }
165 else {
166 _wrongGuess += letter;
167
168 if (_wrongGuess.length() < TOTAL_IMAGES_HANG) {
169 play(getCodeBase(), "audio/ooh.au");
170 }
171 else {
172 play(getCodeBase(), "audio/scream.au");
173 }
174 }
175 }
176
177 repaint();
178 }
179 else {
180 _stopDance();
181 _newGame();
182 }
183 e.consume();
184 }
185
186 public void keyTyped(KeyEvent e) { }
187
188 private void _initValues() {
189 _tracker = new MediaTracker(this);
190 _danceImages = new Image[TOTAL_IMAGES_DANCE];
191 _hangImages = new Image[TOTAL_IMAGES_HANG];
192 _danceIndex = -1;
193 _danceY = HANG_HEIGHT / 2;
194 _danceX = _danceXLo = HANG_WIDTH * 2;
195 _danceXHi = Math.min(
196 DANCE_WIDTH * 2 + HANG_WIDTH * 2, getWidth() - DANCE_WIDTH);
197 _wordList = new ArrayList();
198 _wrongFont = new Font("MONOSPACED", Font.BOLD, 16);
199 _wrongMetrics = getFontMetrics(_wrongFont);
200 _rightFont = new Font("MONOSPACED", Font.PLAIN, 14);
201 _rightMetrics = getFontMetrics(_rightFont);
202 }
203
204 private void _buildWordList() {
205 String paramWords = getParameter("word_list");
206 if (paramWords != null) {
207 StringTokenizer st = new StringTokenizer(paramWords, ",");
208
209 while (st.hasMoreTokens()) {
210 boolean skip = false;
211
212 String token = st.nextToken().trim();
213 for (int i = 0; i < token.length(); i++) {
214 char c = token.charAt(i);
215 if ((c < 'a' || c > 'z') && c != ' ') {
216 skip = true;
217 break;
218 }
219 }
220
221 if (!skip) {
222 _wordList.add(token);
223 }
224 else {
225 System.err.println("Token '" + token +
226 "' contains invalid characters");
227 }
228 }
229 }
230
231 if (_wordList.isEmpty()) {
233 _wordList.add("liferay");
234 _wordList.add("open source");
235 _wordList.add("enterprise");
236 _wordList.add("for life");
237 }
238 }
239
240 private void _loadResources() {
241 for (int i = 0; i < TOTAL_IMAGES_HANG; i++) {
242 Image img = getImage(
243 getCodeBase(), "images/hanging/h" + (i+1) + ".gif");
244 _tracker.addImage(img, MEDIA_TRACKER_HANG);
245 _hangImages[i] = img;
246 }
247
248 for (int i = 0; i < TOTAL_IMAGES_DANCE; i++) {
249 Image img = getImage(
250 getCodeBase(), "images/dancing/d" + (i+1) + ".gif");
251 _tracker.addImage(img, MEDIA_TRACKER_DANCE);
252 _danceImages[i] = img;
253 }
254
255 _danceMusic = getAudioClip(getCodeBase(), "audio/dance.au");
256 }
257
258 private void _newGame() {
259 try {
260 _tracker.waitForID(MEDIA_TRACKER_HANG);
261 } catch (InterruptedException ex) {
262 }
264 _tracker.checkAll(true);
265
266 _rightGuess = new String();
267 _wrongGuess = new String();
268 _wordIndex = (int) (Math.random() * 100) % _wordList.size();
269
270 _guessLength = 0;
271 String word = _getWord();
272 for (int i = 0; i < word.length(); i++) {
273 if (word.charAt(i) == ' ') {
274 _guessLength++;
275 }
276 }
277
278 repaint();
279 }
280
281 private boolean _gameOver() {
282 return
283 _guessLength == _getWord().length() ||
284 _wrongGuess.length() == TOTAL_IMAGES_HANG;
285 }
286
287 private String _getWord() {
288 return (String) _wordList.get(_wordIndex);
289 }
290
291 private void _startDance() {
292 _danceThread = new DanceThread();
293 _danceThread.start();
294 }
295
296 private void _stopDance() {
297 if (_danceThread != null) {
298 _danceThread.interrupt();
299 _danceThread = null;
300 }
301 }
302
303 private class DanceThread extends Thread {
304 public void run() {
305 _danceX = _danceXLo;
306 _danceX += (int) (Math.random() * 100) % (_danceXHi - _danceXLo);
307 _danceIndex = 0;
308 _danceMusic.loop();
309 try {
310 _tracker.waitForID(MEDIA_TRACKER_DANCE);
311
312 for (;;) {
313 _danceIndex++;
314 repaint();
315 sleep(250);
316 }
317 }
318 catch (InterruptedException ex) {
319 }
321 _danceIndex = -1;
322 _danceMusic.stop();
323 repaint();
324 }
325 }
326
327 private MediaTracker _tracker;
329 private AudioClip _danceMusic;
330 private Image[] _danceImages;
331 private Image[] _hangImages;
332 private Thread _danceThread;
333 private int _danceIndex;
334 private int _danceY;
335 private int _danceX;
336 private int _danceXLo;
337 private int _danceXHi;
338
339 private List _wordList;
341 private int _wordIndex;
342 private String _rightGuess;
343 private String _wrongGuess;
344 private int _guessLength;
345
346 private Font _wrongFont;
348 private FontMetrics _wrongMetrics;
349 private Font _rightFont;
350 private FontMetrics _rightMetrics;
351
352 }