斯坦福CS106A作业4

这次的作业是做小时候经常玩的猜单词游戏。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/*
* File: Hangman.java
* ------------------
* This program will eventually play the Hangman game from
* Assignment #4.
*/

import acm.graphics.*;
import acm.program.*;
import acm.util.*;

import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Hangman extends ConsoleProgram {

/***********************************************************
* CONSTANTS *
***********************************************************/

/* The number of guesses in one game of Hangman */
private static final int N_GUESSES = 7;
/* The width and the height to make the karel image */
private static final int KAREL_SIZE = 150;
/* The y-location to display karel */
private static final int KAREL_Y = 230;
/* The width and the height to make the parachute image */
private static final int PARACHUTE_WIDTH = 300;
private static final int PARACHUTE_HEIGHT = 130;
/* The y-location to display the parachute */
private static final int PARACHUTE_Y = 50;
/* The y-location to display the partially guessed string */
private static final int PARTIALLY_GUESSED_Y = 430;
/* The y-location to display the incorrectly guessed letters */
private static final int INCORRECT_GUESSES_Y = 460;
/* The fonts of both labels */
private static final String PARTIALLY_GUESSED_FONT = "Courier-36";
private static final String INCORRECT_GUESSES_FONT = "Courier-26";

/***********************************************************
* Instance Variables *
***********************************************************/

/* An object that can produce pseudo random numbers */
private RandomGenerator rg = new RandomGenerator();

private GCanvas canvas = new GCanvas();
private GLine line1;
private GLine line2;
private GLine line3;
private GLabel label1;
private GLabel label2;


/***********************************************************
* Methods *
***********************************************************/

public void init() {
add(canvas);
}

public void run() {
// shall we?
//初始化
drawBackground();
addKAREL(karel);
parachute();
addline();

BufferedReader rd=openFileReader();
ArrayList<String> list=read(rd);
String word = newgetRandomWord(list);
//String word = getRandomWord();
//String word = "AMBASSADOR";
game(word);
}

//增加图形
private void drawBackground() {
GImage bg=new GImage("background.jpg");
bg.setSize(canvas.getWidth(), canvas.getHeight());
canvas.add(bg);
}

private void addKAREL(GImage a) {
//GImage karel=new GImage("karel.png");
a.setSize(KAREL_SIZE,KAREL_SIZE);
double x=(canvas.getWidth()-a.getWidth())/2;
canvas.add(a,x,KAREL_Y);
}

private void parachute() {
//GImage parachute=new GImage("parachute.png");
parachute.setSize(PARACHUTE_WIDTH,PARACHUTE_HEIGHT);
double x=(canvas.getWidth()-parachute.getWidth())/2;
canvas.add(parachute,x,PARACHUTE_Y);
}

private void addline() {
double x1=canvas.getWidth()/2;
double sep=50;
double y=PARACHUTE_Y+parachute.getHeight();
line1=new GLine(x1,KAREL_Y,x1,y);
line2=new GLine(x1,KAREL_Y,x1-sep,y);
line3=new GLine(x1,KAREL_Y,x1+sep,y);
canvas.add(line1);
canvas.add(line2);
canvas.add(line3);
}

private void showword(String word1,String word2,double y1,double y2) {
//canvas.remove(label1);
label1=new GLabel(word1);
label2=new GLabel(word2);
double x1=(canvas.getWidth()-label1.getWidth())/2;
double x2=(canvas.getWidth()-label2.getWidth())/2;
canvas.add(label1,x1,y1);
canvas.add(label2,x2,y2);
}


//游戏的方法
private void game(String word) {
int n = word.length();
boolean flag = false;
//记录错误次数
int count = 0;
//记录正确猜出的个数
int j = 0;
//记录结果
String ans = "";
for (int i=0;i<n;i++) {
ans+="_";
}
//记录已经猜过的字母,防止重复
String haveguess="";

//在图形界面画图
showword(show(ans),show(haveguess),PARTIALLY_GUESSED_Y,INCORRECT_GUESSES_Y);

println("Welcome to Hangman");

while(count<N_GUESSES && j<n) {
//记录展示的结果
String show = show(ans);
println("Your word now looks like this:"+show);
println("You have "+(N_GUESSES-count)+" guesses left.");
String temp = readLine("Your guess: ");

//先判断是否是字符和字母
char s = temp.charAt(0);
while(temp.length()!=1 || !Character.isLetter(s)||
haveguess.indexOf(Character.toUpperCase(s))!=-1) {
if(temp.length()!=1|| !Character.isLetter(s)) {
temp = readLine("This is not a single letter,please guesses again: ");
s = temp.charAt(0);
}else {
temp = readLine("You have guessed letter,please guesses again: ");
s = temp.charAt(0);
}
}

//转换为小写
s = Character.toUpperCase(s);
String tempword = word.toUpperCase();

int index = tempword.indexOf(s);
//更新已经猜过的字母,注意大小写都要
haveguess+=s;

if(index==-1) {
println("There are no "+s+"' in the word.");
count++;
}else {
println("That guess is correct.");
//要考虑这个字母多次出现的情形
String tempans="";
for(int i =0;i<word.length();i++) {
if(tempword.charAt(i)!=s) {
if (ans.charAt(i)=='_') {
tempans+="_";
}else {
tempans+=ans.charAt(i);
}
}else {
tempans+=word.charAt(i);
//猜对的个数增加
j++;
}
}
ans=tempans;
}

//更新展示的结果
canvas.remove(label1);
canvas.remove(label2);
showword(show(ans),show(haveguess),PARTIALLY_GUESSED_Y,INCORRECT_GUESSES_Y);
}

if(j<n) {
println("You're completely hung.");
canvas.remove(line1);
canvas.remove(line2);
canvas.remove(line3);
canvas.remove(karel);
addKAREL(karel1);
}else {
println("You win.");
}
println("The word was:"+word);
}

//将数据读取到ArrayList
private ArrayList<String> read(BufferedReader rd){
ArrayList<String> list=new ArrayList<String>();
try {
while(true) {
String line=rd.readLine();
if(line==null) {
break;
}
list.add(line);
}
}catch(IOException ex) {
println("Can't open that file.");
}
return list;
}

//读数据
private BufferedReader openFileReader() {
BufferedReader rd = null;
while (rd == null) {
try {
String name = "HangmanLexicon.txt";
rd = new BufferedReader(new FileReader(name));
} catch (IOException ex) {
println("Can't open that file.");
}
}
return rd;
}


/**
* Method: Get Random Word
* -------------------------
* This method returns a word to use in the hangman game. It randomly
* selects from among 10 choices.
*/
private String getRandomWord() {
int index = rg.nextInt(10);
if(index == 0) return "BUOY";
if(index == 1) return "COMPUTER";
if(index == 2) return "CONNOISSEUR";
if(index == 3) return "DEHYDRATE";
if(index == 4) return "FUZZY";
if(index == 5) return "HUBBUB";
if(index == 6) return "KEYHOLE";
if(index == 7) return "QUAGMIRE";
if(index == 8) return "SLITHER";
if(index == 9) return "ZIRCON";
throw new ErrorException("getWord: Illegal index");
}

private String newgetRandomWord(ArrayList list) {
int index = rg.nextInt(list.size());
return (String) (list.get(index));
}

private String show(String s) {
String result="";
for(int i=0;i<s.length();i++) {
result+=s.charAt(i)+" ";
}
return result;
}

private static final GImage parachute=new GImage("parachute.png");
private static final GImage karel=new GImage("karel.png");
private static final GImage karel1=new GImage("karelFlipped.png");
}