codebreaker_artem 0.2.1 → 0.3.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/README.md +1 -2
- data/codebreaker_artem.gemspec +3 -1
- data/lib/codebreaker_artem/cli.rb +115 -0
- data/lib/codebreaker_artem/game.rb +32 -54
- data/lib/codebreaker_artem/starter.rb +31 -0
- data/lib/codebreaker_artem/validator.rb +5 -0
- data/lib/codebreaker_artem/version.rb +1 -1
- metadata +21 -5
- data/lib/codebreaker_artem/game_utils.rb +0 -107
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '056680463d26bc82bcde45002724db966ed5fc50'
|
4
|
+
data.tar.gz: 4c394660eb8fbca917bafb022f630c64d84d8dd8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8047618ac8da41e254767769c12cc0fbfa7a3019e86304748cebd4ba03cab7a7908f2d4b256c9e41ca8b9defae99fb4419251350af61e316f5c23a6b9c4694bf
|
7
|
+
data.tar.gz: 3743e9b166af684ce964de77d433adc0638cb26e45b782cae69df1998c9b0c3a32384cc522e38fcb0ed1d0f62f8fd4170833de4ecd3fbcce6e2c8b2a4249af2c
|
data/README.md
CHANGED
@@ -24,8 +24,7 @@ Or install it yourself as:
|
|
24
24
|
```ruby
|
25
25
|
require 'codebreaker_artem'
|
26
26
|
|
27
|
-
|
28
|
-
game.play
|
27
|
+
CodebreakerArtem::Starter.start
|
29
28
|
```
|
30
29
|
|
31
30
|
The code-maker, which will be played by the application, creates a secret code of four numbers between 1 and 6.
|
data/codebreaker_artem.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = CodebreakerArtem::VERSION
|
9
9
|
spec.licenses = ['MIT']
|
10
10
|
spec.authors = ["b-artem"]
|
11
|
-
spec.email = ["
|
11
|
+
spec.email = ["artemb.dev@gmail.com"]
|
12
12
|
|
13
13
|
spec.summary = %q{Codebreaker game.}
|
14
14
|
spec.description = %q{Codebreaker is a logic game in which a code-breaker
|
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
which will be played by the application, creates a secret code of four
|
17
17
|
numbers between 1 and 6.}
|
18
18
|
spec.homepage = "https://github.com/b-artem/codebreaker_artem"
|
19
|
+
spec.required_ruby_version = ">=1.9.3"
|
19
20
|
|
20
21
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
21
22
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
@@ -36,4 +37,5 @@ Gem::Specification.new do |spec|
|
|
36
37
|
spec.add_development_dependency "bundler", "~> 1.15"
|
37
38
|
spec.add_development_dependency "rake", "~> 10.0"
|
38
39
|
spec.add_development_dependency "rspec", "~> 3.0"
|
40
|
+
spec.add_development_dependency 'pry', "~> 0.10.0"
|
39
41
|
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require_relative 'validator'
|
2
|
+
|
3
|
+
module CodebreakerArtem
|
4
|
+
class CLI
|
5
|
+
class << self
|
6
|
+
def welcome_msg(max_guess_number)
|
7
|
+
puts %(
|
8
|
+
Welcome to the Codebreaker Game!
|
9
|
+
New secret code has just been generated
|
10
|
+
You have #{max_guess_number} attempts
|
11
|
+
Type 'hint' to take a hint
|
12
|
+
Type 'exit' to exit the game
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def guess_prompt(guess_count)
|
17
|
+
print "Please enter your guess no. #{guess_count + 1}: "
|
18
|
+
end
|
19
|
+
|
20
|
+
def submit_guess
|
21
|
+
guess = $stdin.gets.chomp
|
22
|
+
exit?(guess)
|
23
|
+
return :hint if guess =~ /^hint$/i
|
24
|
+
return wrong_code_pattern unless Validator.code_valid?(guess)
|
25
|
+
guess
|
26
|
+
end
|
27
|
+
|
28
|
+
def show_hint(number = nil, position = nil)
|
29
|
+
return one_hint_only unless number && position
|
30
|
+
puts "HINT: Number #{number} is in position #{position + 1}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def show_mark(mark)
|
34
|
+
puts mark
|
35
|
+
end
|
36
|
+
|
37
|
+
def win(code, score)
|
38
|
+
win_msg
|
39
|
+
finish_game(code, score)
|
40
|
+
end
|
41
|
+
|
42
|
+
def lose(code, score, max_guess_number)
|
43
|
+
lose_msg(max_guess_number)
|
44
|
+
finish_game(code, score)
|
45
|
+
end
|
46
|
+
|
47
|
+
def win_msg
|
48
|
+
puts "\nCONGRATULATIONS! YOU'VE WON the Codebreaker game!\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
def lose_msg(max_guess_number)
|
52
|
+
puts "GAME OVER. You've used all #{max_guess_number} attempts\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
def finish_game(code, score)
|
56
|
+
reveal_code(code)
|
57
|
+
save_score(score)
|
58
|
+
end
|
59
|
+
|
60
|
+
def reveal_code(code)
|
61
|
+
puts "The secret code was #{code}\n"
|
62
|
+
end
|
63
|
+
|
64
|
+
def one_hint_only
|
65
|
+
puts 'You have only one hint!'
|
66
|
+
end
|
67
|
+
|
68
|
+
def wrong_code_pattern
|
69
|
+
puts 'Code must contain 4 numbers from 1 to 6. Please try again'
|
70
|
+
end
|
71
|
+
|
72
|
+
def exit?(input)
|
73
|
+
exit if input =~ /^exit$/i
|
74
|
+
end
|
75
|
+
|
76
|
+
def save_score(score)
|
77
|
+
return false unless yes? { 'Do you want to save your score? [y/n]: ' }
|
78
|
+
begin
|
79
|
+
Dir.mkdir('./score') unless File.exist?('./score')
|
80
|
+
file = File.new('./score/score.txt', 'a')
|
81
|
+
rescue
|
82
|
+
puts "Can't create file './score/score.txt'"
|
83
|
+
return
|
84
|
+
end
|
85
|
+
write_score_to_file(file, score)
|
86
|
+
file.close
|
87
|
+
end
|
88
|
+
|
89
|
+
def write_score_to_file(file, score)
|
90
|
+
print 'Please enter your name: '
|
91
|
+
name = $stdin.gets.chomp
|
92
|
+
file << "Name: #{name}\n"
|
93
|
+
file << "Time: #{Time.now}\n"
|
94
|
+
file << "Score: #{score}\n\n"
|
95
|
+
puts "Your score was added to a file #{file.path}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def play_again
|
99
|
+
exit unless yes? { 'Would you like to play one more time? [y/n]: ' }
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
def yes?
|
104
|
+
print yield if block_given?
|
105
|
+
loop do
|
106
|
+
answer = $stdin.gets.chomp
|
107
|
+
exit?(answer)
|
108
|
+
return false if answer =~ /^n/i
|
109
|
+
return true if answer =~ /^y/i
|
110
|
+
puts "Please enter 'y' or 'n': "
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -1,37 +1,40 @@
|
|
1
|
-
require_relative '
|
1
|
+
require_relative 'validator'
|
2
2
|
|
3
3
|
module CodebreakerArtem
|
4
4
|
class Game
|
5
|
-
include GameUtils
|
6
5
|
MAX_GUESS_NUMBER = 10
|
7
6
|
|
8
|
-
attr_reader :secret_code
|
7
|
+
attr_reader :secret_code, :guess_count, :score
|
9
8
|
|
10
9
|
def initialize
|
11
10
|
initial_values_set
|
12
11
|
end
|
13
12
|
|
14
|
-
def play
|
15
|
-
start
|
16
|
-
loop do
|
17
|
-
guess_prompt
|
18
|
-
mark_guess(submit_guess)
|
19
|
-
return lose if @guess_count >= MAX_GUESS_NUMBER
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
13
|
def start
|
26
14
|
initial_values_set
|
27
15
|
generate_secret_code
|
28
|
-
welcome_msg
|
29
16
|
end
|
30
17
|
|
18
|
+
def mark_guess(guess)
|
19
|
+
return false unless Validator.code_valid? guess
|
20
|
+
@guess_count += 1
|
21
|
+
counts = plus_minus_count(guess)
|
22
|
+
score_set(counts[0], counts[1])
|
23
|
+
'' << ('+' * counts[0]) << ('-' * counts[1])
|
24
|
+
end
|
25
|
+
|
26
|
+
def hint
|
27
|
+
return unless hint_available?
|
28
|
+
@hint_available = false
|
29
|
+
position = rand(0..3)
|
30
|
+
[@secret_code[position], position]
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
31
35
|
def initial_values_set
|
32
36
|
@guess_count = 0
|
33
37
|
@score = 0
|
34
|
-
@numbers_guess_count = [0, 0, 0, 0]
|
35
38
|
@hint_available = true
|
36
39
|
end
|
37
40
|
|
@@ -40,53 +43,28 @@ module CodebreakerArtem
|
|
40
43
|
4.times { @secret_code << rand(1..6).to_s }
|
41
44
|
end
|
42
45
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
mark
|
46
|
+
def plus_minus_count(guess)
|
47
|
+
zipped = @secret_code.split('').zip(guess.split(''))
|
48
|
+
not_plus = zipped.delete_if { |item| item.uniq.one? }
|
49
|
+
return [4, 0] if not_plus.empty?
|
50
|
+
plus_count = 4 - not_plus.count
|
51
|
+
[plus_count, minus_count(not_plus)]
|
50
52
|
end
|
51
53
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
guess.
|
56
|
-
|
57
|
-
plus_count += 1
|
58
|
-
@numbers_guess_count[index] += 1
|
59
|
-
elsif @secret_code.include? number
|
60
|
-
minus_count += 1
|
61
|
-
end
|
62
|
-
end
|
63
|
-
[plus_count, minus_count]
|
54
|
+
def minus_count(not_plus)
|
55
|
+
code = not_plus.transpose[0]
|
56
|
+
guess = not_plus.transpose[1]
|
57
|
+
guess.each { |item| code.delete_at(code.index(item) || code.length) }
|
58
|
+
not_plus.count - code.size
|
64
59
|
end
|
65
60
|
|
66
61
|
def score_set(plus_count, minus_count)
|
67
62
|
@score = (plus_count * 3) + (minus_count * 1) +
|
68
|
-
(MAX_GUESS_NUMBER - @guess_count
|
63
|
+
(MAX_GUESS_NUMBER - @guess_count)
|
69
64
|
end
|
70
65
|
|
71
66
|
def hint_available?
|
72
|
-
|
73
|
-
true
|
74
|
-
end
|
75
|
-
|
76
|
-
def win
|
77
|
-
win_msg
|
78
|
-
finish_game
|
79
|
-
end
|
80
|
-
|
81
|
-
def lose
|
82
|
-
lose_msg
|
83
|
-
finish_game
|
84
|
-
end
|
85
|
-
|
86
|
-
def finish_game
|
87
|
-
reveal_code
|
88
|
-
save_score
|
89
|
-
play_again
|
67
|
+
@hint_available
|
90
68
|
end
|
91
69
|
end
|
92
70
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative 'game'
|
2
|
+
require_relative 'cli'
|
3
|
+
|
4
|
+
module CodebreakerArtem
|
5
|
+
class Starter
|
6
|
+
MAX = CodebreakerArtem::Game::MAX_GUESS_NUMBER
|
7
|
+
|
8
|
+
def self.start
|
9
|
+
game = CodebreakerArtem::Game.new
|
10
|
+
game.start
|
11
|
+
CLI.welcome_msg(MAX)
|
12
|
+
play(game)
|
13
|
+
start if CLI.play_again
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.play(game)
|
17
|
+
loop do
|
18
|
+
CLI.guess_prompt(game.guess_count)
|
19
|
+
case input = CLI.submit_guess
|
20
|
+
when nil then next
|
21
|
+
when :hint then CLI.show_hint(*game.hint)
|
22
|
+
else
|
23
|
+
mark = game.mark_guess(input)
|
24
|
+
CLI.show_mark(mark)
|
25
|
+
return CLI.win(input, game.score) if mark == '++++'
|
26
|
+
end
|
27
|
+
return CLI.lose(game.secret_code, game.score, MAX) if game.guess_count >= MAX
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codebreaker_artem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- b-artem
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,13 +52,27 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.10.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.10.0
|
55
69
|
description: |-
|
56
70
|
Codebreaker is a logic game in which a code-breaker
|
57
71
|
tries to break a secret code created by a code-maker. The code-maker,
|
58
72
|
which will be played by the application, creates a secret code of four
|
59
73
|
numbers between 1 and 6.
|
60
74
|
email:
|
61
|
-
-
|
75
|
+
- artemb.dev@gmail.com
|
62
76
|
executables: []
|
63
77
|
extensions: []
|
64
78
|
extra_rdoc_files: []
|
@@ -74,8 +88,10 @@ files:
|
|
74
88
|
- bin/setup
|
75
89
|
- codebreaker_artem.gemspec
|
76
90
|
- lib/codebreaker_artem.rb
|
91
|
+
- lib/codebreaker_artem/cli.rb
|
77
92
|
- lib/codebreaker_artem/game.rb
|
78
|
-
- lib/codebreaker_artem/
|
93
|
+
- lib/codebreaker_artem/starter.rb
|
94
|
+
- lib/codebreaker_artem/validator.rb
|
79
95
|
- lib/codebreaker_artem/version.rb
|
80
96
|
homepage: https://github.com/b-artem/codebreaker_artem
|
81
97
|
licenses:
|
@@ -90,7 +106,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
106
|
requirements:
|
91
107
|
- - ">="
|
92
108
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
109
|
+
version: 1.9.3
|
94
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
111
|
requirements:
|
96
112
|
- - ">="
|
@@ -1,107 +0,0 @@
|
|
1
|
-
require_relative 'game'
|
2
|
-
|
3
|
-
module GameUtils
|
4
|
-
include CodebreakerArtem
|
5
|
-
|
6
|
-
def welcome_msg
|
7
|
-
print "Welcome to the Codebreaker Game!\n" \
|
8
|
-
"New secret code has just been generated\n" \
|
9
|
-
"You have #{Game::MAX_GUESS_NUMBER} attempts\n" \
|
10
|
-
"Type 'hint' to take a hint\n" \
|
11
|
-
"Type 'exit' to exit the game\n\n"
|
12
|
-
end
|
13
|
-
|
14
|
-
def guess_prompt
|
15
|
-
print "Please enter your guess no. #{@guess_count}: "
|
16
|
-
end
|
17
|
-
|
18
|
-
def submit_guess
|
19
|
-
guess = $stdin.gets.chomp
|
20
|
-
exit?(guess)
|
21
|
-
return false if take_hint(guess)
|
22
|
-
return wrong_code_length unless guess.length == 4
|
23
|
-
return wrong_code_numbers unless guess =~ /[1-6]{4}/
|
24
|
-
@guess_count += 1
|
25
|
-
guess
|
26
|
-
end
|
27
|
-
|
28
|
-
def save_score
|
29
|
-
return false unless yes? { 'Do you want to save your score? (y/n): ' }
|
30
|
-
begin
|
31
|
-
Dir.mkdir('./score') unless File.exist?('./score')
|
32
|
-
file = File.new('./score/score.txt', 'a')
|
33
|
-
rescue
|
34
|
-
puts "Can't create file './score/score.txt'"
|
35
|
-
return
|
36
|
-
end
|
37
|
-
write_score_to_file file
|
38
|
-
file.close
|
39
|
-
end
|
40
|
-
|
41
|
-
def write_score_to_file(file)
|
42
|
-
print 'Please enter your name: '
|
43
|
-
name = $stdin.gets.chomp
|
44
|
-
file << "Name: #{name}\n"
|
45
|
-
file << "Time: #{Time.now}\n"
|
46
|
-
file << "Score: #{@score}\n\n"
|
47
|
-
puts "Your data was added to a file #{file.path}"
|
48
|
-
end
|
49
|
-
|
50
|
-
def take_hint(input = nil)
|
51
|
-
return false unless input =~ /hint/i
|
52
|
-
return false unless hint_available?
|
53
|
-
position = @numbers_guess_count.index(@numbers_guess_count.min)
|
54
|
-
secret_number = @secret_code[position]
|
55
|
-
puts "HINT: Number #{secret_number} is in position #{position + 1}"
|
56
|
-
@hint_available = false
|
57
|
-
secret_number
|
58
|
-
end
|
59
|
-
|
60
|
-
def one_hint_only
|
61
|
-
puts 'You have only one hint'
|
62
|
-
end
|
63
|
-
|
64
|
-
def play_again
|
65
|
-
exit unless yes? { 'Would you like to play one more time? (y/n): ' }
|
66
|
-
start
|
67
|
-
end
|
68
|
-
|
69
|
-
def exit?(input)
|
70
|
-
exit if input =~ /exit/
|
71
|
-
false
|
72
|
-
end
|
73
|
-
|
74
|
-
def yes?
|
75
|
-
print yield if block_given?
|
76
|
-
loop do
|
77
|
-
answer = $stdin.gets.chomp
|
78
|
-
exit?(answer)
|
79
|
-
return false if answer =~ /^n/i
|
80
|
-
return true if answer =~ /^y/i
|
81
|
-
puts "Please enter 'y' or 'n': "
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def wrong_code_length
|
86
|
-
puts 'Code contains 4 numbers, please try again'
|
87
|
-
false
|
88
|
-
end
|
89
|
-
|
90
|
-
def wrong_code_numbers
|
91
|
-
puts 'All numbers are between 1 and 6, please try again'
|
92
|
-
false
|
93
|
-
end
|
94
|
-
|
95
|
-
def win_msg
|
96
|
-
puts "\nCONGRATULATIONS! You've won the Codebreaker game!"
|
97
|
-
end
|
98
|
-
|
99
|
-
def lose_msg
|
100
|
-
puts "You've used all your attempts (#{Game::MAX_GUESS_NUMBER})" \
|
101
|
-
" and LOST THE GAME\n"
|
102
|
-
end
|
103
|
-
|
104
|
-
def reveal_code
|
105
|
-
puts "The secret code was #{@secret_code}\n"
|
106
|
-
end
|
107
|
-
end
|