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