tic_tac_toe_ecastillo 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +9 -0
- data/bin/tic_tac_toe +5 -0
- data/lib/tic_tac_toe.rb +9 -0
- data/lib/tic_tac_toe/board.rb +42 -0
- data/lib/tic_tac_toe/cell.rb +25 -0
- data/lib/tic_tac_toe/checker.rb +66 -0
- data/lib/tic_tac_toe/console.rb +38 -0
- data/lib/tic_tac_toe/display.rb +88 -0
- data/lib/tic_tac_toe/gameplay.rb +78 -0
- data/lib/tic_tac_toe/input.rb +104 -0
- data/lib/tic_tac_toe/player.rb +15 -0
- data/lib/tic_tac_toe/start.rb +43 -0
- data/lib/tic_tac_toe_ecastillo/version.rb +3 -0
- data/res/messages.yaml +33 -0
- data/res/messages.yaml~ +10 -0
- data/spec/boards.rb +84 -0
- data/spec/constants.rb +43 -0
- metadata +65 -0
data/README.md
ADDED
data/bin/tic_tac_toe
ADDED
data/lib/tic_tac_toe.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require_relative 'tic_tac_toe/cell'
|
2
|
+
require_relative 'tic_tac_toe/board'
|
3
|
+
require_relative 'tic_tac_toe/display'
|
4
|
+
require_relative 'tic_tac_toe/start'
|
5
|
+
require_relative 'tic_tac_toe/checker'
|
6
|
+
require_relative 'tic_tac_toe/gameplay'
|
7
|
+
require_relative 'tic_tac_toe/player'
|
8
|
+
require_relative 'tic_tac_toe/input'
|
9
|
+
require_relative 'tic_tac_toe/console'
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module TicTacToe
|
2
|
+
class Board
|
3
|
+
|
4
|
+
attr_reader :board
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@board = empty_board
|
8
|
+
super()
|
9
|
+
end
|
10
|
+
|
11
|
+
def fill_board_space(position, player)
|
12
|
+
cell = cell_from_position(position)
|
13
|
+
cell.owner = player
|
14
|
+
end
|
15
|
+
|
16
|
+
def position_empty?(position)
|
17
|
+
cell = cell_from_position(position)
|
18
|
+
cell.empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_empty_positions
|
22
|
+
@board.each.reduce([]) { |positions, row| positions + row.select(&:empty?) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.valid_position_string?(selection)
|
26
|
+
selection.downcase.gsub(" ","").match(/^[abc],[123]$/)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def cell_from_position(position)
|
31
|
+
@board.flatten.find { |cell| cell.position == position.downcase }
|
32
|
+
end
|
33
|
+
|
34
|
+
def empty_board
|
35
|
+
[1,2,3].each.reduce([]) do |board, number|
|
36
|
+
board << ['a','b','c'].each.reduce([]) do |row, letter|
|
37
|
+
row << Cell.new("#{letter},#{number}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module TicTacToe
|
2
|
+
class Cell
|
3
|
+
|
4
|
+
EMPTY_SYMBOL = ' '
|
5
|
+
|
6
|
+
attr_accessor :owner, :position
|
7
|
+
|
8
|
+
def initialize(position, owner = nil)
|
9
|
+
@position = position
|
10
|
+
@owner = owner
|
11
|
+
end
|
12
|
+
|
13
|
+
def owner?(owner)
|
14
|
+
owner == @owner
|
15
|
+
end
|
16
|
+
|
17
|
+
def empty?
|
18
|
+
@owner.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def content
|
22
|
+
empty? ? EMPTY_SYMBOL : @owner.symbol
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module TicTacToe
|
2
|
+
class Checker
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@win = false
|
6
|
+
@draw = false
|
7
|
+
end
|
8
|
+
|
9
|
+
def update(args)
|
10
|
+
gameplay = args[:gameplay]
|
11
|
+
@board = gameplay.board.board
|
12
|
+
@win = win?(args[:player])
|
13
|
+
@draw = draw? unless @win
|
14
|
+
gameplay.finish_game if (@win || @draw)
|
15
|
+
gameplay.finished_turn_status(win: @win, draw: @draw)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def draw?
|
20
|
+
@board.all? {|row| row.all? { |element| !element.empty? }}
|
21
|
+
end
|
22
|
+
|
23
|
+
def win? (player)
|
24
|
+
vertical_win?(player) || horizontal_win?(player) || diagonal_win?(player)
|
25
|
+
end
|
26
|
+
|
27
|
+
def vertical_win?(player)
|
28
|
+
3.times.any? { |count| win_vertical_line?(player, count) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def win_vertical_line?(player, col)
|
32
|
+
rows = [0, 1, 2]
|
33
|
+
rows.all? do |row_index|
|
34
|
+
@board[row_index][col].owner?(player)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def horizontal_win?(player)
|
39
|
+
3.times.any? { |count| win_horizontal_line?(player,count)}
|
40
|
+
end
|
41
|
+
|
42
|
+
def win_horizontal_line?(player, row)
|
43
|
+
cols = [0, 1, 2]
|
44
|
+
cols.all? do |col_index|
|
45
|
+
@board[row][col_index].owner?(player)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def diagonal_win?(player)
|
50
|
+
left_to_right_diagonal_win?(player) || right_to_left_diagonal_win?(player)
|
51
|
+
end
|
52
|
+
|
53
|
+
def left_to_right_diagonal_win?(player)
|
54
|
+
@board[0][0].owner?(player) &&
|
55
|
+
@board[1][1].owner?(player) &&
|
56
|
+
@board[2][2].owner?(player)
|
57
|
+
end
|
58
|
+
|
59
|
+
def right_to_left_diagonal_win?(player)
|
60
|
+
@board[0][2].owner?(player) &&
|
61
|
+
@board[1][1].owner?(player) &&
|
62
|
+
@board[2][0].owner?(player)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module TicTacToe
|
4
|
+
class Console
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def clear_console
|
8
|
+
STDOUT.puts `clear`
|
9
|
+
end
|
10
|
+
|
11
|
+
def respond_to?(method, include_private = false)
|
12
|
+
super || respond_to_console?(method)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def method_missing(name, *args)
|
17
|
+
method = name.to_s
|
18
|
+
return Display.instance.send(name, *args) if display_action?(method)
|
19
|
+
return Input.instance.send(name, *args) if input_action?(method)
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def respond_to_console?(method)
|
24
|
+
name = method.to_s
|
25
|
+
return Display.instance.respond_to?(method) if display_action?(name)
|
26
|
+
return Input.instance.respond_to?(method) if input_action?(name)
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
def input_action?(name)
|
31
|
+
name =~ /^input_/
|
32
|
+
end
|
33
|
+
|
34
|
+
def display_action?(name)
|
35
|
+
name =~ /^display_/
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
module TicTacToe
|
5
|
+
class Display
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
MESSAGES_FILE = File.join(File.dirname(__FILE__), '../../res/messages.yaml')
|
9
|
+
|
10
|
+
attr_accessor :output
|
11
|
+
|
12
|
+
def display_board(args)
|
13
|
+
board = args[:board]
|
14
|
+
Console.instance.clear_console
|
15
|
+
STDOUT.puts "\t A B C"
|
16
|
+
STDOUT.puts board.board.map.with_index{ |row, index| row_message(row, index) }.join
|
17
|
+
end
|
18
|
+
|
19
|
+
def display(msg_name, *args)
|
20
|
+
STDOUT.puts YAML.load_file(MESSAGES_FILE)[msg_name]
|
21
|
+
STDIN.gets if instructions?(msg_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def display_turn_status(args)
|
25
|
+
player_name = args[:player_name]
|
26
|
+
display_board(args)
|
27
|
+
STDOUT.puts "\n\n #{player_name} turn"
|
28
|
+
end
|
29
|
+
|
30
|
+
def display_msg_ask_for_player_name(args)
|
31
|
+
player_number = args[:player_number]
|
32
|
+
STDOUT.puts "Enter player #{player_number + 1} name"
|
33
|
+
end
|
34
|
+
|
35
|
+
def display_msg_win(args)
|
36
|
+
player_name = args[:player_name]
|
37
|
+
STDOUT.puts "#{player_name} won"
|
38
|
+
end
|
39
|
+
|
40
|
+
def display_msg_computer_thinking
|
41
|
+
STDOUT.print "Thinking."
|
42
|
+
2.times do
|
43
|
+
Kernel.sleep(1)
|
44
|
+
STDOUT.print "."
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def respond_to?(method, include_private = false)
|
49
|
+
super || respond_to_display?(method)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def instructions?(msg_name)
|
54
|
+
msg_name.end_with?('_instructions')
|
55
|
+
end
|
56
|
+
|
57
|
+
def respond_to_display?(method)
|
58
|
+
name = method.to_s
|
59
|
+
return false unless name =~ /^display_/
|
60
|
+
name.gsub!(/^display_/,'')
|
61
|
+
msg_in_yml_file?(name)
|
62
|
+
end
|
63
|
+
|
64
|
+
def msg_in_yml_file?(msg)
|
65
|
+
YAML.load_file(MESSAGES_FILE).has_key?(msg)
|
66
|
+
end
|
67
|
+
|
68
|
+
def row_message(row, row_index)
|
69
|
+
message = "\t#{row_index + 1}"
|
70
|
+
row.each_with_index do |cell, index|
|
71
|
+
message << " #{cell.content} "
|
72
|
+
separator = (index == row.size - 1) ? "\n" : "|"
|
73
|
+
message << separator
|
74
|
+
end
|
75
|
+
message << "\t -----------------\n" unless row_index == 2
|
76
|
+
message
|
77
|
+
end
|
78
|
+
|
79
|
+
def method_missing(name, *args)
|
80
|
+
name = name.to_s
|
81
|
+
super unless name =~ /^display_/
|
82
|
+
name.gsub!(/^display_/,'')
|
83
|
+
display(name, *args)
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'observer'
|
2
|
+
|
3
|
+
module TicTacToe
|
4
|
+
class Gameplay
|
5
|
+
include Observable
|
6
|
+
|
7
|
+
attr_reader :board
|
8
|
+
|
9
|
+
def initialize(checker, ui, players_name)
|
10
|
+
create_players(players_name)
|
11
|
+
@ui = ui
|
12
|
+
prepare_initial_conditions
|
13
|
+
add_observer(checker)
|
14
|
+
end
|
15
|
+
|
16
|
+
def play
|
17
|
+
player_turn while !@game_finished
|
18
|
+
end
|
19
|
+
|
20
|
+
def finish_game
|
21
|
+
@game_finished = true
|
22
|
+
end
|
23
|
+
|
24
|
+
def finished_turn_status(args = { win: false, draw: false })
|
25
|
+
@ui.display_board(board: @board)
|
26
|
+
@ui.display_msg_draw if args[:draw]
|
27
|
+
@ui.display_msg_win(player_name: @players[@turn].name) if args[:win]
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def create_players(players_name)
|
32
|
+
@players = players_name.map { |name| Player.new(name) }
|
33
|
+
@players << Player.new('Computer', computer: true) if @players.size == 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def prepare_initial_conditions
|
37
|
+
@game_finished = false
|
38
|
+
@board = Board.new
|
39
|
+
@turn = Kernel.rand(2)
|
40
|
+
set_players_symbols
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_players_symbols
|
44
|
+
@players[@turn].symbol = "X"
|
45
|
+
@players[(@turn + 1) % 2].symbol = "O"
|
46
|
+
end
|
47
|
+
|
48
|
+
def player_turn
|
49
|
+
@ui.display_turn_status(board: @board, player_name: @players[@turn].name)
|
50
|
+
input = @ui.input_player_action(@players[@turn], @board)
|
51
|
+
input_action(input)
|
52
|
+
end
|
53
|
+
|
54
|
+
def input_action(option)
|
55
|
+
case option
|
56
|
+
when 'help' then @ui.display_gameplay_instructions
|
57
|
+
when 'quit' then finish_game
|
58
|
+
when 'reset' then reset
|
59
|
+
else completed_player_move(option)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def reset
|
64
|
+
prepare_initial_conditions
|
65
|
+
end
|
66
|
+
|
67
|
+
def completed_player_move(input)
|
68
|
+
@board.fill_board_space(input, @players[@turn])
|
69
|
+
changed
|
70
|
+
notify_observers(gameplay: self, player: @players[@turn])
|
71
|
+
change_turn unless @game_finished
|
72
|
+
end
|
73
|
+
|
74
|
+
def change_turn
|
75
|
+
@turn = (@turn + 1) % 2
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module TicTacToe
|
4
|
+
class Input
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
ONE_PLAYER_MODE = 1
|
8
|
+
TWO_PLAYER_MODE = 2
|
9
|
+
VALID_INPUT = 0
|
10
|
+
NOT_VALID_INPUT = 1
|
11
|
+
NOT_EMPTY_INPUT_POSITION = 2
|
12
|
+
|
13
|
+
def input_mode
|
14
|
+
display.display_modes_options
|
15
|
+
enter_mode
|
16
|
+
end
|
17
|
+
|
18
|
+
def input_name(args)
|
19
|
+
display.display_msg_ask_for_player_name(args)
|
20
|
+
input_line
|
21
|
+
end
|
22
|
+
|
23
|
+
def input_replay
|
24
|
+
display.display_msg_replay
|
25
|
+
input_line.downcase
|
26
|
+
end
|
27
|
+
|
28
|
+
def input_player_action(player, board)
|
29
|
+
begin
|
30
|
+
input = select_position(player, board.get_empty_positions)
|
31
|
+
validated_input = input_validation(input, board)
|
32
|
+
input_error_message(validated_input)
|
33
|
+
end while !valid?(validated_input)
|
34
|
+
input.downcase
|
35
|
+
end
|
36
|
+
|
37
|
+
def input_line
|
38
|
+
STDIN.gets.chomp
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def display
|
43
|
+
Display.instance
|
44
|
+
end
|
45
|
+
|
46
|
+
def select_position(player, posible_positions)
|
47
|
+
if player.computer?
|
48
|
+
select_random_position(posible_positions)
|
49
|
+
else
|
50
|
+
receive_player_input
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def input_validation(input, board)
|
55
|
+
return VALID_INPUT if quit_reset_option?(input)
|
56
|
+
if(Board.valid_position_string?(input))
|
57
|
+
board.position_empty?(input) ? VALID_INPUT : NOT_EMPTY_INPUT_POSITION
|
58
|
+
else
|
59
|
+
NOT_VALID_INPUT
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def select_random_position(posible_positions)
|
64
|
+
index = Kernel.rand(posible_positions.size)
|
65
|
+
display.display_msg_computer_thinking
|
66
|
+
posible_positions[index].position
|
67
|
+
end
|
68
|
+
|
69
|
+
def receive_player_input
|
70
|
+
display.display_msg_select_position
|
71
|
+
input_line
|
72
|
+
end
|
73
|
+
|
74
|
+
def valid?(validated_input)
|
75
|
+
validated_input == VALID_INPUT
|
76
|
+
end
|
77
|
+
|
78
|
+
def input_error_message(validated_input)
|
79
|
+
case validated_input
|
80
|
+
when NOT_VALID_INPUT
|
81
|
+
display.display_msg_not_valid_input
|
82
|
+
when NOT_EMPTY_INPUT_POSITION
|
83
|
+
display.display_msg_not_empty_position
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def quit_reset_option?(option)
|
88
|
+
['help','quit','reset'].include?(option)
|
89
|
+
end
|
90
|
+
|
91
|
+
def enter_mode
|
92
|
+
mode = input_line
|
93
|
+
while !valid_mode?(mode.to_i)
|
94
|
+
display.display_error_msg_mode
|
95
|
+
mode = input_line
|
96
|
+
end
|
97
|
+
mode.to_i
|
98
|
+
end
|
99
|
+
|
100
|
+
def valid_mode?(mode)
|
101
|
+
[ONE_PLAYER_MODE, TWO_PLAYER_MODE].include?(mode)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module TicTacToe
|
2
|
+
class Start
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@players_name_number = 1
|
6
|
+
@players_name = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def start
|
10
|
+
console.display_beginning_instructions
|
11
|
+
@players_name_number = console.input_mode
|
12
|
+
enter_players_name
|
13
|
+
play_until_no_more_replay
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def console
|
18
|
+
Console.instance
|
19
|
+
end
|
20
|
+
|
21
|
+
def play_until_no_more_replay
|
22
|
+
replay = true
|
23
|
+
while replay
|
24
|
+
start_game
|
25
|
+
replay = replay?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def replay?
|
30
|
+
console.input_replay.eql?('y')
|
31
|
+
end
|
32
|
+
|
33
|
+
def enter_players_name
|
34
|
+
@players_name_number.times { |count| @players_name[count] = console.input_name(player_number: count) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def start_game
|
38
|
+
console.clear_console
|
39
|
+
Gameplay.new(Checker.new, console, @players_name).play
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
data/res/messages.yaml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
msg_not_valid_input : "Not a valid selection, select another one"
|
2
|
+
msg_not_empty_position : "Not an empty position select another one"
|
3
|
+
msg_replay : "Do you want to play again [Y/N]"
|
4
|
+
modes_options : "Select a mode:
|
5
|
+
\n\t1) 1 player
|
6
|
+
\n\t2) 2 players"
|
7
|
+
error_msg_mode : "Enter a valid mode"
|
8
|
+
msg_select_position : "Select the position"
|
9
|
+
msg_draw : "Game drawn"
|
10
|
+
beginning_instructions : "\n\n\t\t Welcome to Tic Tac Toe
|
11
|
+
|
12
|
+
The extremely fun experience of playing such an amazing game as Tic Tac Toe. This game is really popular
|
13
|
+
and we do not want to delay you more but here are some instructions for using this game.
|
14
|
+
First you will be asked to select a mode here you could have:
|
15
|
+
\n\t1 player: Play against the hardest computer you will ever play
|
16
|
+
\n\t2 player: Play with another friend
|
17
|
+
|
18
|
+
\n\n Then, the player/players names are asked, feel free to be honest.
|
19
|
+
After that the game will start here you have to select a position to make your move, the format
|
20
|
+
of this input should be A,1 as an example, with letters going from A to C and numbers from 1 to 3. Also, you
|
21
|
+
have three another options quit, reset and help.'Quit' just quit the games, 'reset' restarts the game and
|
22
|
+
'help' shows you another game help.
|
23
|
+
|
24
|
+
\n\nEnjoy your game (hit enter to continue)"
|
25
|
+
gameplay_instructions : "
|
26
|
+
Select a position to make your move, the format
|
27
|
+
of this input should be A,1 as an example, with letters going from A to C and numbers from 1 to 3. Also, you
|
28
|
+
have three another options quit, reset and help.'Quit' just quit the games, 'reset' restarts the game and
|
29
|
+
'help' shows you another game help.
|
30
|
+
|
31
|
+
\n\n (hit enter to continue)"
|
32
|
+
|
33
|
+
|
data/res/messages.yaml~
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
msg_not_valid_input : "Not a valid selection, select another one"
|
2
|
+
msg_not_empty_position : "Not an empty position select another one"
|
3
|
+
msg_replay : "Do you want to play again [Y/N]"
|
4
|
+
modes_options : "Select a mode:
|
5
|
+
1) 1 player
|
6
|
+
2) 2 players"
|
7
|
+
error_msg_mode : "Enter a valid mode"
|
8
|
+
msg_select_position : "Select the position"
|
9
|
+
msg_draw : "Game drawn"
|
10
|
+
|
data/spec/boards.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'tic_tac_toe'
|
2
|
+
require 'constants'
|
3
|
+
|
4
|
+
module Boards
|
5
|
+
|
6
|
+
def Boards.draw_board
|
7
|
+
board = TicTacToe::Board.new
|
8
|
+
Boards.fill_positions(board, PLAYER_1_DRAW_POSITIONS, player_1)
|
9
|
+
Boards.fill_positions(board, PLAYER_2_DRAW_POSITIONS, player_2)
|
10
|
+
board
|
11
|
+
end
|
12
|
+
|
13
|
+
def Boards.first_vertical_win_board
|
14
|
+
board = TicTacToe::Board.new
|
15
|
+
Boards.fill_positions(board, FIRST_COL_WIN_POSITIONS, player_1)
|
16
|
+
board
|
17
|
+
end
|
18
|
+
|
19
|
+
def Boards.second_vertical_win_board
|
20
|
+
board = TicTacToe::Board.new
|
21
|
+
Boards.fill_positions(board, SECOND_COL_WIN_POSITIONS, player_1)
|
22
|
+
board
|
23
|
+
end
|
24
|
+
|
25
|
+
def Boards.third_vertical_win_board
|
26
|
+
board = TicTacToe::Board.new
|
27
|
+
Boards.fill_positions(board, THIRD_COL_WIN_POSITIONS, player_1)
|
28
|
+
board
|
29
|
+
end
|
30
|
+
|
31
|
+
def Boards.first_horizontal_win_board
|
32
|
+
board = TicTacToe::Board.new
|
33
|
+
Boards.fill_positions(board, FIRST_ROW_WIN_POSITIONS, player_1)
|
34
|
+
board
|
35
|
+
end
|
36
|
+
|
37
|
+
def Boards.second_horizontal_win_board
|
38
|
+
board = TicTacToe::Board.new
|
39
|
+
Boards.fill_positions(board, SECOND_ROW_WIN_POSITIONS, player_1)
|
40
|
+
board
|
41
|
+
end
|
42
|
+
|
43
|
+
def Boards.third_horizontal_win_board
|
44
|
+
board = TicTacToe::Board.new
|
45
|
+
Boards.fill_positions(board, THIRD_ROW_WIN_POSITIONS, player_1)
|
46
|
+
board
|
47
|
+
end
|
48
|
+
|
49
|
+
def Boards.up_diagonal_win_board
|
50
|
+
board = TicTacToe::Board.new
|
51
|
+
Boards.fill_positions(board, DIAGONAL_UP_WIN_POSITIONS, player_1)
|
52
|
+
board
|
53
|
+
end
|
54
|
+
|
55
|
+
def Boards.down_diagonal_win_board
|
56
|
+
board = TicTacToe::Board.new
|
57
|
+
Boards.fill_positions(board, DIAGONAL_DOWN_WIN_POSITIONS, player_1)
|
58
|
+
board
|
59
|
+
end
|
60
|
+
|
61
|
+
def Boards.no_win_nor_draw_board
|
62
|
+
board = TicTacToe::Board.new
|
63
|
+
Boards.fill_positions(board, SOME_POSITIONS, player_1)
|
64
|
+
board
|
65
|
+
end
|
66
|
+
|
67
|
+
def Boards.player_1
|
68
|
+
@@player_1 ||= Boards.player(PLAYER_1, PLAYER_1_SYMBOL)
|
69
|
+
end
|
70
|
+
|
71
|
+
def Boards.player_2
|
72
|
+
@@player_2 ||= Boards.player(PLAYER_2, PLAYER_2_SYMBOL)
|
73
|
+
end
|
74
|
+
|
75
|
+
def Boards.fill_positions(board, positions, player)
|
76
|
+
positions.each { |position| board.fill_board_space(position, player) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def Boards.player(name, symbol)
|
80
|
+
player = TicTacToe::Player.new(name)
|
81
|
+
player.symbol = symbol
|
82
|
+
player
|
83
|
+
end
|
84
|
+
end
|
data/spec/constants.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
A_POSITION = 1
|
2
|
+
A_VALID_MODE = 1
|
3
|
+
AN_INVALID_MODE = 3
|
4
|
+
AN_OWNER = 1
|
5
|
+
NOT_AN_OWNER = 2
|
6
|
+
A_SYMBOL = 3
|
7
|
+
EMPTY_SYMBOL = ' '
|
8
|
+
A_ROW_NUMBER = 1
|
9
|
+
A_COL_NUMBER = 2
|
10
|
+
A_POSITION_STRING = 'b,2'
|
11
|
+
POSITION_STRING_COL = 1
|
12
|
+
POSITION_STRING_ROW = 1
|
13
|
+
NOT_A_POSITION_STRING = 'Z,4'
|
14
|
+
A_PLAYER = 'PLAYER'
|
15
|
+
A_PLAYER_NAME = 'PLAYER'
|
16
|
+
A_COMPUTER_NAME = 'COMPUTER'
|
17
|
+
A_PLAYER_NUMBER = 1
|
18
|
+
AN_OUTPUT = 1
|
19
|
+
AN_INPUT = "INPUT"
|
20
|
+
CELL_CONTENT = 1
|
21
|
+
BOARD_MESSAGE = "\t1 #{CELL_CONTENT} | #{CELL_CONTENT} \n" +
|
22
|
+
"\t -----------------\n" +
|
23
|
+
"\t2 #{CELL_CONTENT} | #{CELL_CONTENT} \n" +
|
24
|
+
"\t -----------------\n" +
|
25
|
+
"\t3 #{CELL_CONTENT} | #{CELL_CONTENT} \n"
|
26
|
+
ALL_POSITIONS = ['A,1', 'B,1', 'C,1', 'A,2', 'B,2', 'C,2', 'A,3', 'B,3', 'C,3']
|
27
|
+
SOME_POSITIONS = ['B,1', 'A,3', 'C,2']
|
28
|
+
ALL_EXCEPT_SOME_POSITIONS = ['A,1', 'C,1', 'A,2', 'B,2', 'B,3', 'C,3']
|
29
|
+
PLAYER_1 = '1'
|
30
|
+
PLAYER_1_SYMBOL = 'X'
|
31
|
+
PLAYER_2 = '2'
|
32
|
+
PLAYER_2_SYMBOL = 'O'
|
33
|
+
PLAYER_1_DRAW_POSITIONS = ['A,1', 'A,3', 'B,2', 'C,2']
|
34
|
+
PLAYER_2_DRAW_POSITIONS = ['A,2', 'B,1', 'B,3', 'C,1', 'C,3']
|
35
|
+
FIRST_ROW_WIN_POSITIONS = ['A,1', 'B,1', 'C,1']
|
36
|
+
SECOND_ROW_WIN_POSITIONS = ['A,2', 'B,2', 'C,2']
|
37
|
+
THIRD_ROW_WIN_POSITIONS = ['A,3', 'B,3', 'C,3']
|
38
|
+
FIRST_COL_WIN_POSITIONS = ['A,1', 'A,2', 'A,3']
|
39
|
+
SECOND_COL_WIN_POSITIONS = ['B,1', 'B,2', 'B,3']
|
40
|
+
THIRD_COL_WIN_POSITIONS = ['C,1', 'C,2', 'C,3']
|
41
|
+
DIAGONAL_UP_WIN_POSITIONS = ['A,1', 'B,2', 'C,3']
|
42
|
+
DIAGONAL_DOWN_WIN_POSITIONS = ['A,3', 'B,2', 'C,1']
|
43
|
+
INVALID_INPUT_POSITION = 'asdasd'
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tic_tac_toe_ecastillo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Erick Castillo
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-01-31 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Play a simple TicTacToe game
|
15
|
+
email: ecastillo@pernix-solutions.com
|
16
|
+
executables:
|
17
|
+
- tic_tac_toe
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- bin/tic_tac_toe
|
22
|
+
- lib/tic_tac_toe/start.rb
|
23
|
+
- lib/tic_tac_toe/display.rb
|
24
|
+
- lib/tic_tac_toe/checker.rb
|
25
|
+
- lib/tic_tac_toe/gameplay.rb
|
26
|
+
- lib/tic_tac_toe/cell.rb
|
27
|
+
- lib/tic_tac_toe/input.rb
|
28
|
+
- lib/tic_tac_toe/console.rb
|
29
|
+
- lib/tic_tac_toe/player.rb
|
30
|
+
- lib/tic_tac_toe/board.rb
|
31
|
+
- lib/tic_tac_toe_ecastillo/version.rb
|
32
|
+
- lib/tic_tac_toe.rb
|
33
|
+
- res/messages.yaml~
|
34
|
+
- res/messages.yaml
|
35
|
+
- README.md
|
36
|
+
- spec/constants.rb
|
37
|
+
- spec/boards.rb
|
38
|
+
homepage: http://github.com/erickcsh/TicTacToe
|
39
|
+
licenses:
|
40
|
+
- MIT
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
requirements: []
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.8.23
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: TicTacToe!
|
63
|
+
test_files:
|
64
|
+
- spec/constants.rb
|
65
|
+
- spec/boards.rb
|