games_bfox 0.2.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/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.md +36 -0
- data/Rakefile +6 -0
- data/exe/mastermind +8 -0
- data/exe/setup +8 -0
- data/exe/tictactoe +8 -0
- data/games.gemspec +36 -0
- data/lib/games/mastermind/board.rb +43 -0
- data/lib/games/mastermind/board_builder.rb +9 -0
- data/lib/games/mastermind/board_presenter_terminal.rb +69 -0
- data/lib/games/mastermind/colors.rb +14 -0
- data/lib/games/mastermind/game.rb +64 -0
- data/lib/games/mastermind/game_config.rb +48 -0
- data/lib/games/mastermind/game_resetter.rb +19 -0
- data/lib/games/mastermind/game_state_changer.rb +41 -0
- data/lib/games/mastermind/guess_evaluator.rb +85 -0
- data/lib/games/mastermind/input_helper.rb +54 -0
- data/lib/games/mastermind/move_generator.rb +46 -0
- data/lib/games/mastermind/peg.rb +15 -0
- data/lib/games/mastermind/pegs.rb +50 -0
- data/lib/games/mastermind/pegs_factory.rb +26 -0
- data/lib/games/mastermind/players_factory.rb +15 -0
- data/lib/games/mastermind.rb +13 -0
- data/lib/games/shared/array_iterator.rb +28 -0
- data/lib/games/shared/game.rb +155 -0
- data/lib/games/shared/input_helper.rb +74 -0
- data/lib/games/shared/io_terminal.rb +25 -0
- data/lib/games/shared/player.rb +15 -0
- data/lib/games/shared/version.rb +3 -0
- data/lib/games/tictactoe/board.rb +40 -0
- data/lib/games/tictactoe/board_builder.rb +10 -0
- data/lib/games/tictactoe/board_presenter_terminal.rb +28 -0
- data/lib/games/tictactoe/game.rb +60 -0
- data/lib/games/tictactoe/game_config.rb +73 -0
- data/lib/games/tictactoe/game_resetter.rb +16 -0
- data/lib/games/tictactoe/game_state_changer.rb +17 -0
- data/lib/games/tictactoe/input_helper.rb +80 -0
- data/lib/games/tictactoe/minimax.rb +81 -0
- data/lib/games/tictactoe/move_generator.rb +68 -0
- data/lib/games/tictactoe/player.rb +11 -0
- data/lib/games/tictactoe/players_factory.rb +11 -0
- data/lib/games/tictactoe/square.rb +30 -0
- data/lib/games/tictactoe/squares.rb +129 -0
- data/lib/games/tictactoe/squares_factory.rb +56 -0
- data/lib/games/tictactoe.rb +13 -0
- data/lib/games/version.rb +3 -0
- data/lib/games.rb +5 -0
- metadata +173 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
module MM
|
2
|
+
class Pegs
|
3
|
+
attr_reader :collection_of_pegs
|
4
|
+
|
5
|
+
#collection_of_pegs is a multi-dimensional array
|
6
|
+
|
7
|
+
def initialize(args)
|
8
|
+
@collection_of_pegs = args[:collection_of_pegs]
|
9
|
+
end
|
10
|
+
|
11
|
+
def retrieve_peg(row, col)
|
12
|
+
if row >= number_of_rows || col >= number_of_cols
|
13
|
+
return nil
|
14
|
+
else
|
15
|
+
return collection_of_pegs[row][col]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def current_row(number_of_turns_taken)
|
20
|
+
collection_of_pegs[number_of_turns_taken]
|
21
|
+
end
|
22
|
+
|
23
|
+
def display_values
|
24
|
+
# reversed so that game appears to be filling itself in from top to bottom
|
25
|
+
collection_of_pegs.reverse.map do |row|
|
26
|
+
row.map do |peg|
|
27
|
+
peg.display_value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def result_values
|
33
|
+
collection_of_pegs.reverse.map do |row|
|
34
|
+
row.map do |peg|
|
35
|
+
peg.result_value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def number_of_rows
|
42
|
+
collection_of_pegs.length
|
43
|
+
end
|
44
|
+
|
45
|
+
def number_of_cols
|
46
|
+
collection_of_pegs[0].length
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'pegs'
|
2
|
+
require_relative 'peg'
|
3
|
+
|
4
|
+
module MM
|
5
|
+
module PegsFactory
|
6
|
+
def self.build_empty_pegs(rows = 12, cols = 4, pegs_class = Pegs)
|
7
|
+
pegs = Array.new(rows) do
|
8
|
+
Array.new(cols)
|
9
|
+
end
|
10
|
+
|
11
|
+
pegs.each_with_index do |element, row|
|
12
|
+
element.each_index do |col|
|
13
|
+
pegs[row][col] = create_empty_peg(row, col)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
pegs_class.new(collection_of_pegs: pegs)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.create_empty_peg(row, col, display_value = nil, peg_class = Peg)
|
21
|
+
peg_class.new(display_value: display_value,
|
22
|
+
row: row,
|
23
|
+
col: col )
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative '../shared/player'
|
2
|
+
|
3
|
+
module MM
|
4
|
+
class PlayersFactory
|
5
|
+
#returns an array in case we would like to extend the game to allow for multiple players
|
6
|
+
def generate_players(config)
|
7
|
+
if config.code_setter == :computer
|
8
|
+
player_1 = Shared::Player.new(name: config.player_1_name)
|
9
|
+
else
|
10
|
+
player_1 = Shared::Player.new(name: config.player_1_name, type: :computer)
|
11
|
+
end
|
12
|
+
[player_1]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Dir[File.join(File.expand_path(File.dirname(__FILE__)), 'shared', '*.rb')].each {|file| require file }
|
2
|
+
Dir[File.join(File.expand_path(File.dirname(__FILE__)), 'mastermind', '*.rb')].each {|file| require file }
|
3
|
+
|
4
|
+
class Mastermind
|
5
|
+
def self.run
|
6
|
+
io = Shared::IOTerminal.new
|
7
|
+
board_presenter = MM::BoardPresenterTerminal.new
|
8
|
+
|
9
|
+
game = MM::Game.new(game_module: MM, io: io, board_presenter: board_presenter)
|
10
|
+
# game.setup
|
11
|
+
game.play
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#from Design Patterns by Russ Olsen pg 128-129
|
2
|
+
module Shared
|
3
|
+
class ArrayIterator
|
4
|
+
def initialize(array)
|
5
|
+
@array = array
|
6
|
+
@index = 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def has_next?
|
10
|
+
@index < @array.length
|
11
|
+
end
|
12
|
+
|
13
|
+
def item
|
14
|
+
@array[@index]
|
15
|
+
end
|
16
|
+
|
17
|
+
def peek
|
18
|
+
@array[@index]
|
19
|
+
end
|
20
|
+
|
21
|
+
def next_item
|
22
|
+
value = @array[@index]
|
23
|
+
@index += 1
|
24
|
+
value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,155 @@
|
|
1
|
+
Dir[File.join(File.dirname(__FILE__), '*.rb')].each {|file| require file }
|
2
|
+
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
|
+
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
|
+
module Shared
|
6
|
+
class Game
|
7
|
+
attr_accessor :board, :board_presenter, :board_builder
|
8
|
+
attr_accessor :players, :players_factory
|
9
|
+
attr_accessor :config, :game_state_changer
|
10
|
+
attr_accessor :number_of_turns_taken
|
11
|
+
attr_accessor :game_resetter
|
12
|
+
attr_accessor :move_generator
|
13
|
+
attr_reader :io, :input_helper, :game_module
|
14
|
+
|
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
|
+
|
31
|
+
def one_time_setup
|
32
|
+
#setup gets necessary info from user and stores it in config object
|
33
|
+
config.one_time_setup
|
34
|
+
end
|
35
|
+
|
36
|
+
def every_time_setup
|
37
|
+
config.every_time_setup
|
38
|
+
self.players = players_factory.generate_players(config)
|
39
|
+
self.board = board_builder.generate_empty_board(config)
|
40
|
+
local_setup
|
41
|
+
end
|
42
|
+
|
43
|
+
#to be implemented by subclasses
|
44
|
+
def local_setup
|
45
|
+
end
|
46
|
+
|
47
|
+
#overriding so that io and input_helper always in harmony
|
48
|
+
def io=(new_io)
|
49
|
+
@io = new_io
|
50
|
+
self.input_helper = game_module::InputHelper.new(new_io)
|
51
|
+
end
|
52
|
+
|
53
|
+
def play
|
54
|
+
one_time_setup
|
55
|
+
while true
|
56
|
+
every_time_setup
|
57
|
+
while !over?
|
58
|
+
print_board
|
59
|
+
move = move_generator.get_player_choice(self)
|
60
|
+
game_state_changer.change_game_state(move, self)
|
61
|
+
end
|
62
|
+
|
63
|
+
#need to print_final_iteration of board
|
64
|
+
print_board
|
65
|
+
|
66
|
+
if won?
|
67
|
+
winning_prompt
|
68
|
+
elsif over_with_no_winner?
|
69
|
+
no_winner_prompt
|
70
|
+
end
|
71
|
+
|
72
|
+
game_resetter.reset_game(self)
|
73
|
+
new_game_starting_graphic
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def current_player
|
78
|
+
players[current_turn_player_index]
|
79
|
+
end
|
80
|
+
|
81
|
+
def current_player_name
|
82
|
+
current_player.name
|
83
|
+
end
|
84
|
+
|
85
|
+
def current_player_human?
|
86
|
+
current_player.type == :human
|
87
|
+
end
|
88
|
+
|
89
|
+
def current_player_computer?
|
90
|
+
current_player.type == :computer
|
91
|
+
end
|
92
|
+
|
93
|
+
def move_forward_one_turn
|
94
|
+
self.number_of_turns_taken += 1
|
95
|
+
end
|
96
|
+
|
97
|
+
def generate_empty_board(config)
|
98
|
+
board_builder.generate_empty_board(config)
|
99
|
+
end
|
100
|
+
|
101
|
+
def change_game_state(available_choice, game)
|
102
|
+
game_state_changer.change_game_state(available_choice, game)
|
103
|
+
end
|
104
|
+
|
105
|
+
def winner
|
106
|
+
#each move is immediately proceeded by an increment to number_of_selections_made; therefore, need to rewind won to find winner
|
107
|
+
if !won?
|
108
|
+
return nil
|
109
|
+
end
|
110
|
+
current_player
|
111
|
+
end
|
112
|
+
|
113
|
+
def display_values
|
114
|
+
board.display_values
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def over?
|
120
|
+
raise 'Called abstract method: over?'
|
121
|
+
end
|
122
|
+
|
123
|
+
def over_with_no_winner?
|
124
|
+
raise 'Called abstract method: draw?'
|
125
|
+
end
|
126
|
+
|
127
|
+
def won?
|
128
|
+
raise 'Called abstract method: won?'
|
129
|
+
end
|
130
|
+
|
131
|
+
def print_board
|
132
|
+
board_presenter.present_board(board)
|
133
|
+
end
|
134
|
+
|
135
|
+
def number_of_players
|
136
|
+
players.size
|
137
|
+
end
|
138
|
+
|
139
|
+
def current_turn_player_index
|
140
|
+
(number_of_turns_taken % number_of_players)
|
141
|
+
end
|
142
|
+
|
143
|
+
def winning_prompt
|
144
|
+
input_helper.winning_prompt(current_player.name)
|
145
|
+
end
|
146
|
+
|
147
|
+
def no_winner_prompt
|
148
|
+
input_helper.no_winner_prompt
|
149
|
+
end
|
150
|
+
|
151
|
+
def new_game_starting_graphic
|
152
|
+
input_helper.new_game_starting_graphic
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Shared
|
2
|
+
class InputHelper
|
3
|
+
attr_accessor :io
|
4
|
+
|
5
|
+
def initialize(io)
|
6
|
+
@io = io
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_game
|
10
|
+
user_choice = get_user_input("Please enter \"M\" if you would like to play Mastermind. Enter \"T\" if you would like to play Tic Tac Toe.", "Invalid character. Please enter either M (Mastermind) or T (Tic Tac Toe).") do |input|
|
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
|
19
|
+
end
|
20
|
+
|
21
|
+
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|
|
23
|
+
input =~ /^[a-zA-Z]+$/
|
24
|
+
end
|
25
|
+
user_choice.capitalize
|
26
|
+
end
|
27
|
+
|
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
|
+
def computer_choosing_graphic
|
45
|
+
io.present("Computer choosing.")
|
46
|
+
3.times do
|
47
|
+
sleep(0.3)
|
48
|
+
io.present(".")
|
49
|
+
end
|
50
|
+
io.present("\n")
|
51
|
+
end
|
52
|
+
|
53
|
+
def new_game_starting_graphic
|
54
|
+
io.present("New game starting in 3")
|
55
|
+
i = 2
|
56
|
+
2.times do
|
57
|
+
marching_dots
|
58
|
+
io.present("#{i.to_s}")
|
59
|
+
i = i - 1
|
60
|
+
end
|
61
|
+
marching_dots
|
62
|
+
io.present("\n")
|
63
|
+
end
|
64
|
+
|
65
|
+
def marching_dots
|
66
|
+
sleep(0.2)
|
67
|
+
io.present(".")
|
68
|
+
sleep(0.2)
|
69
|
+
io.present(".")
|
70
|
+
sleep(0.1)
|
71
|
+
io.present(".")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Shared
|
2
|
+
class IOTerminal
|
3
|
+
def present(prompt)
|
4
|
+
print prompt
|
5
|
+
end
|
6
|
+
|
7
|
+
def present_with_new_line(prompt)
|
8
|
+
puts prompt
|
9
|
+
end
|
10
|
+
|
11
|
+
def receive
|
12
|
+
result = gets.chomp
|
13
|
+
if is_int?(result)
|
14
|
+
return result.to_i
|
15
|
+
else
|
16
|
+
return result.chomp
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def is_int?(figure)
|
22
|
+
Integer(figure) rescue false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Shared
|
2
|
+
class Player
|
3
|
+
attr_accessor :value, :name, :type, :difficulty_level
|
4
|
+
|
5
|
+
def initialize(args = {})
|
6
|
+
@name = args.fetch(:name, "Player 1")
|
7
|
+
@type = args.fetch(:type, :human)
|
8
|
+
@difficulty_level = args.fetch(:difficulty_level, nil)
|
9
|
+
post_initialize(args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def post_initialize(args)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module TTT
|
2
|
+
class Board
|
3
|
+
attr_accessor :rows_and_cols, :squares
|
4
|
+
|
5
|
+
def initialize(args = {})
|
6
|
+
@rows_and_cols = args[:rows_and_cols]
|
7
|
+
@squares = args[:squares]
|
8
|
+
end
|
9
|
+
|
10
|
+
def change_square(display_value, new_value)
|
11
|
+
square_to_change = retrieve_square(display_value)
|
12
|
+
square_to_change.change_value(new_value)
|
13
|
+
end
|
14
|
+
|
15
|
+
def full?
|
16
|
+
return squares.full?
|
17
|
+
end
|
18
|
+
|
19
|
+
def won?
|
20
|
+
return squares.any_combination_won?
|
21
|
+
end
|
22
|
+
|
23
|
+
def display_values
|
24
|
+
return squares.display_values
|
25
|
+
end
|
26
|
+
|
27
|
+
def available_choices
|
28
|
+
return squares.available_choices
|
29
|
+
end
|
30
|
+
|
31
|
+
def number_of_rows
|
32
|
+
rows_and_cols
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def retrieve_square(display_value)
|
37
|
+
return squares.retrieve_square(display_value)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative 'squares_factory'
|
2
|
+
|
3
|
+
module TTT
|
4
|
+
class BoardBuilder
|
5
|
+
def generate_empty_board(config)
|
6
|
+
number_of_rows_cols = config.number_of_rows_cols
|
7
|
+
Board.new(rows_and_cols: number_of_rows_cols, squares: SquaresFactory.build_empty_squares(number_of_rows_cols) )
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module TTT
|
2
|
+
class BoardPresenterTerminal
|
3
|
+
attr_accessor :board
|
4
|
+
|
5
|
+
def present_board(board)
|
6
|
+
@board = board
|
7
|
+
#board.display_values will return multidimensional array
|
8
|
+
display_values.each_with_index do |row, row_number|
|
9
|
+
row.each_with_index do |display_value, index|
|
10
|
+
#http://www.evc-cit.info/cit020/beginning-programming/chp_04/file_printf.html
|
11
|
+
printf "%2s", display_value
|
12
|
+
print " | " unless index == (row.size - 1)
|
13
|
+
end
|
14
|
+
print "\n"
|
15
|
+
#row_number starts at 0
|
16
|
+
puts "_"*(row.size * 5) unless row_number.equal? (number_of_rows - 1)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def display_values
|
21
|
+
board.display_values
|
22
|
+
end
|
23
|
+
|
24
|
+
def number_of_rows
|
25
|
+
board.number_of_rows
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require_relative '../shared/game'
|
2
|
+
|
3
|
+
module TTT
|
4
|
+
class Game < Shared::Game
|
5
|
+
attr_accessor :won_flag
|
6
|
+
|
7
|
+
def local_setup
|
8
|
+
self.won_flag = false
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
def over?
|
13
|
+
won_flag || over_with_no_winner?
|
14
|
+
end
|
15
|
+
|
16
|
+
def over_with_no_winner?
|
17
|
+
board.full?
|
18
|
+
end
|
19
|
+
|
20
|
+
def won?
|
21
|
+
if won_flag
|
22
|
+
return true
|
23
|
+
end
|
24
|
+
|
25
|
+
if board.won?
|
26
|
+
self.won_flag = true
|
27
|
+
else
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def available_choices
|
33
|
+
board.available_choices
|
34
|
+
end
|
35
|
+
|
36
|
+
def player_1_value
|
37
|
+
players[0].value
|
38
|
+
end
|
39
|
+
|
40
|
+
def player_2_value
|
41
|
+
players[1].value
|
42
|
+
end
|
43
|
+
|
44
|
+
def current_player_value
|
45
|
+
current_player.value
|
46
|
+
end
|
47
|
+
|
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
|
+
def change_square(display_value, current_player_value)
|
57
|
+
board.change_square(display_value, current_player_value)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module TTT
|
2
|
+
class GameConfig
|
3
|
+
attr_accessor :input_helper
|
4
|
+
|
5
|
+
attr_accessor :player_1_name
|
6
|
+
attr_accessor :player_1_value
|
7
|
+
attr_accessor :player_2_type
|
8
|
+
attr_accessor :player_2_name
|
9
|
+
attr_accessor :player_2_value
|
10
|
+
attr_accessor :computer_difficulty_level
|
11
|
+
attr_accessor :number_of_rows_cols
|
12
|
+
|
13
|
+
def initialize(input_helper)
|
14
|
+
@input_helper = input_helper
|
15
|
+
end
|
16
|
+
|
17
|
+
def one_time_setup
|
18
|
+
set_player_1_values
|
19
|
+
set_player_2_values
|
20
|
+
set_board_rows_cols
|
21
|
+
end
|
22
|
+
|
23
|
+
def every_time_setup
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_player_1_values
|
28
|
+
self.player_1_name = input_helper.get_player_1_name
|
29
|
+
self.player_1_value = input_helper.get_player_1_value(player_1_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_player_2_values
|
33
|
+
self.player_2_type = input_helper.get_player_2_type
|
34
|
+
if player_2_human?
|
35
|
+
self.player_2_name = input_helper.get_player_2_name
|
36
|
+
self.player_2_value = input_helper.get_player_2_value(player_1_value)
|
37
|
+
elsif player_2_computer?
|
38
|
+
self.player_2_name = "Computer"
|
39
|
+
self.player_2_value = get_computer_value
|
40
|
+
self.computer_difficulty_level = input_helper.get_computer_difficulty_level
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_board_rows_cols
|
45
|
+
#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
|
46
|
+
if computer_difficult?
|
47
|
+
self.number_of_rows_cols = input_helper.get_number_of_rows_cols_max_3
|
48
|
+
else
|
49
|
+
self.number_of_rows_cols = input_helper.get_number_of_rows_cols_max_9
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def player_2_human?
|
54
|
+
player_2_type == :human
|
55
|
+
end
|
56
|
+
|
57
|
+
def player_2_computer?
|
58
|
+
player_2_type == :computer
|
59
|
+
end
|
60
|
+
|
61
|
+
def computer_difficult?
|
62
|
+
computer_difficulty_level == :difficult
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_computer_value
|
66
|
+
if player_1_value != "O"
|
67
|
+
"O"
|
68
|
+
else
|
69
|
+
"X"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module TTT
|
2
|
+
class GameResetter
|
3
|
+
attr_accessor :game
|
4
|
+
|
5
|
+
def reset_game(game)
|
6
|
+
@game = game
|
7
|
+
reset_board
|
8
|
+
game.number_of_turns_taken = 0
|
9
|
+
game.won_flag = false
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset_board
|
13
|
+
game.board = game.generate_empty_board(game.config)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module TTT
|
2
|
+
class GameStateChanger
|
3
|
+
attr_accessor :game
|
4
|
+
|
5
|
+
def change_game_state(player_choice, game)
|
6
|
+
@game = game
|
7
|
+
change_square(player_choice)
|
8
|
+
end
|
9
|
+
|
10
|
+
def change_square(display_value)
|
11
|
+
game.change_square(display_value, game.current_player_value)
|
12
|
+
if !game.won?
|
13
|
+
game.move_forward_one_turn
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|