femis_hangman 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -0
- data/Gemfile +1 -0
- data/README.md +36 -6
- data/bin/hangman +7 -0
- data/bin/resume +13 -0
- data/dictionary.txt +41211 -0
- data/femis_hangman.gemspec +4 -4
- data/lib/femis_hangman/game.rb +122 -0
- data/lib/femis_hangman/message.rb +114 -0
- data/lib/femis_hangman/router.rb +153 -0
- data/lib/femis_hangman/version.rb +1 -1
- data/lib/femis_hangman/word.rb +27 -0
- data/lib/femis_hangman.rb +6 -5
- data/saved_games.yaml +26 -0
- metadata +23 -7
- data/bin/console +0 -14
data/femis_hangman.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Femi Senjobi"]
|
10
10
|
spec.email = ["femi.senjobi@andela.com"]
|
11
11
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
12
|
+
spec.summary = "It is a do or die affiar. Get the words right or you'll be hanged"
|
13
|
+
spec.description = "This gem is an implementation of the hangman.rb game.\nAttempt to guess the missing letters correctly.\nYou have a limited number of tries.\nIf you use up all your chances without getting the word correctly,\nyou will be hanged."
|
14
14
|
spec.homepage = "https://github.com/andela-fsenjobi/femis_hangman"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -23,8 +23,8 @@ Gem::Specification.new do |spec|
|
|
23
23
|
end
|
24
24
|
|
25
25
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
-
spec.bindir = "
|
27
|
-
spec.executables = spec.files.grep(%r{^
|
26
|
+
spec.bindir = "bin"
|
27
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
30
|
spec.add_development_dependency "bundler", "~> 1.11"
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module FemisHangman
|
2
|
+
class Game
|
3
|
+
include(Message)
|
4
|
+
attr_accessor :turns, :history, :word, :feedback, :status
|
5
|
+
|
6
|
+
def initialize(difficulty, feedback)
|
7
|
+
word = Word.new
|
8
|
+
@word = word.generate(difficulty)
|
9
|
+
@history = []
|
10
|
+
@turns = 7 + difficulty
|
11
|
+
@feedback = feedback
|
12
|
+
@status = 'play'
|
13
|
+
end
|
14
|
+
|
15
|
+
def control(input)
|
16
|
+
if input.size > 1
|
17
|
+
commands(input)
|
18
|
+
elsif input.size == 1
|
19
|
+
play(input)
|
20
|
+
else
|
21
|
+
invalid_prompt
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def commands(input)
|
26
|
+
case input
|
27
|
+
when ':h', 'history' then print_text("You have used: #{game_history}")
|
28
|
+
when ':q', 'quit' then quit_game
|
29
|
+
else invalid_prompt
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def play(input)
|
34
|
+
include_letter(input, @history)
|
35
|
+
@turns -= 1 unless @word.include?(input)
|
36
|
+
check_game
|
37
|
+
end
|
38
|
+
|
39
|
+
def include_letter(letter, history)
|
40
|
+
if history.include?(letter)
|
41
|
+
duplicate_prompt(letter)
|
42
|
+
false
|
43
|
+
else
|
44
|
+
history << letter
|
45
|
+
@history = history
|
46
|
+
end
|
47
|
+
@history
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_game
|
51
|
+
if won? then game_won
|
52
|
+
elsif lost? then game_lost
|
53
|
+
else
|
54
|
+
turns_prompt(@turns)
|
55
|
+
puts show_word
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def show_word
|
60
|
+
word = @word.split('')
|
61
|
+
output = ''
|
62
|
+
word.each do |letter|
|
63
|
+
if @history.include?(letter)
|
64
|
+
output << "#{letter} "
|
65
|
+
else
|
66
|
+
output << '_ '
|
67
|
+
end
|
68
|
+
end
|
69
|
+
output
|
70
|
+
end
|
71
|
+
|
72
|
+
def won?
|
73
|
+
word = @word.split('')
|
74
|
+
length = 0
|
75
|
+
word.each {|val| length += 1 if @history.include?(val)}
|
76
|
+
if length == word.size
|
77
|
+
true
|
78
|
+
else
|
79
|
+
false
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def lost?
|
84
|
+
@turns == 0
|
85
|
+
end
|
86
|
+
|
87
|
+
def game_won
|
88
|
+
if @feedback == 2
|
89
|
+
won_gui(@word)
|
90
|
+
else
|
91
|
+
won_prompt(@word)
|
92
|
+
end
|
93
|
+
replay_prompt
|
94
|
+
@status = 'restart'
|
95
|
+
end
|
96
|
+
|
97
|
+
def game_lost
|
98
|
+
if @feedback == 2
|
99
|
+
lost_gui(@word)
|
100
|
+
else
|
101
|
+
lost_prompt(@word)
|
102
|
+
end
|
103
|
+
replay_prompt
|
104
|
+
@status = 'restart'
|
105
|
+
end
|
106
|
+
|
107
|
+
def game_history
|
108
|
+
output = ''
|
109
|
+
if @history.empty?
|
110
|
+
''
|
111
|
+
else
|
112
|
+
@history.each {|letter| output << "#{letter} "}
|
113
|
+
end
|
114
|
+
output
|
115
|
+
end
|
116
|
+
|
117
|
+
def quit_game
|
118
|
+
@status = 'quit'
|
119
|
+
save_prompt
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Message
|
2
|
+
def welcome_prompt
|
3
|
+
puts 'Welcome to Hangman. Guess right or get hanged!'
|
4
|
+
end
|
5
|
+
|
6
|
+
def size_prompt(size)
|
7
|
+
puts "Your word is a #{size} letter word"
|
8
|
+
end
|
9
|
+
|
10
|
+
def load_prompt
|
11
|
+
puts "Choose the game you want to resume.rb from the list below\nPress the respective number"
|
12
|
+
end
|
13
|
+
|
14
|
+
def begin_prompt
|
15
|
+
puts "Let the games begin\n\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
def instructions_prompt
|
19
|
+
puts "########################################################\n\nThis gem is an implementation of the hangman.rb game.\nAttempt to guess the missing letters correctly.\nYou have a limited number of tries.\nIf you use up all your chances without getting\nthe word correctly, you will be hanged.\n\n"
|
20
|
+
puts "To play a new game: Press 'p' or 'play'"
|
21
|
+
puts "To load a saved game: Press 'l' or 'load'"
|
22
|
+
puts "To show insructions: Press 'i' or 'instructions'"
|
23
|
+
puts "To quit Hangman: Press 'q' or 'quit'"
|
24
|
+
puts "\n########################################################"
|
25
|
+
end
|
26
|
+
|
27
|
+
def save_prompt
|
28
|
+
puts "Press 's' or 'save' to save before quiting\nPress 'q' to quit anyway"
|
29
|
+
end
|
30
|
+
|
31
|
+
def lost_prompt(word)
|
32
|
+
puts "You are dead!\nThe word is #{word}"
|
33
|
+
puts "Press any key to continue or 'q' to quit"
|
34
|
+
end
|
35
|
+
|
36
|
+
def won_prompt(word)
|
37
|
+
puts "You win!\nThe word is #{word}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def lost_gui(word)
|
41
|
+
puts <<-DEAD
|
42
|
+
-+----------+-
|
43
|
+
| |
|
44
|
+
| o
|
45
|
+
| /|\\
|
46
|
+
| / \\
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
You are dead!
|
51
|
+
################
|
52
|
+
The word is #{word}
|
53
|
+
################
|
54
|
+
DEAD
|
55
|
+
end
|
56
|
+
|
57
|
+
def won_gui(word)
|
58
|
+
puts <<-DEAD
|
59
|
+
-+----------+-
|
60
|
+
| |
|
61
|
+
|
|
62
|
+
|
|
63
|
+
| o/
|
64
|
+
| /|
|
65
|
+
| \\/ \\
|
66
|
+
| /
|
67
|
+
You are free to go
|
68
|
+
################
|
69
|
+
The word is #{word}
|
70
|
+
################
|
71
|
+
DEAD
|
72
|
+
end
|
73
|
+
|
74
|
+
def level_prompt
|
75
|
+
puts "Choose your difficulty level\n\n1: Beginner\n2: Intermediate\n3: Advanced"
|
76
|
+
end
|
77
|
+
|
78
|
+
def feedback_prompt
|
79
|
+
puts "Choose your feedback type\n\n1: Boring\n2: Funny"
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def replay_prompt
|
84
|
+
puts "Press 'r' or 'restart' to play again\nPress 'q' to quit"
|
85
|
+
end
|
86
|
+
|
87
|
+
def invalid_prompt
|
88
|
+
puts 'Invalid entry!'
|
89
|
+
end
|
90
|
+
|
91
|
+
def empty_prompt
|
92
|
+
puts "You haven't used any letters yet."
|
93
|
+
end
|
94
|
+
|
95
|
+
def duplicate_prompt(letter)
|
96
|
+
puts "You have used the letter #{letter} already"
|
97
|
+
end
|
98
|
+
|
99
|
+
def turns_prompt(turns)
|
100
|
+
puts "You have #{turns} turns left"
|
101
|
+
end
|
102
|
+
|
103
|
+
def print_text(text)
|
104
|
+
puts "#{text}"
|
105
|
+
end
|
106
|
+
|
107
|
+
def thanks_prompt
|
108
|
+
puts 'Thank you for playing!'
|
109
|
+
end
|
110
|
+
|
111
|
+
def game_instruction_prompt
|
112
|
+
puts "Press ':h' or 'history' to view the letters you have used\nPress ':q' or 'quit' to quit (you can save before quiting)"
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module FemisHangman
|
2
|
+
class Router
|
3
|
+
include(Message)
|
4
|
+
attr_accessor :status, :difficulty, :feedback, :game
|
5
|
+
def initialize
|
6
|
+
@status = 'begin'
|
7
|
+
end
|
8
|
+
|
9
|
+
def process(input)
|
10
|
+
if @status == 'begin' then welcome(input)
|
11
|
+
elsif @status == 'feedback' then choose_feedback(input)
|
12
|
+
elsif @status == 'start' then begin_game(input)
|
13
|
+
elsif @status == 'play' then play_game(input)
|
14
|
+
elsif @status == 'finish' then finish_game(input)
|
15
|
+
elsif @status == 'save' then save_game
|
16
|
+
elsif @status == 'load' then load_game(input)
|
17
|
+
elsif @status == 'quit' || 'end' then quit_game
|
18
|
+
else
|
19
|
+
welcome(input)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def welcome(input)
|
24
|
+
case input
|
25
|
+
when 'p', 'play' then start_game
|
26
|
+
when 'q', 'quit' then quit_game
|
27
|
+
when 'l', 'load' then show_saved_games
|
28
|
+
when 'i', 'instructions' then instructions_prompt
|
29
|
+
else invalid_prompt
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def choose_feedback(input)
|
34
|
+
@feedback = input.to_i
|
35
|
+
if @feedback < 1 || @feedback > 2
|
36
|
+
feedback_prompt
|
37
|
+
return
|
38
|
+
end
|
39
|
+
level_prompt
|
40
|
+
@status = 'start'
|
41
|
+
end
|
42
|
+
|
43
|
+
def begin_game(input)
|
44
|
+
@difficulty = input.to_i
|
45
|
+
if @difficulty < 1 || @difficulty > 3
|
46
|
+
invalid_prompt
|
47
|
+
return
|
48
|
+
end
|
49
|
+
@status = 'play'
|
50
|
+
create_game
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_game
|
54
|
+
begin_prompt
|
55
|
+
@game = Game.new(@difficulty, @feedback)
|
56
|
+
size_prompt(@game.word.size)
|
57
|
+
turns_prompt(@game.turns)
|
58
|
+
game_instruction_prompt
|
59
|
+
print_text(@game.show_word)
|
60
|
+
end
|
61
|
+
|
62
|
+
def play_game(input)
|
63
|
+
if @game.status == 'restart'
|
64
|
+
if input == 'r' || input == 'restart'
|
65
|
+
level_prompt
|
66
|
+
@status = 'start'
|
67
|
+
elsif input == 'q' || input == 'quit'
|
68
|
+
quit_game
|
69
|
+
else invalid_prompt
|
70
|
+
end
|
71
|
+
elsif @game.status == 'quit'
|
72
|
+
if input == 's' || 'save' then save_game
|
73
|
+
elsif input == 'q' || 'quit' then quit_game
|
74
|
+
else
|
75
|
+
invalid_prompt
|
76
|
+
end
|
77
|
+
else @game.control(input)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def start_game
|
82
|
+
@status = 'feedback'
|
83
|
+
welcome_prompt
|
84
|
+
feedback_prompt
|
85
|
+
end
|
86
|
+
|
87
|
+
def finish_game(input)
|
88
|
+
if input == 'r' || 'restart'
|
89
|
+
@status = 'start'
|
90
|
+
begin_game(input)
|
91
|
+
elsif input == 'q' || 'quit'
|
92
|
+
save_prompt
|
93
|
+
@status = 'save'
|
94
|
+
else
|
95
|
+
invalid_prompt
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def save_game
|
100
|
+
File.open('./saved_games.yaml', 'a'){|f| f.write(YAML.dump(@game))}
|
101
|
+
thanks_prompt
|
102
|
+
@status = 'end'
|
103
|
+
end
|
104
|
+
|
105
|
+
def show_saved_games
|
106
|
+
@status = 'load'
|
107
|
+
load_prompt
|
108
|
+
i = 0
|
109
|
+
YAML.load_stream(File.open('./saved_games.yaml', 'r')).each do |game|
|
110
|
+
print "#{i += 1}: "
|
111
|
+
word = game.word.split('')
|
112
|
+
history = game.history
|
113
|
+
word.each do |letter|
|
114
|
+
if history.include?(letter)
|
115
|
+
print "#{letter} "
|
116
|
+
else
|
117
|
+
print '_ '
|
118
|
+
end
|
119
|
+
end
|
120
|
+
print "(#{game.turns} turns left)"
|
121
|
+
print "\n"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def load_game(input)
|
126
|
+
game_id = input.to_i
|
127
|
+
i = 0
|
128
|
+
YAML.load_stream(File.open('./saved_games.yaml', 'r')).each do |game|
|
129
|
+
i += 1
|
130
|
+
if i == game_id
|
131
|
+
@status = 'play'
|
132
|
+
@game = game
|
133
|
+
@game.status = 'play'
|
134
|
+
@game.check_game
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def quit_game
|
140
|
+
@status = 'end'
|
141
|
+
thanks_prompt
|
142
|
+
end
|
143
|
+
|
144
|
+
def loop
|
145
|
+
repl = lambda do |prompt|
|
146
|
+
print prompt
|
147
|
+
process(gets.chomp!)
|
148
|
+
end
|
149
|
+
|
150
|
+
repl["% Hangman-#{FemisHangman::VERSION}: "] while @status != 'end'
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module FemisHangman
|
2
|
+
class Word
|
3
|
+
def generate(difficulty)
|
4
|
+
file = File.open('./dictionary.txt', 'r')
|
5
|
+
rand(41211).times { file.gets }
|
6
|
+
word = clean_word($_)
|
7
|
+
file.close
|
8
|
+
if confirm(difficulty, word)
|
9
|
+
word
|
10
|
+
else
|
11
|
+
generate(difficulty)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def confirm(difficulty, word)
|
16
|
+
if word.length > 4 * difficulty && word.length <= 4 * (difficulty + 1)
|
17
|
+
true
|
18
|
+
else
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def clean_word(word)
|
24
|
+
cleaned_word = word.gsub("\n", '')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|