games_bfox 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|