1
+ package ch_20 ;
2
+
3
+ import javafx .application .Application ;
4
+ import javafx .beans .property .SimpleStringProperty ;
5
+ import javafx .beans .property .StringProperty ;
6
+ import javafx .collections .ObservableList ;
7
+ import javafx .scene .Node ;
8
+ import javafx .scene .Scene ;
9
+ import javafx .scene .control .Label ;
10
+ import javafx .scene .input .KeyCode ;
11
+ import javafx .scene .layout .Pane ;
12
+ import javafx .scene .paint .Color ;
13
+ import javafx .scene .shape .Arc ;
14
+ import javafx .scene .shape .Circle ;
15
+ import javafx .scene .shape .Line ;
16
+ import javafx .scene .shape .Shape ;
17
+ import javafx .scene .text .Text ;
18
+ import javafx .scene .text .TextAlignment ;
19
+ import javafx .stage .Stage ;
20
+
21
+ import java .util .*;
22
+
23
+ /**
24
+ * ***20.7 (Game: hangman) Programming Exercise 7.35 presents a console version of the
25
+ * popular hangman game. Write a GUI program that lets a user play the game. The
26
+ * user guesses a word by entering one letter at a time, as shown in Figure 20.18.
27
+ * If the user misses seven times, a hanging man swings. Once a word is finished,
28
+ * the user can press the Enter key to continue to guess another word.
29
+ */
30
+ public class Exercise20_07 extends Application {
31
+ private final static double HEIGHT = 400 ;
32
+ private final static double WIDTH = 400 ;
33
+
34
+ int wrongAnswers = 0 ;
35
+
36
+ Text currentWordPrompt = new Text ("Guess a word: " );
37
+ Text currentWordLbl = new Text ();
38
+ Text missedLetterPrompt = new Text ("Missed letters: " );
39
+ Text missedLettersLbl = new Text ();
40
+ boolean wordComplete ;
41
+
42
+ ObservableList <Node > observableNodes ;
43
+ StringProperty DISPLAY_WORD = new SimpleStringProperty ();
44
+ static String currentWord ;
45
+ StringProperty MISSED_LETTERS = new SimpleStringProperty ();
46
+ static String missedLetters = "" ;
47
+ StringProperty USER_MESSAGE = new SimpleStringProperty ();
48
+
49
+ String [] words = {"abstract" , "assert" , "boolean" ,
50
+ "break" , "byte" , "case" , "catch" , "class" , "const" ,
51
+ "continue" , "default" , "double" , "enum" ,
52
+ "protected" , "public" , "return" , "short" , "static" ,
53
+ "super" , "switch" , "synchronized" , "this" ,
54
+ "throw" , "throws" , "transient" , "void" , "volatile" ,
55
+ "while" };
56
+
57
+ @ Override
58
+ public void start (Stage primaryStage ) {
59
+ Pane pane = new Pane ();
60
+ observableNodes = pane .getChildren ();
61
+ currentWordLbl .textProperty ().bind (DISPLAY_WORD );
62
+ missedLettersLbl .textProperty ().bind (MISSED_LETTERS );
63
+
64
+ Queue <Shape > parts = new LinkedList <>();
65
+ ArrayList <Character > playedLetters = new ArrayList <>();
66
+
67
+ Arc arc = new Arc (WIDTH / 4 , HEIGHT - HEIGHT / 12 , WIDTH / 5 , HEIGHT / 12 , 0 , 180 );
68
+ arc .setFill (Color .TRANSPARENT );
69
+ arc .setStroke (Color .BLACK );
70
+ observableNodes .add (arc );
71
+
72
+ Queue <String > wordsList = new LinkedList <>(Arrays .asList (words ));
73
+ Scene scene = new Scene (pane , WIDTH , HEIGHT );
74
+ Line pole = new Line (arc .getCenterX (), arc .getCenterY () - arc .getRadiusY (), arc .getCenterX (),
75
+ pane .getHeight () / 12 );
76
+ observableNodes .add (pole );
77
+
78
+ Line holder = new Line (pole .getEndX (), pole .getEndY (), pane .getWidth () / 1.7 , pole .getEndY ());
79
+ observableNodes .add (holder );
80
+
81
+ double promptX = arc .getCenterX () + 50 ;
82
+ double promptY = arc .getCenterY () - 55 ;
83
+ currentWordPrompt .setTextAlignment (TextAlignment .RIGHT );
84
+ currentWordPrompt .setX (promptX );
85
+ currentWordPrompt .setY (promptY );
86
+ observableNodes .add (currentWordPrompt );
87
+
88
+ currentWordLbl .setTextAlignment (TextAlignment .RIGHT );
89
+ currentWordLbl .setX (currentWordPrompt .getX () + 100 );
90
+ currentWordLbl .setY (currentWordPrompt .getY ());
91
+ observableNodes .add (currentWordLbl );
92
+
93
+ missedLetterPrompt .setTextAlignment (TextAlignment .RIGHT );
94
+ missedLetterPrompt .setX (promptX );
95
+ missedLetterPrompt .setY (promptY + 20 );
96
+ observableNodes .add (missedLetterPrompt );
97
+
98
+ missedLettersLbl .setTextAlignment (TextAlignment .RIGHT );
99
+ missedLettersLbl .setX (missedLetterPrompt .getX () + 100 );
100
+ missedLettersLbl .setY (missedLetterPrompt .getY ());
101
+ observableNodes .add (missedLettersLbl );
102
+
103
+ Line hang = new Line (holder .getEndX (), holder .getEndY (), holder .getEndX (), pane .getHeight () / 6 );
104
+ parts .add (hang );
105
+
106
+ double radius = WIDTH / 10 ;
107
+ Circle c = new Circle (holder .getEndX (), pane .getHeight () / 6 + radius , radius );
108
+ c .setFill (Color .TRANSPARENT );
109
+ c .setStroke (Color .BLACK );
110
+ parts .add (c );
111
+
112
+ Line leftArm = new Line (pane .getWidth () / 2 , pane .getHeight () / 2 ,
113
+ c .getCenterX () + c .getRadius () * Math .cos (Math .toRadians (220 )),
114
+ c .getCenterY () - c .getRadius () * Math .sin (Math .toRadians (220 )));
115
+ parts .add (leftArm );
116
+
117
+ Line rightArm = new Line (pane .getWidth () / 1.2 , pane .getHeight () / 2 ,
118
+ c .getCenterX () + c .getRadius () * Math .cos (Math .toRadians (315 )),
119
+ c .getCenterY () - c .getRadius () * Math .sin (Math .toRadians (315 )));
120
+ parts .add (rightArm );
121
+
122
+ Line body = new Line (c .getCenterX () + c .getRadius () * Math .cos (Math .toRadians (270 )),
123
+ c .getCenterY () - c .getRadius () * Math .sin (Math .toRadians (270 )),
124
+ c .getCenterX () + c .getRadius () * Math .cos (Math .toRadians (270 )), pane .getHeight () / 1.6 );
125
+ parts .add (body );
126
+
127
+ Line leftLeg = new Line (body .getEndX (), body .getEndY (),
128
+ pane .getWidth () / 2 , pane .getHeight () / 1.3 );
129
+ parts .add (leftLeg );
130
+
131
+ Line rightLeg = new Line (body .getEndX (), body .getEndY (),
132
+ pane .getWidth () / 1.2 , pane .getHeight () / 1.3 );
133
+ parts .add (rightLeg );
134
+
135
+
136
+ scene .setOnKeyPressed (e -> {
137
+ KeyCode keyCode = e .getCode ();
138
+ if (keyCode .isLetterKey ()) {
139
+ String letter = keyCode .getName ();
140
+ System .out .println (letter );
141
+ handleGuess (letter , currentWord , playedLetters , parts , observableNodes );
142
+
143
+ } else if (keyCode == KeyCode .ENTER && wordComplete ) {
144
+ // Next Word
145
+ currentWord = wordsList .poll ();
146
+ wrongAnswers = 0 ;
147
+ missedLetters = "" ;
148
+ playedLetters .clear ();
149
+ MISSED_LETTERS .set (missedLetters );
150
+ DISPLAY_WORD .set (getDisplayWord (currentWord , playedLetters ));
151
+ wordComplete = false ;
152
+
153
+ }
154
+ });
155
+
156
+ primaryStage .setScene (scene );
157
+ primaryStage .setResizable (false );
158
+ primaryStage .setTitle (getClass ().getName ());
159
+ primaryStage .show ();
160
+
161
+ if (wordsList .peek () != null ) {
162
+ currentWord = wordsList .poll ();
163
+ DISPLAY_WORD .set (getDisplayWord (currentWord , playedLetters ));
164
+ }
165
+ }
166
+
167
+ void handleGuess (String letter , String currentWord , ArrayList <Character > playedLetters , Queue <Shape > parts ,
168
+ ObservableList <Node > nodes ) {
169
+ char letterCh = Character .toLowerCase (letter .charAt (0 ));
170
+ if (currentWord .contains (letterCh + "" ) && !wordComplete ) {
171
+ if (!playedLetters .contains (letterCh )) {
172
+ playedLetters .add (letterCh );
173
+ DISPLAY_WORD .set (getDisplayWord (currentWord , playedLetters ));
174
+ if (!DISPLAY_WORD .get ().contains ("*" )) {
175
+ wordComplete = true ;
176
+ MISSED_LETTERS .set ("" );
177
+ }
178
+ }
179
+ } else if (!wordComplete ) {
180
+ wrongAnswers += 1 ;
181
+ if (wrongAnswers == 7 ) {
182
+ observableNodes .clear ();
183
+ observableNodes .add (new Label ("Game Over" ));
184
+ }
185
+ drawHangMan (parts , nodes );
186
+ missedLetters += letter ;
187
+ MISSED_LETTERS .set (missedLetters .toLowerCase ());
188
+
189
+ }
190
+
191
+ }
192
+
193
+ void drawHangMan (Queue <Shape > parts , ObservableList <Node > nodes ) {
194
+ if (parts .peek () != null ) {
195
+ nodes .add (parts .poll ());
196
+ }
197
+ }
198
+
199
+ String getDisplayWord (String word , ArrayList <Character > playedLetters ) {
200
+ StringBuilder result = new StringBuilder ();
201
+ System .out .println (word );
202
+ for (char ch : word .toCharArray ()) {
203
+ if (!playedLetters .contains (ch )) {
204
+ result .append ("*" );
205
+ } else {
206
+ result .append (ch );
207
+ }
208
+ }
209
+ return result .toString ();
210
+ }
211
+ }
0 commit comments