games_bfox 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -12
- data/config/application.yml +5 -0
- data/games.gemspec +2 -1
- data/lib/games/mastermind/board_builder.rb +6 -2
- data/lib/games/mastermind/computer_player_expert.rb +31 -0
- data/lib/games/mastermind/computer_player_novice.rb +18 -0
- data/lib/games/mastermind/game.rb +69 -15
- data/lib/games/mastermind/guess_evaluator.rb +105 -68
- data/lib/games/mastermind/guess_evaluator_result.rb +11 -0
- data/lib/games/mastermind/human_player.rb +9 -0
- data/lib/games/mastermind/io_helpers.rb +65 -0
- data/lib/games/mastermind/peg.rb +2 -4
- data/lib/games/mastermind/pegs.rb +1 -9
- data/lib/games/mastermind/pegs_factory.rb +3 -5
- data/lib/games/mastermind/players_factory.rb +32 -8
- data/lib/games/mastermind/secret_code.rb +19 -0
- data/lib/games/mastermind.rb +9 -2
- data/lib/games/shared/game.rb +56 -70
- data/lib/games/shared/{input_helper.rb → io_helpers.rb} +40 -32
- data/lib/games/shared/player.rb +1 -3
- data/lib/games/shared/player_factory.rb +9 -0
- data/lib/games/shared/players_factory.rb +9 -0
- data/lib/games/tictactoe/board.rb +3 -4
- data/lib/games/tictactoe/board_builder.rb +3 -3
- data/lib/games/tictactoe/board_presenter_terminal.rb +3 -3
- data/lib/games/tictactoe/computer_player_expert.rb +12 -0
- data/lib/games/tictactoe/computer_player_novice.rb +10 -0
- data/lib/games/tictactoe/game.rb +45 -12
- data/lib/games/tictactoe/human_player.rb +9 -0
- data/lib/games/tictactoe/io_helpers.rb +81 -0
- data/lib/games/tictactoe/player.rb +4 -0
- data/lib/games/tictactoe/players_factory.rb +49 -5
- data/lib/games/tictactoe/square.rb +0 -3
- data/lib/games/tictactoe/squares.rb +1 -1
- data/lib/games/tictactoe/squares_factory.rb +7 -11
- data/lib/games/tictactoe.rb +9 -2
- data/lib/games/version.rb +1 -1
- metadata +32 -17
- data/lib/games/mastermind/colors.rb +0 -14
- data/lib/games/mastermind/game_config.rb +0 -48
- data/lib/games/mastermind/game_resetter.rb +0 -19
- data/lib/games/mastermind/game_state_changer.rb +0 -41
- data/lib/games/mastermind/input_helper.rb +0 -67
- data/lib/games/mastermind/move_generator.rb +0 -46
- data/lib/games/shared/array_iterator.rb +0 -28
- data/lib/games/tictactoe/game_config.rb +0 -73
- data/lib/games/tictactoe/game_resetter.rb +0 -16
- data/lib/games/tictactoe/game_state_changer.rb +0 -17
- data/lib/games/tictactoe/input_helper.rb +0 -87
- data/lib/games/tictactoe/move_generator.rb +0 -68
@@ -0,0 +1,19 @@
|
|
1
|
+
module MM
|
2
|
+
class SecretCode
|
3
|
+
def self.generate(io_helpers, is_code_guesser_human)
|
4
|
+
if is_code_guesser_human
|
5
|
+
set_secret_code
|
6
|
+
else
|
7
|
+
io_helpers.get_secret_code_from_user
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.set_secret_code
|
12
|
+
secret_code = []
|
13
|
+
4.times do
|
14
|
+
secret_code.push((1..6).to_a.sample)
|
15
|
+
end
|
16
|
+
secret_code
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/games/mastermind.rb
CHANGED
@@ -4,10 +4,17 @@ Dir[File.join(File.expand_path(File.dirname(__FILE__)), 'mastermind', '*.rb')].e
|
|
4
4
|
class Mastermind
|
5
5
|
def self.run
|
6
6
|
io = Shared::IOTerminal.new
|
7
|
+
io_helpers = MM::IOHelpers.new(io)
|
7
8
|
board_presenter = MM::BoardPresenterTerminal.new
|
9
|
+
board_builder = MM::BoardBuilder.new
|
10
|
+
players_factory = MM::PlayersFactory.new(io_helpers)
|
8
11
|
|
9
|
-
game = MM::Game.new(
|
10
|
-
|
12
|
+
game = MM::Game.new(
|
13
|
+
io_helpers: io_helpers,
|
14
|
+
board_presenter: board_presenter,
|
15
|
+
board_builder: board_builder,
|
16
|
+
players_factory: players_factory
|
17
|
+
)
|
11
18
|
game.play
|
12
19
|
end
|
13
20
|
end
|
data/lib/games/shared/game.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
Dir[File.join(File.dirname(__FILE__), '*.rb')].each {|file| require file }
|
2
|
+
# note the below exclude the game subclasses, because these classes inherit from this class, so if we require these before the parent class is read, an error will be generated.
|
2
3
|
Dir[File.join(File.expand_path("..", File.dirname(__FILE__)), 'tictactoe', '*.rb')].each {|file| require file unless file == File.join(File.expand_path("..", File.dirname(__FILE__)), 'tictactoe', 'game.rb')}
|
3
4
|
Dir[File.join(File.expand_path("..", File.dirname(__FILE__)), 'mastermind', '*.rb')].each {|file| require file unless file == File.join(File.expand_path("..", File.dirname(__FILE__)), 'mastermind', 'game.rb')}
|
4
5
|
|
@@ -6,60 +7,29 @@ module Shared
|
|
6
7
|
class Game
|
7
8
|
attr_accessor :board, :board_presenter, :board_builder
|
8
9
|
attr_accessor :players, :players_factory
|
9
|
-
attr_accessor :
|
10
|
-
|
11
|
-
attr_accessor :game_resetter
|
12
|
-
attr_accessor :move_generator
|
13
|
-
attr_reader :io, :input_helper, :game_module
|
10
|
+
attr_accessor :number_of_turns_taken, :won_flag
|
11
|
+
attr_reader :io_helpers
|
14
12
|
|
15
|
-
def initialize(args = {})
|
16
|
-
@game_module = args.fetch(:game_module, nil)
|
17
|
-
@io = args.fetch(:io, IOTerminal.new)
|
18
|
-
@board_presenter = args.fetch(:board_presenter, nil)
|
19
|
-
|
20
|
-
@input_helper = game_module::InputHelper.new(@io)
|
21
|
-
@board_builder = game_module::BoardBuilder.new
|
22
|
-
@game_state_changer = game_module::GameStateChanger.new
|
23
|
-
@game_resetter = game_module::GameResetter.new
|
24
|
-
@move_generator = game_module::MoveGenerator.new
|
25
|
-
@players_factory = game_module::PlayersFactory.new
|
26
|
-
@config = game_module::GameConfig.new(@input_helper)
|
27
|
-
|
28
|
-
@number_of_turns_taken = 0
|
29
|
-
end
|
30
13
|
|
31
|
-
def
|
32
|
-
|
33
|
-
config.one_time_setup
|
34
|
-
end
|
35
|
-
|
36
|
-
def every_time_setup
|
37
|
-
#setup gets necessary info from user and stores it in config object
|
38
|
-
config.every_time_setup
|
39
|
-
self.players = players_factory.generate_players(config)
|
40
|
-
self.board = board_builder.generate_empty_board(config)
|
41
|
-
local_setup
|
42
|
-
end
|
14
|
+
def initialize(args = {})
|
15
|
+
@board_presenter = args.fetch(:board_presenter)
|
43
16
|
|
44
|
-
|
45
|
-
|
46
|
-
|
17
|
+
@io_helpers = args.fetch(:io_helpers)
|
18
|
+
@board_builder = args.fetch(:board_builder)
|
19
|
+
@players_factory = args.fetch(:players_factory)
|
47
20
|
|
48
|
-
|
49
|
-
def io=(new_io)
|
50
|
-
@io = new_io
|
51
|
-
self.input_helper = game_module::InputHelper.new(new_io)
|
21
|
+
@number_of_turns_taken = 0
|
52
22
|
end
|
53
23
|
|
54
24
|
def play
|
55
25
|
initial_instructions
|
56
26
|
one_time_setup
|
57
|
-
|
27
|
+
loop do
|
58
28
|
every_time_setup
|
59
29
|
while !over?
|
60
30
|
print_board
|
61
|
-
move =
|
62
|
-
|
31
|
+
move = current_player.make_move(self)
|
32
|
+
change_game_state(move)
|
63
33
|
end
|
64
34
|
|
65
35
|
#need to print_final_iteration of board
|
@@ -67,12 +37,12 @@ module Shared
|
|
67
37
|
|
68
38
|
if won?
|
69
39
|
winning_prompt
|
70
|
-
elsif
|
71
|
-
no_winner_prompt
|
40
|
+
elsif no_more_turns?
|
41
|
+
no_winner_prompt(self)
|
72
42
|
custom_final_message(self)
|
73
43
|
end
|
74
44
|
|
75
|
-
|
45
|
+
reset_game
|
76
46
|
new_game_starting_graphic
|
77
47
|
end
|
78
48
|
end
|
@@ -85,26 +55,10 @@ module Shared
|
|
85
55
|
current_player.name
|
86
56
|
end
|
87
57
|
|
88
|
-
def current_player_human?
|
89
|
-
current_player.type == :human
|
90
|
-
end
|
91
|
-
|
92
|
-
def current_player_computer?
|
93
|
-
current_player.type == :computer
|
94
|
-
end
|
95
|
-
|
96
58
|
def move_forward_one_turn
|
97
59
|
self.number_of_turns_taken += 1
|
98
60
|
end
|
99
61
|
|
100
|
-
def generate_empty_board(config)
|
101
|
-
board_builder.generate_empty_board(config)
|
102
|
-
end
|
103
|
-
|
104
|
-
def change_game_state(available_choice, game)
|
105
|
-
game_state_changer.change_game_state(available_choice, game)
|
106
|
-
end
|
107
|
-
|
108
62
|
def winner
|
109
63
|
#each move is immediately proceeded by an increment to number_of_selections_made; therefore, need to rewind won to find winner
|
110
64
|
if !won?
|
@@ -117,22 +71,50 @@ module Shared
|
|
117
71
|
board.display_values
|
118
72
|
end
|
119
73
|
|
74
|
+
|
75
|
+
def computer_choosing_graphic
|
76
|
+
io_helpers.computer_choosing_graphic
|
77
|
+
end
|
78
|
+
|
120
79
|
private
|
121
80
|
|
81
|
+
#hook
|
82
|
+
def one_time_setup
|
83
|
+
end
|
84
|
+
|
85
|
+
#hook
|
86
|
+
def every_time_setup
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def second_player_expert_computer?
|
91
|
+
players[1].kind_of?(TTT::ComputerPlayerExpert)
|
92
|
+
end
|
93
|
+
|
94
|
+
#overriding so that io and io_helpers always in harmony
|
95
|
+
|
122
96
|
def over?
|
123
97
|
raise 'Called abstract method: over?'
|
124
98
|
end
|
125
99
|
|
126
|
-
def
|
127
|
-
raise 'Called abstract method:
|
100
|
+
def no_more_turns?
|
101
|
+
raise 'Called abstract method: no_more_turns?'
|
128
102
|
end
|
129
103
|
|
130
104
|
def won?
|
131
105
|
raise 'Called abstract method: won?'
|
132
106
|
end
|
133
107
|
|
134
|
-
def
|
135
|
-
|
108
|
+
def change_game_state(move)
|
109
|
+
raise 'Called abstract method: change_game_state'
|
110
|
+
end
|
111
|
+
|
112
|
+
def reset_game
|
113
|
+
raise 'Called abstract method: reset_game'
|
114
|
+
end
|
115
|
+
|
116
|
+
def reset_board
|
117
|
+
raise 'Called abstract method: reset_board'
|
136
118
|
end
|
137
119
|
|
138
120
|
def print_board
|
@@ -147,20 +129,24 @@ module Shared
|
|
147
129
|
(number_of_turns_taken % number_of_players)
|
148
130
|
end
|
149
131
|
|
132
|
+
def custom_final_message(game)
|
133
|
+
io_helpers.custom_final_message(game)
|
134
|
+
end
|
135
|
+
|
150
136
|
def initial_instructions
|
151
|
-
|
137
|
+
io_helpers.initial_instructions
|
152
138
|
end
|
153
139
|
|
154
140
|
def winning_prompt
|
155
|
-
|
141
|
+
io_helpers.winning_prompt(current_player_name)
|
156
142
|
end
|
157
143
|
|
158
|
-
def no_winner_prompt
|
159
|
-
|
144
|
+
def no_winner_prompt(game)
|
145
|
+
io_helpers.no_winner_prompt(game)
|
160
146
|
end
|
161
147
|
|
162
148
|
def new_game_starting_graphic
|
163
|
-
|
149
|
+
io_helpers.new_game_starting_graphic
|
164
150
|
end
|
165
151
|
end
|
166
152
|
end
|
@@ -1,46 +1,24 @@
|
|
1
|
+
require 'paint'
|
2
|
+
|
1
3
|
module Shared
|
2
|
-
class
|
4
|
+
class IOHelpers
|
3
5
|
attr_accessor :io
|
4
6
|
|
5
7
|
def initialize(io)
|
6
8
|
@io = io
|
7
9
|
end
|
8
10
|
|
9
|
-
def
|
10
|
-
|
11
|
-
input == 'm' || input == 'M' || input == 't' || input == 'T'
|
12
|
-
end
|
13
|
-
user_choice = user_choice.upcase
|
14
|
-
if user_choice == "M"
|
15
|
-
:mastermind
|
16
|
-
elsif user_choice == "T"
|
17
|
-
:tictactoe
|
18
|
-
end
|
11
|
+
def initial_instructions
|
12
|
+
raise 'Called abstract method: initial_instructions'
|
19
13
|
end
|
20
14
|
|
21
15
|
def get_player_1_name
|
22
|
-
user_choice = get_user_input("Player 1, please enter your name", "Please re-enter your name, using only letters") do |input|
|
16
|
+
user_choice = get_user_input("Player 1, please enter your name:", "Please re-enter your name, using only letters") do |input|
|
23
17
|
input =~ /^[a-zA-Z]+$/
|
24
18
|
end
|
25
19
|
user_choice.capitalize
|
26
20
|
end
|
27
21
|
|
28
|
-
def get_user_input(prompt, reprompt, &block_validation)
|
29
|
-
io.present_with_new_line(prompt)
|
30
|
-
user_choice = nil
|
31
|
-
while true
|
32
|
-
user_choice = io.receive
|
33
|
-
if user_choice.to_s.upcase == "EXIT"
|
34
|
-
#http://blog.honeybadger.io/how-to-exit-a-ruby-program/
|
35
|
-
exit(0)
|
36
|
-
end
|
37
|
-
#breaks out of input loop if input is valid (the block validation makes sure some rule is true)
|
38
|
-
break if block_validation.call(user_choice)
|
39
|
-
puts reprompt
|
40
|
-
end
|
41
|
-
user_choice
|
42
|
-
end
|
43
|
-
|
44
22
|
def computer_choosing_graphic
|
45
23
|
io.present("Computer choosing.")
|
46
24
|
3.times do
|
@@ -62,6 +40,40 @@ module Shared
|
|
62
40
|
io.present("\n")
|
63
41
|
end
|
64
42
|
|
43
|
+
def winning_prompt(current_player_name)
|
44
|
+
if current_player_name == "Computer"
|
45
|
+
io.present_with_new_line(Paint["#{current_player_name} wins!", :red, :bold])
|
46
|
+
else
|
47
|
+
io.present_with_new_line(Paint["#{current_player_name} wins!", :green, :bold])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def no_winner_prompt
|
52
|
+
raise 'Called abstract method: no_winner_prompt'
|
53
|
+
end
|
54
|
+
|
55
|
+
def custom_final_message(game)
|
56
|
+
#hook
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def get_user_input(prompt, reprompt, &block_validation)
|
62
|
+
io.present_with_new_line(prompt)
|
63
|
+
user_choice = nil
|
64
|
+
while true
|
65
|
+
user_choice = io.receive
|
66
|
+
if user_choice.to_s.upcase == "EXIT"
|
67
|
+
#http://blog.honeybadger.io/how-to-exit-a-ruby-program/
|
68
|
+
exit(0)
|
69
|
+
end
|
70
|
+
#breaks out of input loop if input is valid (the block validation makes sure some rule is true)
|
71
|
+
break if block_validation.call(user_choice)
|
72
|
+
puts reprompt
|
73
|
+
end
|
74
|
+
user_choice
|
75
|
+
end
|
76
|
+
|
65
77
|
def marching_dots
|
66
78
|
sleep(0.2)
|
67
79
|
io.present(".")
|
@@ -70,9 +82,5 @@ module Shared
|
|
70
82
|
sleep(0.1)
|
71
83
|
io.present(".")
|
72
84
|
end
|
73
|
-
|
74
|
-
def custom_final_message(game)
|
75
|
-
|
76
|
-
end
|
77
85
|
end
|
78
86
|
end
|
data/lib/games/shared/player.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
module Shared
|
2
2
|
class Player
|
3
|
-
attr_accessor :
|
3
|
+
attr_accessor :name
|
4
4
|
|
5
5
|
def initialize(args = {})
|
6
6
|
@name = args.fetch(:name, "Player 1")
|
7
|
-
@type = args.fetch(:type, :human)
|
8
|
-
@difficulty_level = args.fetch(:difficulty_level, nil)
|
9
7
|
post_initialize(args)
|
10
8
|
end
|
11
9
|
|
@@ -1,9 +1,8 @@
|
|
1
1
|
module TTT
|
2
2
|
class Board
|
3
|
-
attr_accessor :
|
3
|
+
attr_accessor :squares
|
4
4
|
|
5
5
|
def initialize(args = {})
|
6
|
-
@rows_and_cols = args[:rows_and_cols]
|
7
6
|
@squares = args[:squares]
|
8
7
|
end
|
9
8
|
|
@@ -28,8 +27,8 @@ module TTT
|
|
28
27
|
return squares.available_choices
|
29
28
|
end
|
30
29
|
|
31
|
-
def
|
32
|
-
|
30
|
+
def number_of_rows_cols
|
31
|
+
squares.number_of_rows_cols
|
33
32
|
end
|
34
33
|
|
35
34
|
private
|
@@ -1,10 +1,10 @@
|
|
1
|
+
require_relative 'board'
|
1
2
|
require_relative 'squares_factory'
|
2
3
|
|
3
4
|
module TTT
|
4
5
|
class BoardBuilder
|
5
|
-
def generate_empty_board(
|
6
|
-
|
7
|
-
Board.new(rows_and_cols: number_of_rows_cols, squares: SquaresFactory.build_empty_squares(number_of_rows_cols) )
|
6
|
+
def generate_empty_board(number_of_rows_cols)
|
7
|
+
Board.new(squares: SquaresFactory.build_empty_squares(number_of_rows_cols) )
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
@@ -13,7 +13,7 @@ module TTT
|
|
13
13
|
end
|
14
14
|
print "\n"
|
15
15
|
#row_number starts at 0
|
16
|
-
puts "_"*(row.size * 5) unless row_number.equal? (
|
16
|
+
puts "_"*(row.size * 5) unless row_number.equal? (number_of_rows_cols - 1)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -21,8 +21,8 @@ module TTT
|
|
21
21
|
board.display_values
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
25
|
-
board.
|
24
|
+
def number_of_rows_cols
|
25
|
+
board.number_of_rows_cols
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative '../tictactoe/player'
|
2
|
+
|
3
|
+
module TTT
|
4
|
+
class ComputerPlayerExpert < TTT::Player
|
5
|
+
def make_move(game)
|
6
|
+
game.computer_choosing_graphic
|
7
|
+
minimax = TTT::Minimax.new(game.board, game.number_of_turns_taken, game.player_1_value, game.player_2_value)
|
8
|
+
minimax.run_minimax
|
9
|
+
minimax.choice
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/games/tictactoe/game.rb
CHANGED
@@ -2,18 +2,37 @@ require_relative '../shared/game'
|
|
2
2
|
|
3
3
|
module TTT
|
4
4
|
class Game < Shared::Game
|
5
|
-
|
5
|
+
def one_time_setup
|
6
|
+
self.players = players_factory.generate_players
|
7
|
+
number_of_rows_cols = get_board_rows
|
8
|
+
self.board = board_builder.generate_empty_board(number_of_rows_cols)
|
9
|
+
end
|
6
10
|
|
7
|
-
def
|
11
|
+
def every_time_setup
|
8
12
|
self.won_flag = false
|
9
13
|
end
|
10
14
|
|
15
|
+
def get_board_rows
|
16
|
+
#need this if else logic because if computer is difficult, it runs minimax, which is too slow to allow for more than 3 rows/cols
|
17
|
+
if second_player_expert_computer?
|
18
|
+
io_helpers.get_number_of_rows_cols_max_3
|
19
|
+
else
|
20
|
+
io_helpers.get_number_of_rows_cols_max_9
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def change_game_state(move)
|
25
|
+
change_square(move, current_player_value)
|
26
|
+
if !won?
|
27
|
+
move_forward_one_turn
|
28
|
+
end
|
29
|
+
end
|
11
30
|
|
12
31
|
def over?
|
13
|
-
won_flag ||
|
32
|
+
won_flag || no_more_turns?
|
14
33
|
end
|
15
34
|
|
16
|
-
def
|
35
|
+
def no_more_turns?
|
17
36
|
board.full?
|
18
37
|
end
|
19
38
|
|
@@ -29,6 +48,24 @@ module TTT
|
|
29
48
|
end
|
30
49
|
end
|
31
50
|
|
51
|
+
def reset_game
|
52
|
+
reset_board
|
53
|
+
self.number_of_turns_taken = 0
|
54
|
+
self.won_flag = false
|
55
|
+
end
|
56
|
+
|
57
|
+
def reset_board
|
58
|
+
self.board = generate_empty_board(number_of_rows_cols)
|
59
|
+
end
|
60
|
+
|
61
|
+
def number_of_rows_cols
|
62
|
+
board.number_of_rows_cols
|
63
|
+
end
|
64
|
+
|
65
|
+
def generate_empty_board(number_of_rows_cols)
|
66
|
+
board_builder.generate_empty_board(number_of_rows_cols)
|
67
|
+
end
|
68
|
+
|
32
69
|
def available_choices
|
33
70
|
board.available_choices
|
34
71
|
end
|
@@ -45,16 +82,12 @@ module TTT
|
|
45
82
|
current_player.value
|
46
83
|
end
|
47
84
|
|
48
|
-
def current_player_difficult_computer?
|
49
|
-
current_player_computer? && current_player.difficulty_level == :difficult
|
50
|
-
end
|
51
|
-
|
52
|
-
def current_player_easy_computer?
|
53
|
-
current_player_computer? && current_player.difficulty_level == :easy
|
54
|
-
end
|
55
|
-
|
56
85
|
def change_square(display_value, current_player_value)
|
57
86
|
board.change_square(display_value, current_player_value)
|
58
87
|
end
|
88
|
+
|
89
|
+
def get_player_choice(current_player_name, available_choices)
|
90
|
+
io_helpers.get_player_choice(current_player_name, available_choices)
|
91
|
+
end
|
59
92
|
end
|
60
93
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require_relative '../shared/io_helpers'
|
2
|
+
require 'paint'
|
3
|
+
|
4
|
+
module TTT
|
5
|
+
class IOHelpers < Shared::IOHelpers
|
6
|
+
def initial_instructions
|
7
|
+
io.present_with_new_line(Paint["-" * 60 + "TIC TAC TOE" + "-" * 60, :blue, :bold, :bright, :underline])
|
8
|
+
io.present_with_new_line(Paint["INSTRUCTIONS: ", :green] + "Try to fill a row, a column, or a diagonal with only your token value.")
|
9
|
+
io.present_with_new_line("-" * 131)
|
10
|
+
io.present_with_new_line(Paint["Type ",:red] + Paint["\"Exit\" ", :red, :bold] + Paint["to quit the game.", :red])
|
11
|
+
io.present_with_new_line("_" * 131)
|
12
|
+
end
|
13
|
+
|
14
|
+
def no_winner_prompt(game)
|
15
|
+
io.present_with_new_line(Paint["Draw! Please try again.", :red, :bold])
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_number_of_rows_cols_max_3
|
19
|
+
get_user_input("Please choose how many squares you would like in each row.", "Please choose number between 2 and 3.") do |input|
|
20
|
+
input.to_i >=2 && input.to_i <=3
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_number_of_rows_cols_max_9
|
25
|
+
get_user_input("Please choose how many squares you would like in each row.", "Please choose number between 2 and 3.") do |input|
|
26
|
+
input.to_i >=2 && input.to_i <=9
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_player_2_name
|
31
|
+
user_choice = get_user_input("Player 2, please enter your name:", "Please re-enter your name, using only letters") do |input|
|
32
|
+
input =~ /^[a-zA-Z]+$/
|
33
|
+
end
|
34
|
+
user_choice.capitalize
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_player_value(player_name = "Player 1", taken_value = "")
|
38
|
+
user_choice = get_user_input("#{player_name}, please enter your preferred token value, consisting of one letter only. For example, " + Paint["\"X\" ", :blue, :bold] + "and " + Paint["\"O\" ", :blue, :bold] + " are the most common token values in Tic Tac Toe.", "Invalid entry. Must be one letter. Please re-enter.") do |input|
|
39
|
+
(input =~ /^[a-zA-Z]$/ && input.upcase != taken_value.upcase)
|
40
|
+
end
|
41
|
+
user_choice.upcase
|
42
|
+
end
|
43
|
+
|
44
|
+
# def get_player_2_name
|
45
|
+
# user_choice = get_user_input("Player 2, please enter your name", "Please re-enter your name, using only letters") do |input|
|
46
|
+
# input =~ /^[a-zA-Z]+$/
|
47
|
+
# end
|
48
|
+
# user_choice.capitalize
|
49
|
+
# end
|
50
|
+
|
51
|
+
def get_player_2_type
|
52
|
+
user_choice = get_user_input("Please enter " + Paint["\"C\" ", :blue, :bold] + "if you would like to play the Computer. Enter " + Paint["\"H\" ", :blue, :bold] + "if you would like to play the human sitting next to you:", "Invalid character. Please enter either C(Computer) or H(Human).") do |input|
|
53
|
+
input == 'c' || input == 'C' || input == 'h' || input == 'H'
|
54
|
+
end
|
55
|
+
user_choice = user_choice.upcase
|
56
|
+
if user_choice == "C"
|
57
|
+
:computer
|
58
|
+
elsif user_choice == "H"
|
59
|
+
:human
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_computer_knowledge_level
|
64
|
+
user_choice = get_user_input("Please enter " + Paint["\"E\" ", :blue, :bold] + "if you would like to play an easy Computer. Enter " + Paint["\"D\" ", :blue, :bold] +"if you would like to play an extremely difficult computer.", "Invalid character. Please enter either E (Easy) or D (Difficult).") do |input|
|
65
|
+
input == 'd' || input == 'D' || input == 'e' || input == 'E'
|
66
|
+
end
|
67
|
+
user_choice = user_choice.upcase
|
68
|
+
if user_choice == "D"
|
69
|
+
:expert
|
70
|
+
elsif user_choice == "E"
|
71
|
+
:novice
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_player_choice(current_player_name, available_choices)
|
76
|
+
get_user_input("#{current_player_name}, please enter the number of the square that you would like to change.", "Invalid entry. Please try again.") do |input|
|
77
|
+
available_choices.include?(input)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|