swttt-gem 0.9.0 → 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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.0
1
+ 1.0.0
data/lib/.DS_Store ADDED
Binary file
data/lib/board.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class Board
2
- attr_reader :game_history, :game_board, :player_value, :board, :row_scores,
2
+ attr_reader :game_history, :player_value, :row_scores, :dimension,
3
3
  :column_scores, :left_diagonal_score, :right_diagonal_score
4
4
 
5
5
  def initialize(dimension = 3)
@@ -25,6 +25,10 @@ class Board
25
25
  @game_history.size
26
26
  end
27
27
 
28
+ def value_at(row, column)
29
+ @board[row][column]
30
+ end
31
+
28
32
  def is_empty_at?(row, column)
29
33
  @board[row][column].zero?
30
34
  end
@@ -33,8 +37,8 @@ class Board
33
37
  @game_history.size == @dimension*@dimension
34
38
  end
35
39
 
36
- def dimension
37
- @dimension-1
40
+ def winning_value
41
+ @dimension
38
42
  end
39
43
 
40
44
  def player_value
@@ -43,31 +47,29 @@ class Board
43
47
  return value
44
48
  end
45
49
 
46
- def print
47
- (0...@dimension).each { |row| print_row(row) }
48
- puts "\n"
50
+ def corner_occupied?
51
+ corner_cells.each { |corner| return true if @game_history.include?(corner) }
52
+ return false
49
53
  end
50
54
 
51
- private
52
-
53
- def print_row(row)
54
- puts "\n"
55
- (0...@dimension).each { |column| print_square(row, column) }
55
+ def random_corner_cell
56
+ corner_cells[rand(corner_cells.size)]
56
57
  end
57
58
 
58
- def print_square(row, column)
59
- putc "["
60
- putc "X" if @board[row][column] == 1
61
- putc"O" if @board[row][column] == -1
62
- putc " " if @board[row][column].zero?
63
- putc "]"
59
+ private
60
+
61
+ def corner_cells
62
+ [Move.new(0,0),
63
+ Move.new(0,@dimension-1),
64
+ Move.new(@dimension-1,0),
65
+ Move.new(@dimension-1, @dimension-1)]
64
66
  end
65
67
 
66
68
  def update_sums(row, column, update_value)
67
69
  @row_scores[row] += update_value
68
70
  @column_scores[column] += update_value
69
71
  @left_diagonal_score += update_value if row == column
70
- @right_diagonal_score += update_value if row == dimension - column
72
+ @right_diagonal_score += update_value if row == dimension - column - 1
71
73
  end
72
74
  end
73
75
 
data/lib/game_observer.rb CHANGED
@@ -28,11 +28,11 @@ private
28
28
  end
29
29
 
30
30
  def check_for_winner
31
- (0..@game_board.dimension).each { |index| return true if is_a_win?(yield(index)) }
32
- false
31
+ (0...@game_board.dimension).each { |index| return true if is_a_win?(yield(index)) }
32
+ return false
33
33
  end
34
34
 
35
35
  def is_a_win?(value)
36
- value == @game_board.dimension+1
36
+ value == @game_board.winning_value
37
37
  end
38
38
  end
@@ -2,10 +2,6 @@ class MinimaxComputer
2
2
 
3
3
  def initialize(board, observer)
4
4
  @game_board, @observer = board, observer
5
- @first_move = [Move.new(0,0),
6
- Move.new(0,@game_board.dimension),
7
- Move.new(@game_board.dimension,0),
8
- Move.new(@game_board.dimension, @game_board.dimension)]
9
5
  @my_player_value = @game_board.player_value
10
6
  end
11
7
 
@@ -28,37 +24,29 @@ private
28
24
  @game_board.move(move.row, move.column)
29
25
  end
30
26
 
31
- def select_first_move
32
- return corner_move if all_board_corners_open?
33
- return middle_move
34
- end
35
-
36
- def all_board_corners_open?
37
- !@first_move.include?(@game_board.game_history.first)
38
- end
39
-
40
- def corner_move
41
- @first_move[rand(@first_move.size)]
42
- end
43
-
44
- def middle_move
45
- middle = @game_board.dimension/2
46
- return move = Move.new(middle, middle)
47
- end
48
-
49
27
  def perform_mini_max(iteration)
50
28
  return path_score if @observer.game_over?
51
29
  best_moves = BestMove.new(@game_board, @my_player_value)
