tic_tac_toe_wilbertcr 0.0.1
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/bin/tic_tac_toe +10 -0
- data/lib/tic_tac_toe.rb +8 -0
- data/lib/tic_tac_toe/Board.rb +92 -0
- data/lib/tic_tac_toe/Display.rb +55 -0
- data/lib/tic_tac_toe/Game.rb +42 -0
- data/lib/tic_tac_toe/Human.rb +37 -0
- data/lib/tic_tac_toe/Machine.rb +103 -0
- data/lib/tic_tac_toe/Players.rb +11 -0
- metadata +53 -0
data/bin/tic_tac_toe
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require_relative "../lib/tic_tac_toe.rb"
|
|
3
|
+
|
|
4
|
+
first_player = Players.human(1,2)
|
|
5
|
+
first_player.name=("Human")
|
|
6
|
+
|
|
7
|
+
second_player = Players.machine(2,1)
|
|
8
|
+
second_player.name=("Machine")
|
|
9
|
+
session = Game.new(first_player,second_player)
|
|
10
|
+
session.play()
|
data/lib/tic_tac_toe.rb
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
|
|
2
|
+
require_relative "./tic_tac_toe/Board.rb"
|
|
3
|
+
require_relative "./tic_tac_toe/Players.rb"
|
|
4
|
+
require_relative "./tic_tac_toe/Display.rb"
|
|
5
|
+
require_relative "./tic_tac_toe/Human.rb"
|
|
6
|
+
require_relative "./tic_tac_toe/Machine.rb"
|
|
7
|
+
require_relative "./tic_tac_toe/Game.rb"
|
|
8
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
class Board
|
|
2
|
+
|
|
3
|
+
@patterns_array
|
|
4
|
+
Winner_not_found = -1
|
|
5
|
+
|
|
6
|
+
def initialize()
|
|
7
|
+
@board = [0,0,0,0,0,0,0,0,0]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def game_tied?()
|
|
11
|
+
return @board.index(0) == nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def game_over?()
|
|
15
|
+
return get_winner_id() != Winner_not_found || game_tied?()
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def get_winner_id()
|
|
19
|
+
@patterns_array = []
|
|
20
|
+
check_patterns()
|
|
21
|
+
winner = @patterns_array.first
|
|
22
|
+
winner.nil? ? Winner_not_found : winner
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get_cell(position)
|
|
26
|
+
@board[position]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def set_cell(value, cell_position)
|
|
30
|
+
@board[cell_position] = value
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def empty_cell?(position)
|
|
34
|
+
@board[position] == 0
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def cells_equal?(first_cell,second_cell)
|
|
38
|
+
get_cell(first_cell)==get_cell(second_cell)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def cell_symbol(position)
|
|
42
|
+
value = get_cell(position)
|
|
43
|
+
case value
|
|
44
|
+
when 0
|
|
45
|
+
" "
|
|
46
|
+
when 1
|
|
47
|
+
" X "
|
|
48
|
+
when 2
|
|
49
|
+
" O "
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def check_patterns()
|
|
56
|
+
check_vertical_pattern()
|
|
57
|
+
check_horizontal_pattern()
|
|
58
|
+
check_diagonal_pattern()
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def check_vertical_pattern()
|
|
62
|
+
top_cell = 0; center = 3; bottom_cell = 6;
|
|
63
|
+
3.times do
|
|
64
|
+
pattern_scanner(top_cell, center, bottom_cell)
|
|
65
|
+
top_cell +=1; center +=1; bottom_cell +=1;
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def check_horizontal_pattern()
|
|
70
|
+
left_cell = 0; center = 1; right_cell = 2;
|
|
71
|
+
3.times do
|
|
72
|
+
pattern_scanner(left_cell, center, right_cell)
|
|
73
|
+
left_cell +=3; center +=3; right_cell +=3;
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def check_diagonal_pattern()
|
|
78
|
+
first_cell = 0; center = 4; last_cell = 8;
|
|
79
|
+
2.times do
|
|
80
|
+
pattern_scanner(first_cell, center, last_cell)
|
|
81
|
+
first_cell = 2; last_cell = 6;
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def pattern_scanner(first_cell, second_cell, third_cell)
|
|
86
|
+
if (!empty_cell?(first_cell) && cells_equal?(first_cell,second_cell) &&
|
|
87
|
+
cells_equal?(second_cell,third_cell))
|
|
88
|
+
@patterns_array.push(get_cell(first_cell))
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
class Display
|
|
2
|
+
|
|
3
|
+
@player1
|
|
4
|
+
@player2
|
|
5
|
+
|
|
6
|
+
def initialize(player1, player2)
|
|
7
|
+
@player1 = player1
|
|
8
|
+
@player2 = player2
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def game_instructions()
|
|
12
|
+
puts "Goal:"
|
|
13
|
+
puts ""
|
|
14
|
+
puts "The goal of Tic Tac Toe is to be the first player to get"
|
|
15
|
+
puts "three in a row on a 3x3 grid."
|
|
16
|
+
puts ""
|
|
17
|
+
puts "Instructions:"
|
|
18
|
+
puts ""
|
|
19
|
+
puts "In order to enter your move, please provide an integer between"
|
|
20
|
+
puts "1 and 9, the numbers represent the positions in the board the"
|
|
21
|
+
puts "following way:"
|
|
22
|
+
puts "----------------\n"
|
|
23
|
+
puts "| 1 | 2 | 3 |\n"
|
|
24
|
+
puts "----------------\n"
|
|
25
|
+
puts "| 4 | 5 | 6 |\n"
|
|
26
|
+
puts "----------------\n"
|
|
27
|
+
puts "| 7 | 8 | 9 |\n"
|
|
28
|
+
puts "----------------\n"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def board(board,security=true)
|
|
32
|
+
puts "-------------\n"
|
|
33
|
+
puts "|#{board.cell_symbol(0)}|#{board.cell_symbol(1)}|#{board.cell_symbol(2)}|\n"
|
|
34
|
+
puts "-------------\n"
|
|
35
|
+
puts "|#{board.cell_symbol(3)}|#{board.cell_symbol(4)}|#{board.cell_symbol(5)}|\n"
|
|
36
|
+
puts "-------------\n"
|
|
37
|
+
puts "|#{board.cell_symbol(6)}|#{board.cell_symbol(7)}|#{board.cell_symbol(8)}|\n"
|
|
38
|
+
puts "-------------\n"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def game_result(winner)
|
|
42
|
+
if winner == @player1.id
|
|
43
|
+
puts "Congratulations #{@player1.name}"
|
|
44
|
+
elsif winner == @player2.id
|
|
45
|
+
puts "Congratulations #{@player2.name}"
|
|
46
|
+
else #Game is a tie
|
|
47
|
+
puts "Game was a tie"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def player_move(player,move)
|
|
52
|
+
puts "#{player.name} move is: #{move+1}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class Game
|
|
2
|
+
|
|
3
|
+
attr_reader :Player1,:Player2
|
|
4
|
+
|
|
5
|
+
Winner_not_found = -1
|
|
6
|
+
|
|
7
|
+
def initialize(player1, player2)
|
|
8
|
+
@Player1 = player1
|
|
9
|
+
@Player2 = player2
|
|
10
|
+
@Board = Board.new()
|
|
11
|
+
@Display = Display.new(@Player1,@Player2)
|
|
12
|
+
@current_player = @Player1
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def play()
|
|
16
|
+
@Display.game_instructions()
|
|
17
|
+
while !@Board.game_over?
|
|
18
|
+
play_turn()
|
|
19
|
+
update_current_player
|
|
20
|
+
end
|
|
21
|
+
@Display.game_result(@Board.get_winner_id)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def play_turn()
|
|
27
|
+
player_move = @current_player.get_move(@Board)
|
|
28
|
+
@Display.player_move(@current_player,player_move)
|
|
29
|
+
update_and_display_board(@current_player.id, player_move)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def update_current_player()
|
|
33
|
+
@current_player = (@current_player == @Player1) ? @Player2 : @Player1
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update_and_display_board(player,move)
|
|
37
|
+
@Board.set_cell(player,move)
|
|
38
|
+
@Display.board(@Board)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
class Human
|
|
3
|
+
|
|
4
|
+
attr_accessor :name
|
|
5
|
+
attr_reader :id
|
|
6
|
+
|
|
7
|
+
@board
|
|
8
|
+
@id
|
|
9
|
+
@opponent_identifier
|
|
10
|
+
|
|
11
|
+
def initialize(my_id,opponent_id)
|
|
12
|
+
@id = my_id
|
|
13
|
+
@opponent_id = opponent_id
|
|
14
|
+
@name = "Human"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def get_move(board)
|
|
18
|
+
@board = board
|
|
19
|
+
move = 0
|
|
20
|
+
while invalid_move?(move)
|
|
21
|
+
puts "Please provide your move:"
|
|
22
|
+
STDOUT.flush()
|
|
23
|
+
move = gets.chomp.to_i
|
|
24
|
+
if invalid_move?(move)
|
|
25
|
+
puts "Incorrect input provided, please try again."
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
move-1 #Array is 0...8, human player's options are 1..9
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def invalid_move?(move)
|
|
34
|
+
!(1..9).include?(move) || !@board.empty_cell?(move-1)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
class Machine
|
|
2
|
+
|
|
3
|
+
attr_accessor :name
|
|
4
|
+
attr_reader :id
|
|
5
|
+
|
|
6
|
+
@patternsMatrix
|
|
7
|
+
@board
|
|
8
|
+
@id
|
|
9
|
+
@opponent_id
|
|
10
|
+
|
|
11
|
+
def initialize(my_id,opponent_id)
|
|
12
|
+
@patternsMatrix = []
|
|
13
|
+
@id = my_id
|
|
14
|
+
@opponent_id = opponent_id
|
|
15
|
+
@name = "Hal"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def get_move(board)
|
|
19
|
+
@board = board
|
|
20
|
+
strategies_array = get_strategies_array()
|
|
21
|
+
winning_strategy = strategies_array[0]
|
|
22
|
+
blocking_strategy = strategies_array[1]
|
|
23
|
+
no_strategy = strategies_array[2]
|
|
24
|
+
move = winning_strategy
|
|
25
|
+
if move.nil?
|
|
26
|
+
move = blocking_strategy
|
|
27
|
+
if move.nil?
|
|
28
|
+
move = no_strategy
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
move.first
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def get_strategies_array()
|
|
37
|
+
@patternsMatrix = []
|
|
38
|
+
find_vertical_pattern()
|
|
39
|
+
find_horizontal_pattern()
|
|
40
|
+
find_diagonal_pattern()
|
|
41
|
+
get_first_available_move()
|
|
42
|
+
return [@patternsMatrix.rassoc(@id),@patternsMatrix.rassoc(@opponent_id),@patternsMatrix.rassoc(-1)]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def find_vertical_pattern()
|
|
46
|
+
top_position = 0; mid_position = 3; bottom_position = 6
|
|
47
|
+
3.times do
|
|
48
|
+
checkLinesForPattern(top_position, mid_position, bottom_position)
|
|
49
|
+
top_position +=1; mid_position +=1; bottom_position +=1
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def find_horizontal_pattern()
|
|
54
|
+
left_position = 0; mid_position = 1; right_position = 2
|
|
55
|
+
3.times do
|
|
56
|
+
checkLinesForPattern(left_position, mid_position, right_position)
|
|
57
|
+
left_position +=3; mid_position +=3; right_position +=3
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def find_diagonal_pattern()
|
|
62
|
+
first = 0 ; second = 4; third = 8
|
|
63
|
+
2.times do
|
|
64
|
+
checkLinesForPattern(first, second, third)
|
|
65
|
+
first = 2; third = 6
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def get_first_available_move()
|
|
70
|
+
if @board.empty_cell?(4)
|
|
71
|
+
@patternsMatrix.push([4,-1])
|
|
72
|
+
elsif @board.empty_cell?(0)
|
|
73
|
+
@patternsMatrix.push([0,-1])
|
|
74
|
+
elsif @board.empty_cell?(2)
|
|
75
|
+
@patternsMatrix.push([2,-1])
|
|
76
|
+
elsif @board.empty_cell?(6)
|
|
77
|
+
@patternsMatrix.push([6,-1])
|
|
78
|
+
elsif @board.empty_cell?(8)
|
|
79
|
+
@patternsMatrix.push([8,-1])
|
|
80
|
+
else
|
|
81
|
+
random_generator = Random.new
|
|
82
|
+
move = random_generator.rand(0..8)
|
|
83
|
+
while !@board.empty_cell?(move)
|
|
84
|
+
move = random_generator.rand(0..8)
|
|
85
|
+
end
|
|
86
|
+
@patternsMatrix.push([move,-1])
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def checkLinesForPattern(first_position, second_position, third_position)
|
|
91
|
+
if (!@board.empty_cell?(first_position) && @board.cells_equal?(first_position,second_position) &&
|
|
92
|
+
@board.empty_cell?(third_position))
|
|
93
|
+
@patternsMatrix.push([third_position,@board.get_cell(first_position)])
|
|
94
|
+
elsif (!@board.empty_cell?(first_position) && @board.cells_equal?(first_position,third_position) &&
|
|
95
|
+
@board.empty_cell?(second_position))
|
|
96
|
+
@patternsMatrix.push([second_position,@board.get_cell(first_position)])
|
|
97
|
+
elsif (!@board.empty_cell?(second_position) && @board.cells_equal?(second_position,third_position) &&
|
|
98
|
+
@board.empty_cell?(first_position))
|
|
99
|
+
@patternsMatrix.push([first_position,@board.get_cell(second_position)])
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: tic_tac_toe_wilbertcr
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Wilbert Sequeira
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2013-06-14 00:00:00.000000000 Z
|
|
13
|
+
dependencies: []
|
|
14
|
+
description: Console Tic Tac Toe game
|
|
15
|
+
email: wilbertcr@gmail.com
|
|
16
|
+
executables:
|
|
17
|
+
- tic_tac_toe
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- lib/tic_tac_toe.rb
|
|
22
|
+
- lib/tic_tac_toe/Human.rb
|
|
23
|
+
- lib/tic_tac_toe/Players.rb
|
|
24
|
+
- lib/tic_tac_toe/Machine.rb
|
|
25
|
+
- lib/tic_tac_toe/Game.rb
|
|
26
|
+
- lib/tic_tac_toe/Board.rb
|
|
27
|
+
- lib/tic_tac_toe/Display.rb
|
|
28
|
+
- bin/tic_tac_toe
|
|
29
|
+
homepage: http://rubygems.org/gems/tic_tac_toe
|
|
30
|
+
licenses: []
|
|
31
|
+
post_install_message:
|
|
32
|
+
rdoc_options: []
|
|
33
|
+
require_paths:
|
|
34
|
+
- lib
|
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
36
|
+
none: false
|
|
37
|
+
requirements:
|
|
38
|
+
- - ! '>='
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
42
|
+
none: false
|
|
43
|
+
requirements:
|
|
44
|
+
- - ! '>='
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
requirements: []
|
|
48
|
+
rubyforge_project:
|
|
49
|
+
rubygems_version: 1.8.25
|
|
50
|
+
signing_key:
|
|
51
|
+
specification_version: 3
|
|
52
|
+
summary: Tic tac toe console game
|
|
53
|
+
test_files: []
|