tobi-mastermind 1.0
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 +7 -0
- data/bin/console +14 -0
- data/bin/mastermind +5 -0
- data/bin/setup +7 -0
- data/lib/mastermind/tobi/gamehelper.rb +106 -0
- data/lib/mastermind/tobi/gamemethods.rb +91 -0
- data/lib/mastermind/tobi/gameplay.rb +15 -0
- data/lib/mastermind/tobi/logic.rb +38 -0
- data/lib/mastermind/tobi/multi_game.rb +97 -0
- data/lib/mastermind/tobi/player.rb +21 -0
- data/lib/mastermind/tobi/single_game.rb +117 -0
- data/lib/mastermind/tobi/store.yaml +137 -0
- data/lib/mastermind/tobi/timehelper.rb +31 -0
- data/lib/mastermind/tobi/ui.rb +71 -0
- data/lib/mastermind_start.rb +17 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 90c82361b37324c107990abb8336d085795b1dfd
|
4
|
+
data.tar.gz: 38cc4b58d57efcc9066588c0ee0e00e19aa27e36
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bab88ba83c5ca30683d603a55b468b35d7587c4ab228287dbe05d92ec0b2d0064e26582d02add45693b1f826580f9c463e98b317061119ea6b00bf0325f22c3b
|
7
|
+
data.tar.gz: f5f456ec4734be6503cc6441e64ef488b7cd1941588aa03dcfb3aff1fec1c85df3b247c531081033d2f3012a9ff44a089dadb955e571652e8e8f08856638a2b1
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "tobi/mastermind"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/mastermind
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'ui'
|
2
|
+
require 'logic'
|
3
|
+
require 'single_game'
|
4
|
+
require 'multi_game'
|
5
|
+
|
6
|
+
module MasterMind
|
7
|
+
module Tobi
|
8
|
+
module GameHelper
|
9
|
+
def user_choice
|
10
|
+
option_chosen = false
|
11
|
+
|
12
|
+
while !option_chosen
|
13
|
+
option_chosen = true # assume user selects valid option so as to quit loop
|
14
|
+
|
15
|
+
input = gets.chomp.downcase
|
16
|
+
option_chosen = validate_input?(input)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_input?(input)
|
21
|
+
case input
|
22
|
+
when "p", "play" then play_game
|
23
|
+
when "r", "read"
|
24
|
+
print_help
|
25
|
+
return false # continue loop after displaying help message
|
26
|
+
when "q", "quit" then exit
|
27
|
+
else # user selects an invalid option
|
28
|
+
print UI::INVALID_MESSAGE
|
29
|
+
return false
|
30
|
+
end
|
31
|
+
return true
|
32
|
+
end
|
33
|
+
|
34
|
+
def play_game
|
35
|
+
game_logic = GameLogic.new(ask_level); sequence = game_logic.generate_sequence
|
36
|
+
ask_mode(sequence, game_logic)
|
37
|
+
puts ""
|
38
|
+
print UI::OPTIONS_MESSAGE + UI::INPUT_PROMPT
|
39
|
+
user_choice
|
40
|
+
end
|
41
|
+
|
42
|
+
def ask_mode(sequence, game_logic)
|
43
|
+
print UI::MODE_SELECT
|
44
|
+
option_chosen = false
|
45
|
+
|
46
|
+
while !option_chosen
|
47
|
+
option_chosen = true # assume user selects valid option so as to quit loop
|
48
|
+
|
49
|
+
input = gets.chomp.downcase
|
50
|
+
case input
|
51
|
+
when "s", "single" then SinglePlayer.new(sequence, game_logic).start_game
|
52
|
+
when "m", "multi"
|
53
|
+
print UI::PASSWORD_MESSAGE
|
54
|
+
hide_guess = MasterMind::Tobi::GameHelper.yes_or_no?
|
55
|
+
MultiPlayer.new(sequence, game_logic, hide_guess).start_game
|
56
|
+
else
|
57
|
+
print UI::INVALID_MESSAGE
|
58
|
+
option_chosen = false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.yes_or_no?
|
65
|
+
option_chosen = false
|
66
|
+
|
67
|
+
while !option_chosen
|
68
|
+
option_chosen = true # assume user selects valid option so as to quit loop
|
69
|
+
|
70
|
+
input = gets.chomp.downcase
|
71
|
+
case input
|
72
|
+
when "y", "yes" then return true
|
73
|
+
when "n", "no" then return false
|
74
|
+
else # user selects an invalid option
|
75
|
+
print UI::INVALID_MESSAGE
|
76
|
+
option_chosen = false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def print_help
|
82
|
+
puts UI::HELP_MESSAGE
|
83
|
+
print UI::OPTIONS_MESSAGE + UI::INPUT_PROMPT
|
84
|
+
end
|
85
|
+
|
86
|
+
def ask_level
|
87
|
+
print UI::LEVEL_MESSAGE
|
88
|
+
option_chosen = false
|
89
|
+
|
90
|
+
while !option_chosen
|
91
|
+
option_chosen = true # assume user selects valid level so as to quit loop
|
92
|
+
|
93
|
+
input = gets.chomp.downcase
|
94
|
+
case input
|
95
|
+
when "b", "beginner" then return GameLogic::BEGINNER
|
96
|
+
when "i", "intermediate" then return GameLogic::INTERMEDIATE
|
97
|
+
when "a", "advanced" then return GameLogic::ADVANCED
|
98
|
+
else # user selects an invalid level
|
99
|
+
print UI::INVALID_MESSAGE
|
100
|
+
option_chosen = false
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'ui'
|
2
|
+
require 'gamehelper'
|
3
|
+
module MasterMind
|
4
|
+
module Tobi
|
5
|
+
module GameMethods
|
6
|
+
|
7
|
+
def average_string(top_ten_list, current_player) # generates user's performance compared to average
|
8
|
+
time_diff, guess_diff = difference(top_ten_list, current_player)
|
9
|
+
|
10
|
+
"That's %s %s and %s %s %s the average\n" % [time_convert(time_diff.abs), time_diff < 0 ? "slower" : "faster",
|
11
|
+
guess_diff.abs, guess_diff.abs == 1 ? "guess" : "guesses", guess_diff < 0 ? "more" : "fewer"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def difference(top_ten_list, current_player)
|
15
|
+
total_time = 0
|
16
|
+
total_guess = 0
|
17
|
+
|
18
|
+
diff_hash = top_ten_list.each{ |player|
|
19
|
+
total_time += player.time
|
20
|
+
total_guess += player.guesses
|
21
|
+
}
|
22
|
+
|
23
|
+
average_time = (total_time.to_f/top_ten_list.length).round - current_player.time
|
24
|
+
average_guess = (total_guess.to_f/top_ten_list.length).round - current_player.guesses
|
25
|
+
|
26
|
+
return average_time, average_guess
|
27
|
+
end
|
28
|
+
|
29
|
+
def print_top_ten(current_player)
|
30
|
+
top_ten_list = get_top_ten
|
31
|
+
|
32
|
+
puts average_string(top_ten_list, current_player) if top_ten_list.length > 1 # print out user's performance compared to average
|
33
|
+
|
34
|
+
# print out top ten results
|
35
|
+
if !top_ten_list.nil?
|
36
|
+
puts ""
|
37
|
+
puts UI::TOP_TEN
|
38
|
+
top_ten_list.each_with_index{|player, index| puts "#{index+1}. " + player.to_s }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_top_ten
|
43
|
+
YAML.load_stream(File.open(UI::DB_STORE)).sort{|player1, player2| # load player objects from db and sort by guesses/time
|
44
|
+
by_guess = player1.guesses <=> player2.guesses # first sort by guesses
|
45
|
+
by_guess == 0 ? player1.time <=> player2.time : by_guess # then sort by time
|
46
|
+
}[0...10] if File.file?(UI::DB_STORE) # pick out top ten
|
47
|
+
end
|
48
|
+
|
49
|
+
def store_game(sequence, guesses, time) #get player name and store details to file
|
50
|
+
print UI::NAME_MESSAGE
|
51
|
+
name = get_name
|
52
|
+
current_player = Player.new(name, sequence, time, guesses) # create new player object
|
53
|
+
|
54
|
+
# write player object to file if file does not exist, or verify whether to add record from user, and write if it exists
|
55
|
+
File.open(UI::DB_STORE, 'a'){|file| file.write(YAML.dump(current_player))} if user_permits_store?
|
56
|
+
|
57
|
+
current_player
|
58
|
+
end
|
59
|
+
|
60
|
+
def user_permits_store? # confirm from user to add record to top-scores if file exists
|
61
|
+
return true if !File.exist?(UI::DB_STORE) # if file does not exist, return true
|
62
|
+
print UI::OVERWRITE_MESSAGE
|
63
|
+
print UI::INPUT_PROMPT
|
64
|
+
option_chosen = false
|
65
|
+
|
66
|
+
return MasterMind::Tobi::GameHelper.yes_or_no?
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_name
|
70
|
+
name = ""
|
71
|
+
|
72
|
+
while name.eql?("")
|
73
|
+
name = gets.chomp.capitalize
|
74
|
+
print UI::INVALID_MESSAGE if name.eql?("")
|
75
|
+
end
|
76
|
+
|
77
|
+
name
|
78
|
+
end
|
79
|
+
|
80
|
+
def print_history(history)
|
81
|
+
if history.empty?
|
82
|
+
print "No history yet. Enter a guess" + UI::INPUT_PROMPT
|
83
|
+
else
|
84
|
+
puts ""
|
85
|
+
puts history
|
86
|
+
print UI::INPUT_PROMPT
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module MasterMind
|
2
|
+
module Tobi
|
3
|
+
class GamePlay
|
4
|
+
attr_reader :entry; attr_reader :correct_elements; attr_reader :correct_positions
|
5
|
+
|
6
|
+
def initialize(entry, correct_elements, correct_positions)
|
7
|
+
@entry = entry; @correct_elements = correct_elements; @correct_positions = correct_positions
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
"#{entry} ::: #{correct_elements} correct #{correct_elements > 1 ? 'elements' : 'element'} ::: #{correct_positions} in correct #{correct_positions > 1 ? 'positions' : 'position'}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module MasterMind
|
2
|
+
module Tobi
|
3
|
+
class GameLogic
|
4
|
+
attr_reader :level; attr_reader :length; attr_reader :color_array; attr_reader :sequence_type
|
5
|
+
|
6
|
+
BEGINNER, INTERMEDIATE, ADVANCED = 0, 1, 2
|
7
|
+
SEQUENCE_TYPES = ['a beginner', 'an intermediate', 'an advanced']
|
8
|
+
COLORS = [['r', 'g', 'b', 'y'], ['r', 'g', 'b', 'y', 'o'], ['r', 'g', 'b', 'y', 'o', 'v']]
|
9
|
+
|
10
|
+
def initialize(level)
|
11
|
+
@level = level
|
12
|
+
@color_array = COLORS[level]
|
13
|
+
@length = color_array.length
|
14
|
+
@sequence_type = SEQUENCE_TYPES[level]
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_sequence
|
18
|
+
(color_array * (rand() * 1000).to_i).shuffle[0...color_array.length] # generate random combination of r/g/b/y
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.check_input(sequence, input)
|
22
|
+
verify_values(input.split(''), sequence, sequence[0..-1])
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.verify_values(split_input, sequence, sequence_copy)
|
26
|
+
result_values = {correct_elements: 0, correct_position: 0}
|
27
|
+
split_input.each_with_index{ |element, index|
|
28
|
+
result_values[:correct_position] += 1 if split_input[index] == sequence[index] # if element in correct position
|
29
|
+
if sequence_copy.include?(element)
|
30
|
+
result_values[:correct_elements] += 1
|
31
|
+
sequence_copy.delete_at(sequence_copy.index(element)) # if in sequence, delete first occurrence so as to counter duplicates
|
32
|
+
end
|
33
|
+
}
|
34
|
+
result_values
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'single_game'
|
2
|
+
require 'logic'
|
3
|
+
require 'ui'
|
4
|
+
require 'io/console'
|
5
|
+
|
6
|
+
module MasterMind
|
7
|
+
module Tobi
|
8
|
+
class MultiPlayer < SinglePlayer
|
9
|
+
attr_reader :hide_guess
|
10
|
+
|
11
|
+
def initialize(sequence, game_logic, hide_guess)
|
12
|
+
super(sequence, game_logic)
|
13
|
+
@hide_guess = hide_guess
|
14
|
+
end
|
15
|
+
|
16
|
+
def start_game
|
17
|
+
number = num_of_players
|
18
|
+
end_guess = 12*number + 1
|
19
|
+
|
20
|
+
puts UI::GENERATE_MESSAGE % [game_logic.sequence_type, game_logic.length, UI::COLOR_STRINGS[game_logic.level]]
|
21
|
+
history_hash = {}
|
22
|
+
guesses_hash = {}
|
23
|
+
(1..number).each {|x|
|
24
|
+
history_hash[x] = []
|
25
|
+
guesses_hash[x] = 0
|
26
|
+
}
|
27
|
+
|
28
|
+
multi_start_game(number, history_hash, guesses_hash)
|
29
|
+
end
|
30
|
+
|
31
|
+
def multi_start_game(number, history_hash, guesses_hash)
|
32
|
+
total_guesses = 0 # total guesses of all players
|
33
|
+
catch :player_wins do
|
34
|
+
while total_guesses < (UI::GUESS_MAX * number) # until all players have exhausted their guesses
|
35
|
+
for index in (1..number) # loop through to allow each player have a guess
|
36
|
+
total_guesses += 1
|
37
|
+
multi_helper(guesses_hash, index, history_hash)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
puts UI::SORRY_MULTI_MESSAGE % sequence.join.upcase if total_guesses == UI::GUESS_MAX * number # guesses exhausted with no winner
|
42
|
+
end
|
43
|
+
|
44
|
+
def multi_helper(guesses_hash, index, history_hash)
|
45
|
+
last_guess = guesses_hash[index] # to store player's last guess
|
46
|
+
print "************"
|
47
|
+
print UI::PLAYER_MESSAGE % index
|
48
|
+
while guesses_hash[index] == last_guess # to counter situations where user enters invalid input, guess would still be same
|
49
|
+
guesses_hash[index] = get_guess(history_hash, guesses_hash, index)
|
50
|
+
throw(:player_wins) if guesses_hash[index] == end_guess # if there is a win
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_guess(history_hash, guesses_hash, index)
|
55
|
+
input = hide_guess ? STDIN.noecho(&:gets).chomp : gets.chomp
|
56
|
+
|
57
|
+
length_or_option = false
|
58
|
+
length_or_option = invalid_length?(input) # invalid length for entry
|
59
|
+
|
60
|
+
if !length_or_option
|
61
|
+
length_or_option = treat_option?(input, history_hash[index]) # entry is a game option
|
62
|
+
end
|
63
|
+
|
64
|
+
if !length_or_option
|
65
|
+
guesses_hash[index] = check_help(input, guesses_hash, history_hash, index)
|
66
|
+
end
|
67
|
+
|
68
|
+
guesses_hash[index]
|
69
|
+
end
|
70
|
+
|
71
|
+
def check_help(input, guesses_hash, history_hash, index)
|
72
|
+
treat_guess(input, guesses_hash[index], history_hash[index]) # player enters a guess
|
73
|
+
end
|
74
|
+
|
75
|
+
def wrong_guess(sequence, guesses, input, history)
|
76
|
+
result = GameLogic.check_input(sequence, input) # get results from input
|
77
|
+
history << GamePlay.new(input, result[:correct_elements], result[:correct_position]) # add game play to history
|
78
|
+
|
79
|
+
puts UI::INFO_MESSAGE % [hide_guess ? "Your Guess" : input.upcase, result[:correct_elements], result[:correct_position]]
|
80
|
+
puts UI::GUESSES_MESSAGE % [guesses, guesses > 1 ? "guesses" : "guess"]
|
81
|
+
print UI::INPUT_PROMPT
|
82
|
+
end
|
83
|
+
|
84
|
+
def num_of_players
|
85
|
+
print UI::MULTI_START_MESSAGE
|
86
|
+
input = gets.chomp
|
87
|
+
|
88
|
+
while (input.to_i <= 1)
|
89
|
+
print UI::INVALID_MESSAGE
|
90
|
+
input = gets.chomp
|
91
|
+
end
|
92
|
+
|
93
|
+
return input.to_i
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'timehelper'
|
2
|
+
|
3
|
+
module MasterMind
|
4
|
+
module Tobi
|
5
|
+
class Player
|
6
|
+
attr_reader :name
|
7
|
+
attr_reader :sequence
|
8
|
+
attr_reader :time
|
9
|
+
attr_reader :guesses
|
10
|
+
include TimeHelper
|
11
|
+
|
12
|
+
def initialize(name, sequence, time, guesses)
|
13
|
+
@name = name; @sequence = sequence; @time = time; @guesses = guesses
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"%s solved '%s' in %s %s over %s" % [name, sequence.join.upcase, guesses, guesses > 1 ? "guesses" : "guess", time_convert(time)]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'ui'
|
2
|
+
require 'timehelper'
|
3
|
+
require 'player'
|
4
|
+
require 'yaml'
|
5
|
+
require 'gameplay'
|
6
|
+
require 'gamemethods'
|
7
|
+
|
8
|
+
module MasterMind
|
9
|
+
module Tobi
|
10
|
+
class SinglePlayer
|
11
|
+
include GameMethods
|
12
|
+
include TimeHelper
|
13
|
+
|
14
|
+
attr_reader :start_time
|
15
|
+
attr_reader :history
|
16
|
+
attr_reader :sequence
|
17
|
+
attr_reader :game_logic
|
18
|
+
attr_accessor :end_guess
|
19
|
+
|
20
|
+
ALLOWED = ['c', 'h', 'q', 'cheat', 'history', 'quit']
|
21
|
+
|
22
|
+
def initialize(sequence, game_logic)
|
23
|
+
@start_time = Time.now
|
24
|
+
@history = []
|
25
|
+
@sequence = sequence
|
26
|
+
@game_logic = game_logic
|
27
|
+
@end_guess = 13
|
28
|
+
end
|
29
|
+
|
30
|
+
# generate game sequence and start game play
|
31
|
+
def start_game
|
32
|
+
print UI::GENERATE_MESSAGE % [game_logic.sequence_type, game_logic.length, UI::COLOR_STRINGS[game_logic.level]]
|
33
|
+
print UI::INPUT_PROMPT
|
34
|
+
|
35
|
+
# allow the user guess up to twelve times before ending game
|
36
|
+
guesses = 0
|
37
|
+
while guesses < UI::GUESS_MAX
|
38
|
+
guesses = process_input(guesses, history)
|
39
|
+
end
|
40
|
+
puts UI::SORRY_SINGLE_MESSAGE % sequence.join.upcase if guesses == UI::GUESS_MAX
|
41
|
+
end
|
42
|
+
|
43
|
+
def process_input(guesses, history)
|
44
|
+
input = gets.chomp.downcase
|
45
|
+
length_or_option = false
|
46
|
+
|
47
|
+
length_or_option = invalid_length?(input)
|
48
|
+
|
49
|
+
if !length_or_option
|
50
|
+
length_or_option = treat_option?(input, history)
|
51
|
+
end
|
52
|
+
|
53
|
+
if !length_or_option
|
54
|
+
guesses = treat_guess(input, guesses, history)
|
55
|
+
end
|
56
|
+
guesses
|
57
|
+
end
|
58
|
+
|
59
|
+
# check if user's guess is longer or fewer than the required length
|
60
|
+
def invalid_length?(input)
|
61
|
+
if input.length < game_logic.length && !(ALLOWED.include?(input))
|
62
|
+
print UI::INPUT_SHORT_MESSAGE
|
63
|
+
return true
|
64
|
+
|
65
|
+
elsif input.length > game_logic.length && !(ALLOWED.include?(input))
|
66
|
+
print UI::INPUT_LONG_MESSAGE
|
67
|
+
return true
|
68
|
+
end
|
69
|
+
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
|
73
|
+
# check if user selects an option
|
74
|
+
def treat_option?(input, history)
|
75
|
+
case input
|
76
|
+
when "h", "history" then print_history(history)
|
77
|
+
when "q", "quit" then exit(0)
|
78
|
+
when "c", "cheat" then print UI::SEQUENCE_MESSAGE % sequence.join.upcase
|
79
|
+
else return false
|
80
|
+
end
|
81
|
+
return true
|
82
|
+
end
|
83
|
+
|
84
|
+
# treat guesses entered by user
|
85
|
+
def treat_guess(input, guesses, history)
|
86
|
+
guesses += 1
|
87
|
+
if input == sequence.join # right guess entered
|
88
|
+
right_guess(start_time, sequence, guesses)
|
89
|
+
guesses = end_guess # sentinel value to end guess loop
|
90
|
+
else
|
91
|
+
wrong_guess(sequence, guesses, input, history) # wrong guess entered
|
92
|
+
end
|
93
|
+
|
94
|
+
return guesses
|
95
|
+
end
|
96
|
+
|
97
|
+
def right_guess(start_time, sequence, guesses)
|
98
|
+
time_elapsed = (Time.now - start_time).to_i # time used by user in seconds
|
99
|
+
current_player = store_game(sequence, guesses, time_elapsed) # store user data to top-scores file
|
100
|
+
|
101
|
+
puts UI::CONGRATS_MESSAGE % [current_player.name, sequence.join.upcase, guesses, guesses > 1 ? "guesses" : "guess",
|
102
|
+
time_convert(time_elapsed) << '.']
|
103
|
+
print_top_ten(current_player)
|
104
|
+
end
|
105
|
+
|
106
|
+
def wrong_guess(sequence, guesses, input, history)
|
107
|
+
result = GameLogic.check_input(sequence, input) # get results from input
|
108
|
+
history << GamePlay.new(input, result[:correct_elements], result[:correct_position]) # add game play to history
|
109
|
+
|
110
|
+
puts UI::INFO_MESSAGE % [input.upcase, result[:correct_elements], result[:correct_position]]
|
111
|
+
puts UI::GUESSES_MESSAGE % [guesses, guesses > 1 ? "guesses" : "guess"]
|
112
|
+
print UI::INPUT_PROMPT
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Player
|
2
|
+
name: tobiloba
|
3
|
+
sequence:
|
4
|
+
- b
|
5
|
+
- g
|
6
|
+
- r
|
7
|
+
- y
|
8
|
+
time: 5
|
9
|
+
guesses: 1
|
10
|
+
--- !ruby/object:Player
|
11
|
+
name: tben
|
12
|
+
sequence:
|
13
|
+
- r
|
14
|
+
- r
|
15
|
+
- y
|
16
|
+
- y
|
17
|
+
- g
|
18
|
+
time: 13
|
19
|
+
guesses: 1
|
20
|
+
--- !ruby/object:Player
|
21
|
+
name: tobi2
|
22
|
+
sequence:
|
23
|
+
- y
|
24
|
+
- b
|
25
|
+
- r
|
26
|
+
- g
|
27
|
+
- y
|
28
|
+
time: 7
|
29
|
+
guesses: 1
|
30
|
+
--- !ruby/object:Player
|
31
|
+
name: tobi3
|
32
|
+
sequence:
|
33
|
+
- y
|
34
|
+
- g
|
35
|
+
- g
|
36
|
+
- y
|
37
|
+
time: 3
|
38
|
+
guesses: 1
|
39
|
+
--- !ruby/object:Player
|
40
|
+
name: tobi4
|
41
|
+
sequence:
|
42
|
+
- r
|
43
|
+
- y
|
44
|
+
- y
|
45
|
+
- y
|
46
|
+
time: 5
|
47
|
+
guesses: 1
|
48
|
+
--- !ruby/object:Player
|
49
|
+
name: tbaba
|
50
|
+
sequence:
|
51
|
+
- r
|
52
|
+
- r
|
53
|
+
- g
|
54
|
+
- y
|
55
|
+
time: 3
|
56
|
+
guesses: 1
|
57
|
+
--- !ruby/object:Player
|
58
|
+
name: tboss
|
59
|
+
sequence:
|
60
|
+
- b
|
61
|
+
- y
|
62
|
+
- g
|
63
|
+
- b
|
64
|
+
time: 15
|
65
|
+
guesses: 1
|
66
|
+
--- !ruby/object:Player
|
67
|
+
name: madara
|
68
|
+
sequence:
|
69
|
+
- r
|
70
|
+
- r
|
71
|
+
- b
|
72
|
+
- y
|
73
|
+
time: 27
|
74
|
+
guesses: 1
|
75
|
+
--- !ruby/object:Player
|
76
|
+
name: 7jsdf
|
77
|
+
sequence:
|
78
|
+
- b
|
79
|
+
- g
|
80
|
+
- b
|
81
|
+
- r
|
82
|
+
time: 3
|
83
|
+
guesses: 1
|
84
|
+
--- !ruby/object:Player
|
85
|
+
name: asdf
|
86
|
+
sequence:
|
87
|
+
- y
|
88
|
+
- r
|
89
|
+
- b
|
90
|
+
- b
|
91
|
+
time: 4
|
92
|
+
guesses: 1
|
93
|
+
--- !ruby/object:Player
|
94
|
+
name: babatee
|
95
|
+
sequence:
|
96
|
+
- g
|
97
|
+
- g
|
98
|
+
- b
|
99
|
+
- r
|
100
|
+
time: 2
|
101
|
+
guesses: 1
|
102
|
+
--- !ruby/object:Player
|
103
|
+
name: Tbff
|
104
|
+
sequence:
|
105
|
+
- r
|
106
|
+
- g
|
107
|
+
- y
|
108
|
+
- b
|
109
|
+
time: 74
|
110
|
+
guesses: 2
|
111
|
+
--- !ruby/object:Player
|
112
|
+
name: Toisdaf
|
113
|
+
sequence:
|
114
|
+
- r
|
115
|
+
- g
|
116
|
+
- y
|
117
|
+
- b
|
118
|
+
time: 8
|
119
|
+
guesses: 2
|
120
|
+
--- !ruby/object:Player
|
121
|
+
name: Yuo
|
122
|
+
sequence:
|
123
|
+
- r
|
124
|
+
- g
|
125
|
+
- y
|
126
|
+
- b
|
127
|
+
time: 9
|
128
|
+
guesses: 2
|
129
|
+
--- !ruby/object:Player
|
130
|
+
name: Ttiosd
|
131
|
+
sequence:
|
132
|
+
- r
|
133
|
+
- g
|
134
|
+
- y
|
135
|
+
- b
|
136
|
+
time: 24
|
137
|
+
guesses: 2
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module MasterMind
|
2
|
+
module Tobi
|
3
|
+
module TimeHelper
|
4
|
+
def time_convert(time_int)
|
5
|
+
hours = time_int / 3600
|
6
|
+
minutes = (time_int % 3600) / 60
|
7
|
+
seconds = (time_int % 3600) % 60
|
8
|
+
time_string = construct_string(hours, minutes, seconds)
|
9
|
+
end
|
10
|
+
|
11
|
+
def construct_string(hours, minutes, seconds)
|
12
|
+
time_string = ''
|
13
|
+
if hours >= 1
|
14
|
+
time_string << (hours.to_s + (time == 1 ? ' hour' :' hours'))
|
15
|
+
time_string << ', ' if minutes > 0
|
16
|
+
end
|
17
|
+
|
18
|
+
if minutes >= 1
|
19
|
+
time_string << (minutes.to_s + (minutes == 1 ? ' minute' : ' minutes'))
|
20
|
+
time_string << ', ' if seconds > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
if seconds >= 1
|
24
|
+
time_string << (seconds.to_s + (seconds == 1 ? ' second' : ' seconds'))
|
25
|
+
elsif seconds == 0 && time_string == ''
|
26
|
+
time_string << '0 seconds'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module MasterMind
|
2
|
+
module Tobi
|
3
|
+
module UI
|
4
|
+
|
5
|
+
GUESS_MAX = 12
|
6
|
+
|
7
|
+
WELCOME_MESSAGE = "\nWelcome to the Classy MasterMind game by Tobi\n"
|
8
|
+
|
9
|
+
INPUT_PROMPT = "\n>> "
|
10
|
+
|
11
|
+
OPTIONS_MESSAGE = "\nWould you like to (p)lay, (r)ead the instructions or (quit) ?"
|
12
|
+
|
13
|
+
HELP_MESSAGE = "\nOnce game starts, a random code is generated and you're asked to guess what the code is.
|
14
|
+
Every code is a four/five/six digit word made up by the letters [r, g, b, y]/[r, g, b, y, o]/[r, g, b, y, o, v]
|
15
|
+
depending on difficulty levels beginner/intermediate/advanced levels. You have twelve guesses per game.
|
16
|
+
On every guess, you are presented with a message identifying the number of elements you got correctly, and in what positions.
|
17
|
+
To view entry history, enter h or history at any time
|
18
|
+
To view sequence generated, enter c or cheat at any time
|
19
|
+
To quit the game at any point enter q or quit\n\n"
|
20
|
+
|
21
|
+
BEGINNER_COLOR = "(r)ed, (g)reen, (b)lue and (y)ellow"
|
22
|
+
|
23
|
+
INTERMEDIATE_COLOR = "(r)ed, (g)reen, (b)lue, (y)ellow, and (o)range"
|
24
|
+
|
25
|
+
ADVANCED_COLOR = "(r)ed, (g)reen, (b)lue, (y)ellow, (o)range and (v)iolet"
|
26
|
+
|
27
|
+
COLOR_STRINGS = [BEGINNER_COLOR, INTERMEDIATE_COLOR, ADVANCED_COLOR]
|
28
|
+
|
29
|
+
GENERATE_MESSAGE = "\nI have generated %s sequence with %s elements made \
|
30
|
+
up of: %s\nUse (q)uit at any time to end the game. \nWhat's your guess?"
|
31
|
+
|
32
|
+
INVALID_MESSAGE = "\nEntry invalid! Please try again" + INPUT_PROMPT
|
33
|
+
|
34
|
+
INPUT_SHORT_MESSAGE = "Input too short. Please enter guess correctly" + INPUT_PROMPT
|
35
|
+
|
36
|
+
INPUT_LONG_MESSAGE = "Input too long. Please enter guess correctly." + INPUT_PROMPT
|
37
|
+
|
38
|
+
SEQUENCE_MESSAGE = "The sequence is %s" + INPUT_PROMPT
|
39
|
+
|
40
|
+
CONGRATS_MESSAGE = "\n%s, You guessed the sequence '%s' in %s %s over %s"
|
41
|
+
|
42
|
+
INFO_MESSAGE = "'%s' has %s of the correct elements with %s in the correct positions."
|
43
|
+
|
44
|
+
END_MESSAGE = "Do you want to (p)lay again or (q)uit?"
|
45
|
+
|
46
|
+
GUESSES_MESSAGE = "You've taken %s %s"
|
47
|
+
|
48
|
+
LEVEL_MESSAGE = "\nDifficulty level: (b)eginner, (i)ntermediate or (a)dvanced? " + INPUT_PROMPT
|
49
|
+
|
50
|
+
NAME_MESSAGE = "\nCongratulations! You've guessed the sequence! What's your name?" + INPUT_PROMPT
|
51
|
+
|
52
|
+
DB_STORE = 'store.yaml'
|
53
|
+
|
54
|
+
TOP_TEN = '=== TOP TEN ==='
|
55
|
+
|
56
|
+
OVERWRITE_MESSAGE = 'Data file already exists. Do you want to add your score to top scores? (y)es or (n)o..'
|
57
|
+
|
58
|
+
MODE_SELECT = "\nPlease choose mode >>> (s)ingle or (m)ulti player mode?" + INPUT_PROMPT
|
59
|
+
|
60
|
+
MULTI_START_MESSAGE = "Welcome to the MultiPlayer Challenge. How many users will be playing today?" + INPUT_PROMPT
|
61
|
+
|
62
|
+
PLAYER_MESSAGE = "********Player %s's turn" + INPUT_PROMPT
|
63
|
+
|
64
|
+
SORRY_SINGLE_MESSAGE = "Sorry, You lost. The sequence is %s"
|
65
|
+
|
66
|
+
SORRY_MULTI_MESSAGE = "Sorry, You all lost. The sequence is %s"
|
67
|
+
|
68
|
+
PASSWORD_MESSAGE = "\nWould you like to hide each player's guesses? (y)es or (n)o ?" + INPUT_PROMPT
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
lib_master = File.expand_path('../mastermind/tobi', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib_master) unless $LOAD_PATH.include?(lib_master)
|
3
|
+
require 'ui'
|
4
|
+
require 'gamehelper'
|
5
|
+
|
6
|
+
module MasterMind
|
7
|
+
module Tobi
|
8
|
+
extend GameHelper
|
9
|
+
VERSION = 1.0
|
10
|
+
|
11
|
+
def self.start
|
12
|
+
puts UI::WELCOME_MESSAGE
|
13
|
+
print UI::OPTIONS_MESSAGE + UI::INPUT_PROMPT
|
14
|
+
user_choice
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tobi-mastermind
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.0'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tobi Oduah
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: MasterMind game implemented in a fun way
|
56
|
+
email:
|
57
|
+
- tobi.oduah@andela.com
|
58
|
+
executables:
|
59
|
+
- console
|
60
|
+
- mastermind
|
61
|
+
- setup
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- bin/console
|
66
|
+
- bin/mastermind
|
67
|
+
- bin/setup
|
68
|
+
- lib/mastermind/tobi/gamehelper.rb
|
69
|
+
- lib/mastermind/tobi/gamemethods.rb
|
70
|
+
- lib/mastermind/tobi/gameplay.rb
|
71
|
+
- lib/mastermind/tobi/logic.rb
|
72
|
+
- lib/mastermind/tobi/multi_game.rb
|
73
|
+
- lib/mastermind/tobi/player.rb
|
74
|
+
- lib/mastermind/tobi/single_game.rb
|
75
|
+
- lib/mastermind/tobi/store.yaml
|
76
|
+
- lib/mastermind/tobi/timehelper.rb
|
77
|
+
- lib/mastermind/tobi/ui.rb
|
78
|
+
- lib/mastermind_start.rb
|
79
|
+
homepage: http://github.com/andela-toduah
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata:
|
83
|
+
allowed_push_host: https://rubygems.org
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.4.5.1
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: MasterMind
|
104
|
+
test_files: []
|