tobi-mastermind 1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|