Source code: hangman1/Game.java
1 /* This work is hereby released into the Public Domain.
2 * To view a copy of the public domain dedication, visit
3 * http://creativecommons.org/licenses/publicdomain/
4 * or send a letter to Creative Commons, 559 Nathan Abbott Way,
5 * Stanford, California 94305, USA.
6 */
7 package hangman1;
8
9 /**
10 * Tracks the players progress through the game, including guessed letters and
11 * incorrect guesses remaining.
12 *
13 * @author Howard Lewis Ship
14 */
15 public class Game
16 {
17 private String _targetWord;
18 private int _incorrectGuessesLeft;
19 private char[] _letters;
20 private boolean[] _guessed = new boolean[26];
21 private boolean _win;
22
23 /**
24 * Returns true if the player has guessed all letters in the word.
25 *
26 */
27
28 public boolean isWin()
29 {
30 return _win;
31 }
32
33 /**
34 * Returns an array of letters that have been guessed by the player, with
35 * an underscore for each unguessed position. Once the player loses,
36 * this returns the array of actual letters in the target word.
37 *
38 * <p>
39 * The caller must not modify this array.
40 *
41 */
42
43 public char[] getLetters()
44 {
45 return _letters;
46 }
47
48 /**
49 * Returns the number of incorrect guesses remaining.
50 * An incorrect guess when this is already zero results
51 * in a loss.
52 *
53 */
54
55 public int getIncorrectGuessesLeft()
56 {
57 return _incorrectGuessesLeft;
58 }
59
60 /**
61 * Returns an array of flags indicating which letters have already been guessed.
62 * There are 26 flags, one for each letter, starting with 'A' at index 0, up to 'Z' at
63 * index 25.
64 *
65 * <p>The caller must not modify this array.
66 *
67 */
68
69 public boolean[] getGuessedLetters()
70 {
71 return _guessed;
72 }
73
74 /**
75 * Initializes the Game with a new target word. This resets the
76 * incorrectGuessesLeft count, and initializes the array of
77 * letters and letters guessed.
78 *
79 */
80
81
82 public void start(String word)
83 {
84 _targetWord = word;
85 _incorrectGuessesLeft = 5;
86 _win = false;
87
88 int count = word.length();
89
90 _letters = new char[count];
91
92 for (int i = 0; i < count; i++)
93 _letters[i] = '_';
94
95 for (int i = 0; i < 26; i++)
96 _guessed[i] = false;
97 }
98
99 /**
100 * The player makes a guess. If the letter has already been
101 * guessed, then no change occurs. Otherwise, there's a check
102 * to see if the guess fills in any positions in the target word.
103 * This may result in a win. If the guess doesn't match any
104 * letter of the word, then a failure occurs; when enough
105 * failures occur, the game results in a loss.
106 *
107 * @return true if further guesses are allowed (this guess did
108 * not result in a win or a loss), or false if further guesses
109 * are not allowed (the player guessed the word, or used up
110 * all possible incorrect guesses).
111 *
112 */
113
114 public boolean makeGuess(char letter)
115 {
116 char ch = Character.toLowerCase(letter);
117
118 if (ch < 'a' || ch > 'z')
119 throw new IllegalArgumentException("Must provide an alphabetic character.");
120
121 int index = ch - 'a';
122
123 // If the player (somehow) guesses the same letter more than once, it does not affect
124 // state of the game.
125
126 if (_guessed[index])
127 return true;
128
129 _guessed[index] = true;
130
131 boolean good = false;
132 boolean complete = true;
133
134 for (int i = 0; i < _letters.length; i++)
135 {
136 if (_letters[i] != '_')
137 continue;
138
139 if (_targetWord.charAt(i) == ch)
140 {
141 good = true;
142 _letters[i] = ch;
143 continue;
144 }
145
146 // An empty slot that does not match
147 // the guess, so the word is not
148 // complete.
149
150 complete = false;
151 }
152
153 if (good)
154 {
155 _win = complete;
156
157 return !complete;
158 }
159
160
161 if (_incorrectGuessesLeft == 0)
162 {
163 // Replace the letters array with the solution
164
165 _letters = _targetWord.toCharArray();
166
167 return false;
168 }
169
170 _incorrectGuessesLeft--;
171
172 // Not a good guess, but not a loss yet
173
174 return true;
175 }
176 }