tic_tac_toe_ecastillo 1.0.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.
- 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
|