52
- for_each_cell { |row, column| best_moves.add_better_move(best_moves.value, calculate_path_score(row, column,iteration),
30
+ for_each_cell { |row, column| best_moves.add_better_move(calculate_path_score(row, column,iteration),
53
31
  Move.new(row, column)) if @game_board.is_empty_at?(row, column) }
54
32
  return best_moves.value if !iteration.zero?
55
33
  move = best_moves.get_random_move
56
34
  @game_board.move(move.row, move.column)
57
35
  end
58
36
 
59
- def for_each_cell
60
- (0..@game_board.dimension).each do |row|
61
- (0..@game_board.dimension).each { |column| yield(row, column) }
37
+ def select_first_move
38
+ return @game_board.random_corner_cell if !@game_board.corner_occupied?
39
+ return middle_move
40
+ end
41
+
42
+ def middle_move
43
+ middle = @game_board.dimension/2
44
+ return move = Move.new(middle, middle)
45
+ end
46
+
47
+ def for_each_cell
48
+ (0...@game_board.dimension).each do |row|
49
+ (0...@game_board.dimension).each { |column| yield(row, column) }
62
50
  end
63
51
  end
64
52
 
@@ -103,16 +91,16 @@ class BestMove
103
91
  @moves[rand(@moves.size)]
104
92
  end
105
93
 
106
- def add_better_move(best_score, path_score, move)
107
- if better_or_equal_move?(best_score, path_score)
94
+ def add_better_move(path_score, move)
95
+ if better_or_equal_move?(path_score)
108
96
  @moves.clear and @value = path_score if path_score != @value
109
97
  @moves << move
110
98
  end
111
99
  end
112
100
 
113
- def better_or_equal_move?(best_score, path_score)
114
- (best_score.nil?) or
115
- (path_score >= best_score && @game_board.player_value == @my_player_value) or
116
- (path_score <= best_score && @game_board.player_value != @my_player_value)
101
+ def better_or_equal_move?(path_score)
102
+ (@value.nil?) or
103
+ (path_score >= @value && @game_board.player_value == @my_player_value) or
104
+ (path_score <= @value && @game_board.player_value != @my_player_value)
117
105
  end
118
106
  end
data/spec/board_spec.rb CHANGED
@@ -7,20 +7,20 @@ describe Board do
7
7
  end
8
8
 
9
9
  def iterate_board
10
- (0..@my_board.dimension).each do |row|
11
- (0..@my_board.dimension).each do |column|
10
+ (0...@my_board.dimension).each do |row|
11
+ (0...@my_board.dimension).each do |column|
12
12
  yield(row, column)
13
13
  end
14
14
  end
15
15
  end
16
16
 
17
17
  it "should create a board" do
18
- @my_board.nil?.should == false
18
+ @my_board.nil?.should be_false
19
19
  end
20
20
 
21
21
  it "should check for a full board" do
22
22
  iterate_board { |row, column| @my_board.move(row, column) }
23
- @my_board.full?.should == true
23
+ @my_board.full?.should be_true
24
24
  end
25
25
 
26
26
  context "game history" do
@@ -75,20 +75,15 @@ describe Board do
75
75
  @my_board.player_value.should == 1
76
76
  end
77
77
 
78
- it "has a 3x3 board" do
79
- @my_board.board.size.should == 3
80
- @my_board.board[1].size.should == 3
81
- end
82
-
83
78
  it "updates the board when move is called" do
84
79
  @my_board.move(0,0)
85
- @my_board.board[0][0].should == 1
80
+ @my_board.value_at(0,0).should == 1
86
81
  end
87
82
 
88
83
  it "undos the board" do
89
84
  @my_board.move(2,2)
90
85
  @my_board.undo_move
91
- @my_board.board[2][2].should == 0
86
+ @my_board.value_at(2,2).should == 0
92
87
  end
93
88
 
94
89
  context "sum values" do
@@ -126,4 +121,29 @@ describe Board do
126
121
  @my_board.right_diagonal_score.should == 0
127
122
  end
128
123
  end
124
+
125
+ it "has a winning value" do
126
+ @my_board.winning_value.should == 3
127
+ end
128
+
129
+ it "detects if a corner cell is occupied" do
130
+ @my_board.corner_occupied?.should be_false
131
+ @my_board.move(0,0)
132
+ @my_board.corner_occupied?.should be_true
133
+ @my_board.undo_move
134
+ @my_board.move(0,2)
135
+ @my_board.corner_occupied?.should be_true
136
+ @my_board.undo_move
137
+ @my_board.move(2,0)
138
+ @my_board.corner_occupied?.should be_true
139
+ @my_board.undo_move
140
+ @my_board.move(2,2)
141
+ @my_board.corner_occupied?.should be_true
142
+ end
143
+
144
+ it "returns a random corner cell" do
145
+ move = @my_board.random_corner_cell
146
+ @my_board.move(move.row, move.column)
147
+ @my_board.corner_occupied?.should be_true
148
+ end
129
149
  end
@@ -9,7 +9,7 @@ describe GameObserver do
9
9
  end
10
10
 
11
11
  def iterate_row_or_column
12
- (0..@my_board.dimension).each { |position| yield(position) }
12
+ (0...@my_board.dimension).each { |position| yield(position) }
13
13
  end
14
14
 
15
15
  it "detects a horizontal win" do
@@ -28,7 +28,7 @@ describe GameObserver do
28
28
  end
29
29
 
30
30
  it "detects a right diagonal win" do
31
- iterate_row_or_column { |position| @my_board.move(@my_board.dimension-position,position,1) }
31
+ iterate_row_or_column { |position| @my_board.move(@my_board.dimension-position-1,position,1) }
32
32
  @observer.has_winner?.should == true
33
33
  end
34
34
 
data/swttt-gem.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{swttt-gem}
8
- s.version = "0.9.0"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Stephen Walker"]
12
- s.date = %q{2011-05-09}
12
+ s.date = %q{2011-05-11}
13
13
  s.description = %q{TTT Gem}
14
14
  s.email = %q{stephenwalker1988@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
25
25
  "README.rdoc",
26
26
  "Rakefile",
27
27
  "VERSION",
28
+ "lib/.DS_Store",
28
29
  "lib/board.rb",
29
30
  "lib/game_observer.rb",
30
31
  "lib/human_player.rb",
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swttt-gem
3
3
  version: !ruby/object:Gem::Version
4
- hash: 59
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
+ - 1
7
8
  - 0
8
- - 9
9
9
  - 0
10
- version: 0.9.0
10
+ version: 1.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Stephen Walker
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-09 00:00:00 -05:00
18
+ date: 2011-05-11 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -96,6 +96,7 @@ files:
96
96
  - README.rdoc
97
97
  - Rakefile
98
98
  - VERSION
99
+ - lib/.DS_Store
99
100
  - lib/board.rb
100
101
  - lib/game_observer.rb
101
102
  - lib/human_player.rb