ultimate_tic_tac_toe 0.0.21
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 +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/ultimate_tic_tac_toe/board.rb +92 -0
- data/lib/ultimate_tic_tac_toe/computer.rb +89 -0
- data/lib/ultimate_tic_tac_toe/game.rb +83 -0
- data/lib/ultimate_tic_tac_toe/interface.rb +75 -0
- data/lib/ultimate_tic_tac_toe/version.rb +3 -0
- data/lib/ultimate_tic_tac_toe.rb +11 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/ultimate_tic_tac_toe/board_spec.rb +71 -0
- data/spec/ultimate_tic_tac_toe/computer_spec.rb +30 -0
- data/spec/ultimate_tic_tac_toe/game_spec.rb +29 -0
- data/spec/ultimate_tic_tac_toe/interface_spec.rb +38 -0
- data/ultimate_tic_tac_toe.gemspec +23 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b2f259908af12ca6c27a5057faae16a431ce2313
|
4
|
+
data.tar.gz: c6eda1e857bc58679e0d53b50820e3e1c581058c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c983dace240e29d196ef3f89d066f2700134b5271c337377d9d785c91386c469498051aded5d4b5fe8678bd9fad2ebc6e8bbd5ed717eb18fb7381b57dabf27ee
|
7
|
+
data.tar.gz: e1b7e9f2f1c0dd57cf0cce8aa2ab069e3d0b8a22fc21c16c18421f85373bc34eb1d0458d0b80cf7fe72454c3ff08f4637d32f050eb577a1f7081023a5703e2a0
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 TODO: Write your name
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# UltimateTicTacToe
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'ultimate_tic_tac_toe'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ultimate_tic_tac_toe
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,92 @@
|
|
1
|
+
class Board
|
2
|
+
|
3
|
+
HUMAN = "X"
|
4
|
+
COMPUTER = "O"
|
5
|
+
|
6
|
+
attr_accessor :grid, :size, :possible_boards, :player
|
7
|
+
|
8
|
+
def initialize(grid_size)
|
9
|
+
@grid = Array.new(grid_size)
|
10
|
+
@size = @grid.length
|
11
|
+
@possible_boards = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def winning_possibilities
|
15
|
+
if grid.length == 9
|
16
|
+
[[0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [2,4,6]]
|
17
|
+
elsif grid.length == 16
|
18
|
+
[[0,1,2,3], [4,5,6,7], [8,9,10,11],[12,13,14,15], [0,5,10,15], [3,6,9, 12], [0,4,8,12], [1,5,9,13], [2,6,10,14], [3,7,11,15]]
|
19
|
+
elsif grid.length == 25
|
20
|
+
[[0,1,2,3,4], [5,6,7,8,9],[10,11,12,13,14],[15,16,17,18,19], [20,21,22,23,24,25], [0,5,10,15,20], [1,6,11,16,21], [2,7,12,17,22], [3,8,13,18,23],[4,9,14,19,24], [0,6,12,18,24],[4,8,12,16,20]]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def winner?(player)
|
25
|
+
if grid.length == 9
|
26
|
+
winning_possibilities.each do |win|
|
27
|
+
if grid[win[0]] == player && grid[win[1]] == player && grid[win[2]] == player
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
elsif grid.length == 16
|
32
|
+
winning_possibilities.each do |win|
|
33
|
+
if grid[win[0]] == player && grid[win[1]] == player && grid[win[2]] == player && grid[win[3]] == player
|
34
|
+
return true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
elsif grid.length == 25
|
38
|
+
winning_possibilities.each do |win|
|
39
|
+
if grid[win[0]] == player && grid[win[1]] == player && grid[win[2]] == player && grid[win[3]] == player && grid[win[4]] == player
|
40
|
+
return true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
def tie?
|
48
|
+
if (player_moves + computer_moves) == grid.length && !winner?("X") && !winner?("O")
|
49
|
+
true
|
50
|
+
else
|
51
|
+
false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def occupied?(grid, location)
|
56
|
+
grid[location].nil? ? false : grid[location]
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_move_list(grid)
|
60
|
+
grid.each_index.select{|index| grid[index].nil?}
|
61
|
+
end
|
62
|
+
|
63
|
+
def unoccupied(position)
|
64
|
+
@grid[position].nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
def take_turn(player)
|
68
|
+
player == HUMAN ? COMPUTER : HUMAN
|
69
|
+
end
|
70
|
+
|
71
|
+
def store_position(position, participant)
|
72
|
+
@grid[position] = participant
|
73
|
+
end
|
74
|
+
|
75
|
+
def simulate_move(board, position, player)
|
76
|
+
board.grid[position] = player
|
77
|
+
board
|
78
|
+
end
|
79
|
+
|
80
|
+
def current_player
|
81
|
+
@grid.count(HUMAN) > @grid.count(COMPUTER) ? COMPUTER : HUMAN
|
82
|
+
end
|
83
|
+
|
84
|
+
def player_moves
|
85
|
+
@grid.count(HUMAN)
|
86
|
+
end
|
87
|
+
|
88
|
+
def computer_moves
|
89
|
+
@grid.count(COMPUTER)
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class Computer
|
2
|
+
|
3
|
+
HUMAN = "X"
|
4
|
+
COMPUTER = "O"
|
5
|
+
MAX_DEPTH = 5 #to control length of calc time
|
6
|
+
|
7
|
+
attr_accessor :best_move, :sub_alpha, :active_player
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@sub_alpha = []
|
11
|
+
@best_move = 0
|
12
|
+
@best_moves =[]
|
13
|
+
end
|
14
|
+
|
15
|
+
def computer_move(board)
|
16
|
+
if board.player_moves > board.computer_moves
|
17
|
+
@active_player = COMPUTER
|
18
|
+
computers_move(board)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def computers_move(board)
|
23
|
+
if board.computer_moves < 0
|
24
|
+
if board.unoccupied(6)
|
25
|
+
board.store_position(6, COMPUTER)
|
26
|
+
else
|
27
|
+
board.store_position(8, COMPUTER)
|
28
|
+
end
|
29
|
+
else
|
30
|
+
minimax(board, @active_player)
|
31
|
+
board.store_position(@best_move, @active_player)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def minimax(board, current_player)
|
36
|
+
minimax_recurse(board, current_player, 0)
|
37
|
+
end
|
38
|
+
|
39
|
+
def check_winner(board, depth)
|
40
|
+
winner = 'None'
|
41
|
+
winner = COMPUTER if board.winner?(COMPUTER)
|
42
|
+
winner = HUMAN if board.winner?(HUMAN)
|
43
|
+
winner = 'tie' if board.tie?
|
44
|
+
winner = 'tie' if (depth >= MAX_DEPTH && board.grid.size > 10)
|
45
|
+
winner
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def minimax_recurse(board, player, depth)
|
50
|
+
winner = check_winner(board, depth)
|
51
|
+
unless winner == 'None'
|
52
|
+
if winner == 'tie'
|
53
|
+
return 0
|
54
|
+
elsif winner == @active_player
|
55
|
+
return 1
|
56
|
+
else
|
57
|
+
return -1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
next_player = (player == COMPUTER ? HUMAN : COMPUTER )
|
62
|
+
|
63
|
+
if player == @active_player
|
64
|
+
alpha = -1
|
65
|
+
else
|
66
|
+
alpha = 1
|
67
|
+
end
|
68
|
+
|
69
|
+
possible_moves = board.get_move_list(board.grid)
|
70
|
+
|
71
|
+
possible_moves.each do |move|
|
72
|
+
new_board = board.dup
|
73
|
+
new_board.grid = board.grid.dup
|
74
|
+
next_board = new_board.simulate_move(new_board, move, player)
|
75
|
+
@sub_alpha = minimax_recurse(next_board, next_player, depth + 1)
|
76
|
+
|
77
|
+
if player == @active_player
|
78
|
+
if ((depth == 0 ) && (alpha <= @sub_alpha ))
|
79
|
+
@best_move = move
|
80
|
+
end
|
81
|
+
alpha = [alpha, @sub_alpha].max
|
82
|
+
else
|
83
|
+
alpha = [alpha, @sub_alpha].min
|
84
|
+
end
|
85
|
+
end
|
86
|
+
alpha
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
class Game
|
2
|
+
|
3
|
+
HUMAN = "X"
|
4
|
+
COMPUTER = "O"
|
5
|
+
|
6
|
+
attr_accessor :position
|
7
|
+
|
8
|
+
def initialize(interface, computer)
|
9
|
+
@interface = interface
|
10
|
+
@computer = computer
|
11
|
+
end
|
12
|
+
|
13
|
+
def check_within_range(position, grid_length)
|
14
|
+
if position == "0"
|
15
|
+
true
|
16
|
+
elsif position.to_i < grid_length && position.to_i > 0
|
17
|
+
true
|
18
|
+
else
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_space_unoccupied(position)
|
24
|
+
@board.unoccupied(position)
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate_input(inputted_position, grid)
|
28
|
+
end_of_grid = grid.length
|
29
|
+
|
30
|
+
until check_within_range(inputted_position, end_of_grid)
|
31
|
+
@interface.reject(inputted_position)
|
32
|
+
@interface.prompt
|
33
|
+
inputted_position = @interface.user_input
|
34
|
+
end
|
35
|
+
|
36
|
+
until check_space_unoccupied(inputted_position.to_i)
|
37
|
+
@interface.denied
|
38
|
+
@interface.prompt
|
39
|
+
inputted_position = @interface.user_input
|
40
|
+
end
|
41
|
+
|
42
|
+
inputted_position.to_i
|
43
|
+
end
|
44
|
+
|
45
|
+
def game_over
|
46
|
+
(@board.tie? || @board.winner?(COMPUTER) || @board.winner?(HUMAN))
|
47
|
+
end
|
48
|
+
|
49
|
+
def check_board_after_computer_move
|
50
|
+
if @board.winner?("O") == true
|
51
|
+
@interface.computer_wins
|
52
|
+
@interface.pretty_print_board(@board.grid)
|
53
|
+
|
54
|
+
elsif @board.tie?
|
55
|
+
@interface.cats_game
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def play
|
60
|
+
@board = @board ||= Board.new(@interface.grid_size)
|
61
|
+
|
62
|
+
until game_over
|
63
|
+
|
64
|
+
@interface.pretty_print_board(@board.grid)
|
65
|
+
@interface.prompt
|
66
|
+
position = validate_input(@interface.user_input, @board.grid)
|
67
|
+
|
68
|
+
@board.store_position(position, HUMAN)
|
69
|
+
|
70
|
+
if @board.winner?("X") == true
|
71
|
+
@interface.player_wins
|
72
|
+
@interface.pretty_print_board(@board.grid)
|
73
|
+
else
|
74
|
+
@computer.computer_move(@board)
|
75
|
+
check_board_after_computer_move
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
class Interface
|
2
|
+
|
3
|
+
def opening_prompt
|
4
|
+
puts "What size board do you want to play (9, 16, 25)"
|
5
|
+
size = user_input
|
6
|
+
size
|
7
|
+
end
|
8
|
+
|
9
|
+
def grid_size
|
10
|
+
size = opening_prompt
|
11
|
+
|
12
|
+
if size == "9" || size == "16" || size == '25'
|
13
|
+
return size.to_i
|
14
|
+
else
|
15
|
+
puts "Please enter 9, 16 or 25"
|
16
|
+
grid_size
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def axis_length(size)
|
22
|
+
Math.sqrt(size).to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
def insert_spaces(position, size, output, grid)
|
26
|
+
if position % axis_length(size) == (axis_length(size) - 1)
|
27
|
+
output << "\n" unless position == (size - 1)
|
28
|
+
else
|
29
|
+
if position < 10 || !grid[position].nil?
|
30
|
+
output << " "
|
31
|
+
else
|
32
|
+
output << " "
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
def pretty_print_board(grid)
|
39
|
+
output = ""
|
40
|
+
size = grid.length
|
41
|
+
size.times do |position|
|
42
|
+
output << (grid[position].nil? ? position.to_s : "#{grid[position]}")
|
43
|
+
insert_spaces(position, size, output, grid)
|
44
|
+
end
|
45
|
+
puts "\n Your Board \n\n\n" + output
|
46
|
+
end
|
47
|
+
|
48
|
+
def prompt
|
49
|
+
puts "Where do you want to place your X?"
|
50
|
+
end
|
51
|
+
|
52
|
+
def user_input
|
53
|
+
gets.chomp
|
54
|
+
end
|
55
|
+
|
56
|
+
def denied
|
57
|
+
puts "Already occupied, try again"
|
58
|
+
end
|
59
|
+
|
60
|
+
def cats_game
|
61
|
+
puts "CATS GAME!"
|
62
|
+
end
|
63
|
+
|
64
|
+
def computer_wins
|
65
|
+
puts "Computer wins! Again"
|
66
|
+
end
|
67
|
+
|
68
|
+
def player_wins
|
69
|
+
puts "Human wins! Impossible!"
|
70
|
+
end
|
71
|
+
|
72
|
+
def reject(position)
|
73
|
+
puts "#{position} isnt no good"
|
74
|
+
end
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Board do
|
4
|
+
let(:new_board) {Board.new(9)}
|
5
|
+
let(:new_board_16){Board.new(16)}
|
6
|
+
let(:new_interface) {Interface.new}
|
7
|
+
HUMAN = "X"
|
8
|
+
COMPUTER = "O"
|
9
|
+
|
10
|
+
it "checks for player victories(3x3)" do
|
11
|
+
new_board.grid = ["X", 1, 2, "X", 4, 5, "X", 7, 8]
|
12
|
+
new_board.winner?("X").should eq true
|
13
|
+
end
|
14
|
+
|
15
|
+
it "checks for player victories(4x4)" do
|
16
|
+
new_board.grid = ["X", 1, 2, 3, 4, "X", 6, 7, 8,9,"X",11,12,13,14,"X"]
|
17
|
+
new_board.winner?("X").should eq true
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'checks for a tie' do
|
21
|
+
new_board.grid = ["X","O","X","X","O","O","O","X","X"]
|
22
|
+
new_board.tie?.should == true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'checks for a tie(4x4)' do
|
26
|
+
new_board_16.grid = ["X","O","X","O","O","O","X","O","X", "X","O","O","X","O","X","X"]
|
27
|
+
new_board_16.tie?.should == true
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'checks for a tie(4x4)' do
|
31
|
+
new_board_16.grid = ["X","O","X","O","O","O","X","O","X", "O","O","O","X","X","X","X"]
|
32
|
+
new_board_16.tie?.should == false
|
33
|
+
end
|
34
|
+
|
35
|
+
it "stores player positions" do
|
36
|
+
new_board.store_position(1, HUMAN)
|
37
|
+
new_board.grid.should == [nil, "X",nil,nil,nil,nil,nil,nil,nil]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "checks to see if a spot is occupied" do
|
41
|
+
grid = [nil,nil,nil,nil,nil,nil,nil,nil,nil]
|
42
|
+
new_board.occupied?(grid, 3).should eq false
|
43
|
+
end
|
44
|
+
|
45
|
+
it "lets players alternate" do
|
46
|
+
new_board.take_turn(HUMAN).should == COMPUTER
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'stores simulated moves' do
|
50
|
+
new_board.grid = [nil, "X",nil,nil,nil,nil,nil,nil,nil]
|
51
|
+
board_copy = new_board.dup
|
52
|
+
board_copy.simulate_move(board_copy, 3, "O").grid.should == [nil, "X",nil,"O",nil,nil,nil,nil,nil]
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
it 'makes a list of possible moves' do
|
57
|
+
grid = [nil, "X",nil,nil,nil,nil,nil,nil,nil]
|
58
|
+
new_board.get_move_list(grid).should == [0,2,3,4,5,6,7,8]
|
59
|
+
end
|
60
|
+
|
61
|
+
it "checks for unoccupied spaces" do
|
62
|
+
new_board.grid = [nil, "X",nil,nil,nil,nil,nil,nil,nil]
|
63
|
+
new_board.unoccupied(1).should == false
|
64
|
+
end
|
65
|
+
|
66
|
+
it "tests possible combinations for computer's victory(3x3)" do
|
67
|
+
new_board.grid = ["O", 1, 2, "O", 4, 5, "O", 7, 8]
|
68
|
+
new_board.winner?("O").should eq true
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'computer'
|
2
|
+
require 'board'
|
3
|
+
|
4
|
+
describe Computer do
|
5
|
+
let!(:new_interface) {Interface.new}
|
6
|
+
let!(:new_board) {Board.new(9)}
|
7
|
+
let(:new_computer) {Computer.new}
|
8
|
+
let(:fun_game) {Game.new(new_interface, new_computer)}
|
9
|
+
|
10
|
+
it 'knows the current player' do
|
11
|
+
new_board.grid = [0,1,2,"X",4,5,6,7,8]
|
12
|
+
new_board.current_player.should == COMPUTER
|
13
|
+
end
|
14
|
+
|
15
|
+
it "checks for computer wins during recursion" do
|
16
|
+
new_board.grid = [0, "O", 2, "X", "O", 5, "X", "O", 8]
|
17
|
+
new_computer.minimax_recurse(new_board,"O", 1).should == -1
|
18
|
+
end
|
19
|
+
|
20
|
+
it "checks for ties during recursion" do
|
21
|
+
new_board.grid = ["X","O","X","X","O","O","O","X","X"]
|
22
|
+
new_computer.minimax_recurse(new_board, "O", 8).should == 0
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns sub-alpha values for a given board' do
|
26
|
+
new_board.grid = [0, 1, 2 , 3, 4, 5, 6, 7, 8]
|
27
|
+
new_computer.minimax_recurse(new_board, HUMAN, 0).should == 1
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'game'
|
2
|
+
require 'interface'
|
3
|
+
require 'board'
|
4
|
+
# puts $:
|
5
|
+
describe Game do
|
6
|
+
let!(:new_interface) {Interface.new}
|
7
|
+
let!(:new_board) {Board.new(9)}
|
8
|
+
let(:new_computer) {Computer.new}
|
9
|
+
let(:fun_game) {Game.new(new_interface, new_computer)}
|
10
|
+
|
11
|
+
it "can check that human's move is within the board" do
|
12
|
+
fun_game.check_within_range("7", new_board.grid.length).should eq true
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'determines when the game is over' do
|
16
|
+
fun_game.stub(:new).and_return(new_board)
|
17
|
+
new_board.stub(:tie?).and_return(true)
|
18
|
+
fun_game.game_over.should be(true)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "informs the player of bad input" do
|
22
|
+
# new_interface.stub(:gets){"g\n"}
|
23
|
+
# fun_game.validate_input("\z", new_board.grid)
|
24
|
+
# fun_game.should_receive(:validate_input).with("d", new_board.grid)
|
25
|
+
fun_game.should_receive(:puts).with("f isnt no good")
|
26
|
+
fun_game.validate_input("f", new_board.grid)
|
27
|
+
# new_interface.prompt
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'game'
|
2
|
+
require 'interface'
|
3
|
+
require 'board'
|
4
|
+
|
5
|
+
|
6
|
+
describe Interface do
|
7
|
+
|
8
|
+
let!(:new_interface) {Interface.new}
|
9
|
+
let!(:new_board) {Board.new(9)}
|
10
|
+
let(:new_computer) {Computer.new}
|
11
|
+
let(:fun_game) {Game.new(new_interface, new_computer)}
|
12
|
+
|
13
|
+
# it "informs the player of bad input" do
|
14
|
+
# Interface.stub(:new).and_return(new_interface)
|
15
|
+
# new_interface.stub(:gets){"g\n"}
|
16
|
+
# fun_game.should_receive(:puts).with("f isnt no good").at_least(1).times
|
17
|
+
# new_interface.prompt
|
18
|
+
# end
|
19
|
+
|
20
|
+
# it 'prints a board that corresponds to the grid size' do
|
21
|
+
|
22
|
+
# end
|
23
|
+
it 'gets the initial input from human' do
|
24
|
+
new_interface.stub(:gets){"9\n"}
|
25
|
+
new_interface.opening_prompt.should == "9"
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'determines the grid length of the board' do
|
29
|
+
new_interface.stub(:gets){"9\n"}
|
30
|
+
new_interface.grid_size.should == 9
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'prints out a pretty board' do
|
34
|
+
new_interface.should_receive(:puts).with("\n Your Board \n\n\n0 1 2\n3 4 5\n6 7 8")
|
35
|
+
new_interface.pretty_print_board(new_board.grid)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ultimate_tic_tac_toe/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ultimate_tic_tac_toe"
|
8
|
+
spec.version = UltimateTicTacToe::VERSION
|
9
|
+
spec.authors = ["Rod Levy"]
|
10
|
+
spec.email = ["rodlevy1@gmail.com"]
|
11
|
+
spec.description = %q{Unbeatable Tic Tac Toe Game}
|
12
|
+
spec.summary = %q{Implements a game of tic-tac-toe where the computer always wins}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ultimate_tic_tac_toe
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.21
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rod Levy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Unbeatable Tic Tac Toe Game
|
42
|
+
email:
|
43
|
+
- rodlevy1@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- lib/ultimate_tic_tac_toe.rb
|
54
|
+
- lib/ultimate_tic_tac_toe/board.rb
|
55
|
+
- lib/ultimate_tic_tac_toe/computer.rb
|
56
|
+
- lib/ultimate_tic_tac_toe/game.rb
|
57
|
+
- lib/ultimate_tic_tac_toe/interface.rb
|
58
|
+
- lib/ultimate_tic_tac_toe/version.rb
|
59
|
+
- spec/spec_helper.rb
|
60
|
+
- spec/ultimate_tic_tac_toe/board_spec.rb
|
61
|
+
- spec/ultimate_tic_tac_toe/computer_spec.rb
|
62
|
+
- spec/ultimate_tic_tac_toe/game_spec.rb
|
63
|
+
- spec/ultimate_tic_tac_toe/interface_spec.rb
|
64
|
+
- ultimate_tic_tac_toe.gemspec
|
65
|
+
homepage: ''
|
66
|
+
licenses:
|
67
|
+
- MIT
|
68
|
+
metadata: {}
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 2.0.6
|
86
|
+
signing_key:
|
87
|
+
specification_version: 4
|
88
|
+
summary: Implements a game of tic-tac-toe where the computer always wins
|
89
|
+
test_files:
|
90
|
+
- spec/spec_helper.rb
|
91
|
+
- spec/ultimate_tic_tac_toe/board_spec.rb
|
92
|
+
- spec/ultimate_tic_tac_toe/computer_spec.rb
|
93
|
+
- spec/ultimate_tic_tac_toe/game_spec.rb
|
94
|
+
- spec/ultimate_tic_tac_toe/interface_spec.rb
|