File Coverage

blib/lib/Games/GuessWord.pm
Criterion Covered Total %
statement 64 64 100.0
branch 8 10 80.0
condition 4 5 80.0
subroutine 14 14 100.0
pod 11 11 100.0
total 101 104 97.1


line stmt bran cond sub pod time code
1             package Games::GuessWord;
2 3     3   61885 use vars qw($VERSION);
  3         7  
  3         174  
3 3     3   20 use strict;
  3         5  
  3         100  
4 3     3   15 use warnings;
  3         10  
  3         8231  
5             $VERSION = '0.16';
6              
7             =head1 NAME
8              
9             Games::GuessWord - Guess the letters in a word (ie Hangman)
10              
11             =head1 SYNOPSIS
12              
13             use Games::GuessWord;
14              
15             my $g = Games::GuessWord->new(file => "/path/to/wordlist");
16             print "Score: " . $g->score . "\n";
17             print "Chances: " . $g->chances . "\n";
18             print "Answer: " . $g->answer . "\n";
19             my @guesses = $g->guesses;
20             $g->guess("t");
21             # ...
22             if ($g->won) {
23             print "You won!\n";
24             $g->new_word;
25             }
26              
27             =head1 DESCRIPTION
28              
29             This module is a simple wrapper around a word guessing game. You have
30             to guess the word by guessing letters in the word, and is otherwise
31             known as Hangman.
32              
33             =head1 METHODS
34              
35             =head2 new
36              
37             This is the constructor. You can either pass in a list of words or a
38             wordlist. A random word is picked:
39              
40             my $g = Games::GuessWord->new(words => ["sleepy", "grumpy"]);
41             # or...
42             my $g = Games::GuessWord->new(file => "t/words");
43              
44             You can also set the number of chances each game has with the chances
45             parameter
46              
47             my $g = Games::GuessWord->new(file => "t/words",
48             chances => 5);
49              
50             =cut
51              
52             sub new {
53 4     4 1 61 my $class = shift;
54 4         28 my %conf = @_;
55              
56 4         9 my $self = {};
57 4         17 $self->{score} = 0;
58 4         11 $self->{words} = $conf{words};
59 4         12 $self->{file} = $conf{file};
60 4   100     30 $self->{starting_chances} = $conf{chances} || 6;
61              
62 4         11 bless $self, $class;
63 4         23 $self->new_word;
64              
65 4         12 return $self;
66             }
67              
68              
69             =head2 answer
70              
71             This method returns the current word being guessed, with asterisks (*)
72             replacing letters that have not been guessed yet. For example, if
73             trying to guess "buffy" and the letters "b" and "f" have been
74             correctly guessed, this will return "b*ff*".
75              
76             print "Answer: " . $g->answer . "\n";
77              
78             =cut
79              
80             sub answer {
81 24     24 1 37 my $self = shift;
82 24         45 my $secret = $self->{secret};
83 24         50 my $guesses = join('', ($self->guesses));
84 24         522 $secret =~ s/[^1$guesses]/*/g;
85 24         119 return $secret;
86             }
87              
88              
89             =head2 chances
90              
91             This method returns the number of chances left. You start off with six
92             chances by default and lose a chance everytime you get a guess wrong.
93              
94             print "Chances: " . $g->chances . "\n";
95              
96             =cut
97              
98             sub chances {
99 98     98 1 128 my $self = shift;
100 98         1116 return $self->{chances};
101             }
102              
103              
104             =head2 guess
105              
106             This methods guesses a letter in the word:
107              
108             $g->guess("t");
109              
110             =cut
111              
112             sub guess {
113 30     30 1 1747 my $self = shift;
114 30         52 my $letter = shift;
115              
116 30 100       74 if ($self->chances == 0) {
117 1         5 return undef;
118             }
119              
120 29         40 push @{$self->{guesses}}, $letter;
  29         64  
121              
122 29 100       95 if ($self->secret =~ /$letter/) {
123 9         26 $self->{score} += $self->chances + 1;
124             } else {
125 20         73 $self->{chances}--;
126             }
127             }
128              
129              
130             =head2 guesses
131              
132             This method returns the guesses taken so far this turn:
133              
134             my @guesses = $g->guesses;
135              
136             =cut
137              
138             sub guesses {
139 39     39 1 72 my $self = shift;
140 39         38 return @{$self->{guesses}};
  39         180  
141             }
142              
143              
144             =head2 new_word
145              
146             This method throws the current turn away and picks a new word:
147              
148             $g->new_word;
149              
150             =cut
151              
152             sub new_word {
153 28     28 1 9520 my $self = shift;
154 28         35 my $secret;
155 28 100       82 if ($self->{words}) {
156 6         17 $secret = $self->{words}->[int rand(@{$self->{words}})];
  6         161  
157             } else {
158 22 50       805 open(IN, $self->{file}) or die "Error reading file $self->{file}: $@";
159 22   66     558 rand($.) < 1 && ($secret = $_) while ;
160 22         254 close IN;
161 22         39 chomp $secret;
162             }
163 28         56 $secret = lc $secret;
164 28         85 $self->{secret} = $secret;
165 28         63 $self->{chances} = $self->{starting_chances};
166 28         57 $self->{guesses} = [];
167              
168 28 50       77 $self->{score} = 0 if $self->lost;
169 28         63 1;
170             }
171              
172              
173             =head2 secret
174              
175             This method returns the secret word that the user is trying to guess:
176              
177             my $secret = $g->secret;
178              
179             =cut
180              
181             sub secret {
182 61     61 1 178 my $self = shift;
183 61         707 return $self->{secret};
184             }
185              
186              
187             =head2 score
188              
189             This method returns the current score. You get a higher score if you
190             guess the word earlier on. The score persists over turns if you win:
191              
192             print "Score: " . $g->score . "\n";
193              
194             =cut
195              
196             sub score {
197 15     15 1 878 my $self = shift;
198 15         73 return $self->{score};
199             }
200              
201              
202             =head2 won
203              
204             Returns true if and only if they have won the game, i.e. if the
205             answer equals the secret word.
206              
207             =cut
208              
209             sub won {
210 9     9 1 14 my $self = shift;
211 9         22 return $self->answer eq $self->secret
212             }
213              
214              
215             =head2 lost
216              
217             Returns true if and only if they have lost the game, i.e. if they
218             have no more chances left
219              
220             =cut
221              
222             sub lost {
223 44     44 1 63 my $self = shift;
224 44         88 return $self->chances == 0;
225             }
226              
227             =head2 starting_chances
228              
229             Sets the number of starting chances, i.e. the number of chances
230             the player gets for each game. By default this is six.
231              
232             =cut
233              
234             sub starting_chances {
235 1     1 1 2 my $self = shift;
236 1         3 my $starting_chances = shift;
237              
238 1         4 $self->{starting_chances} = $starting_chances;
239             }
240              
241              
242              
243             =head1 SHOWING YOUR APPRECIATION
244              
245             There was a thread on london.pm mailing list about working in a vacumn
246             - that it was a bit depressing to keep writing modules but never get
247             any feedback. So, if you use and like this module then please send me
248             an email and make my day.
249              
250             All it takes is a few little bytes.
251              
252             =head1 AUTHOR
253              
254             Leon Brocard EFE
255              
256             =head1 COPYRIGHT
257              
258             Copyright (C) 2001-8, Leon Brocard
259              
260             =head1 LICENSE
261              
262             This module is free software; you can redistribute it or modify it
263             under the same terms as Perl itself.
264              
265             =cut
266              
267             1;