bashrw_ttt 0.1.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/bin/play.rb +10 -0
- data/lib/ttt/ai.rb +33 -0
- data/lib/ttt/ai_easy.rb +17 -0
- data/lib/ttt/ai_hard.rb +21 -0
- data/lib/ttt/ai_medium.rb +21 -0
- data/lib/ttt/ai_medium_back.rb +58 -0
- data/lib/ttt/board.rb +37 -0
- data/lib/ttt/config_helper.rb +53 -0
- data/lib/ttt/config_options.rb +27 -0
- data/lib/ttt/context.rb +214 -0
- data/lib/ttt/four_by_four.rb +62 -0
- data/lib/ttt/game.rb +94 -0
- data/lib/ttt/game_history.rb +37 -0
- data/lib/ttt/game_interactor.rb +126 -0
- data/lib/ttt/human.rb +12 -0
- data/lib/ttt/interfaces/cli/lib/cli/board_selection.rb +34 -0
- data/lib/ttt/interfaces/cli/lib/cli/cli_game.rb +186 -0
- data/lib/ttt/interfaces/cli/lib/cli/cli_presenter.rb +216 -0
- data/lib/ttt/interfaces/cli/lib/cli/clio.rb +17 -0
- data/lib/ttt/interfaces/cli/lib/cli/play_again.rb +38 -0
- data/lib/ttt/interfaces/cli/lib/cli/player_selection.rb +43 -0
- data/lib/ttt/interfaces/cli/lib/cli/selection.rb +8 -0
- data/lib/ttt/interfaces/cli/lib/cli/walk_history.rb +48 -0
- data/lib/ttt/interfaces/cli/spec/cli/board_selection_spec.rb +29 -0
- data/lib/ttt/interfaces/cli/spec/cli/cli_game_spec.rb +376 -0
- data/lib/ttt/interfaces/cli/spec/cli/cli_presenter_spec.rb +147 -0
- data/lib/ttt/interfaces/cli/spec/cli/play_again_spec.rb +39 -0
- data/lib/ttt/interfaces/cli/spec/cli/player_selection_spec.rb +62 -0
- data/lib/ttt/interfaces/cli/spec/cli/walk_history_spec.rb +115 -0
- data/lib/ttt/interfaces/cli/spec/spec_helper.rb +14 -0
- data/lib/ttt/interfaces/limelight/four_by_four/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/four_by_four/styles.rb +74 -0
- data/lib/ttt/interfaces/limelight/four_by_four_finished/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/four_by_four_finished/styles.rb +74 -0
- data/lib/ttt/interfaces/limelight/game_list/players/load_button.rb +10 -0
- data/lib/ttt/interfaces/limelight/game_list/props.rb +17 -0
- data/lib/ttt/interfaces/limelight/game_list/styles.rb +8 -0
- data/lib/ttt/interfaces/limelight/main_menu/players/exit_ttt.rb +3 -0
- data/lib/ttt/interfaces/limelight/main_menu/players/load_game.rb +3 -0
- data/lib/ttt/interfaces/limelight/main_menu/players/new_game.rb +3 -0
- data/lib/ttt/interfaces/limelight/main_menu/props.rb +17 -0
- data/lib/ttt/interfaces/limelight/new_game/players/board_type.rb +1 -0
- data/lib/ttt/interfaces/limelight/new_game/players/new_game.rb +5 -0
- data/lib/ttt/interfaces/limelight/new_game/players/player_type.rb +1 -0
- data/lib/ttt/interfaces/limelight/new_game/players/setup_button.rb +21 -0
- data/lib/ttt/interfaces/limelight/new_game/props.rb +21 -0
- data/lib/ttt/interfaces/limelight/new_game/styles.rb +23 -0
- data/lib/ttt/interfaces/limelight/partials/board_partial.rb +14 -0
- data/lib/ttt/interfaces/limelight/partials/menu_button_partial.rb +5 -0
- data/lib/ttt/interfaces/limelight/partials/move_history_partial.rb +6 -0
- data/lib/ttt/interfaces/limelight/partials/title_history_partial.rb +10 -0
- data/lib/ttt/interfaces/limelight/players/board.rb +3 -0
- data/lib/ttt/interfaces/limelight/players/game.rb +4 -0
- data/lib/ttt/interfaces/limelight/players/generic_move_history.rb +5 -0
- data/lib/ttt/interfaces/limelight/players/generic_player.rb +8 -0
- data/lib/ttt/interfaces/limelight/players/left_button.rb +3 -0
- data/lib/ttt/interfaces/limelight/players/main_menu.rb +3 -0
- data/lib/ttt/interfaces/limelight/players/right_button.rb +3 -0
- data/lib/ttt/interfaces/limelight/playscripts/game_playscript.rb +169 -0
- data/lib/ttt/interfaces/limelight/production.rb +14 -0
- data/lib/ttt/interfaces/limelight/spec/game_playscript_spec.rb +218 -0
- data/lib/ttt/interfaces/limelight/spec/main_menu/main_menu_spec.rb +38 -0
- data/lib/ttt/interfaces/limelight/spec/new_game/new_game_spec.rb +45 -0
- data/lib/ttt/interfaces/limelight/spec/spec_helper.rb +8 -0
- data/lib/ttt/interfaces/limelight/stages.rb +6 -0
- data/lib/ttt/interfaces/limelight/styles.rb +119 -0
- data/lib/ttt/interfaces/limelight/three_by_three/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/three_by_three/styles.rb +39 -0
- data/lib/ttt/interfaces/limelight/three_by_three_by_three/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/three_by_three_by_three/styles.rb +119 -0
- data/lib/ttt/interfaces/limelight/three_by_three_by_three_finished/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/three_by_three_by_three_finished/styles.rb +119 -0
- data/lib/ttt/interfaces/limelight/three_by_three_finished/props.rb +1 -0
- data/lib/ttt/interfaces/limelight/three_by_three_finished/styles.rb +39 -0
- data/lib/ttt/interfaces/rails/app/controllers/application_controller.rb +3 -0
- data/lib/ttt/interfaces/rails/app/controllers/ttt_games_controller.rb +86 -0
- data/lib/ttt/interfaces/rails/app/helpers/application_helper.rb +2 -0
- data/lib/ttt/interfaces/rails/app/models/ttt_game.rb +34 -0
- data/lib/ttt/interfaces/rails/app/presenters/web_game_presenter.rb +159 -0
- data/lib/ttt/interfaces/rails/autotest/discover.rb +1 -0
- data/lib/ttt/interfaces/rails/config/application.rb +67 -0
- data/lib/ttt/interfaces/rails/config/boot.rb +6 -0
- data/lib/ttt/interfaces/rails/config/environment.rb +5 -0
- data/lib/ttt/interfaces/rails/config/environments/development.rb +37 -0
- data/lib/ttt/interfaces/rails/config/environments/production.rb +67 -0
- data/lib/ttt/interfaces/rails/config/environments/test.rb +37 -0
- data/lib/ttt/interfaces/rails/config/initializers/backtrace_silencers.rb +7 -0
- data/lib/ttt/interfaces/rails/config/initializers/inflections.rb +15 -0
- data/lib/ttt/interfaces/rails/config/initializers/mime_types.rb +5 -0
- data/lib/ttt/interfaces/rails/config/initializers/secret_token.rb +7 -0
- data/lib/ttt/interfaces/rails/config/initializers/session_store.rb +8 -0
- data/lib/ttt/interfaces/rails/config/initializers/wrap_parameters.rb +14 -0
- data/lib/ttt/interfaces/rails/config/routes.rb +49 -0
- data/lib/ttt/interfaces/rails/db/schema.rb +28 -0
- data/lib/ttt/interfaces/rails/db/seeds.rb +7 -0
- data/lib/ttt/interfaces/rails/spec/controllers/ttt_games_controller_spec.rb +211 -0
- data/lib/ttt/interfaces/rails/spec/models/ttt_game_spec.rb +76 -0
- data/lib/ttt/interfaces/rails/spec/presenters/web_game_presenter_spec.rb +52 -0
- data/lib/ttt/interfaces/rails/spec/spec_helper.rb +13 -0
- data/lib/ttt/interfaces/web_interface/html_generator.rb +76 -0
- data/lib/ttt/interfaces/web_interface/web_game_presenter.rb +0 -0
- data/lib/ttt/minimax.rb +46 -0
- data/lib/ttt/move_history.rb +10 -0
- data/lib/ttt/move_traverser.rb +49 -0
- data/lib/ttt/player.rb +15 -0
- data/lib/ttt/riak_db.rb +53 -0
- data/lib/ttt/setup.rb +59 -0
- data/lib/ttt/three_by_three.rb +35 -0
- data/lib/ttt/three_by_three_by_three.rb +37 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/ttt/ai_easy_spec.rb +15 -0
- data/spec/ttt/ai_hard_spec.rb +76 -0
- data/spec/ttt/ai_medium_spec.rb +65 -0
- data/spec/ttt/ai_spec.rb +50 -0
- data/spec/ttt/board_spec.rb +96 -0
- data/spec/ttt/config_helper_spec.rb +54 -0
- data/spec/ttt/context_spec.rb +398 -0
- data/spec/ttt/four_by_four_spec.rb +112 -0
- data/spec/ttt/game_history_spec.rb +41 -0
- data/spec/ttt/game_interactor_spec.rb +197 -0
- data/spec/ttt/game_spec.rb +246 -0
- data/spec/ttt/human_spec.rb +18 -0
- data/spec/ttt/move_history_spec.rb +13 -0
- data/spec/ttt/move_traverser_spec.rb +75 -0
- data/spec/ttt/player_spec.rb +13 -0
- data/spec/ttt/riak_db_spec.rb +64 -0
- data/spec/ttt/setup_spec.rb +63 -0
- data/spec/ttt/three_by_three_by_three_spec.rb +130 -0
- data/spec/ttt/three_by_three_spec.rb +110 -0
- metadata +238 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module TTT
|
|
2
|
+
describe Human do
|
|
3
|
+
let(:human) { Human.new(side: "x") }
|
|
4
|
+
let(:game) { Game.new(view: view, board: board) }
|
|
5
|
+
|
|
6
|
+
describe "#no_gui?" do
|
|
7
|
+
it "returns false" do
|
|
8
|
+
human.no_gui?.should == false
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "#prompt" do
|
|
13
|
+
it "returns 'Player thinking'" do
|
|
14
|
+
human.prompt.should == "Enter move:"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module TTT
|
|
4
|
+
describe MoveHistory do
|
|
5
|
+
describe "#new" do
|
|
6
|
+
it "returns a new TTT::MoveHistory object with side and move attributes" do
|
|
7
|
+
move_history = described_class.new(side: "x", move: 0)
|
|
8
|
+
move_history.side.should == "x"
|
|
9
|
+
move_history.move.should == 0
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module TTT
|
|
4
|
+
describe MoveTraverser do
|
|
5
|
+
let(:board) { ThreeByThree.new }
|
|
6
|
+
let(:game_history) { GameHistory.new }
|
|
7
|
+
let(:traverser) { game_history.move_traverser }
|
|
8
|
+
|
|
9
|
+
context do
|
|
10
|
+
before(:each) do
|
|
11
|
+
game_history.record_move(0, 'x')
|
|
12
|
+
game_history.record_move(1, 'o')
|
|
13
|
+
game_history.record_move(2, 'x')
|
|
14
|
+
game_history.record_move(3, 'o')
|
|
15
|
+
game_history.record_move(4, 'x')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "#adjust_move_index" do
|
|
19
|
+
|
|
20
|
+
it "moves backward in the move history by 1 when its invoked with -1" do
|
|
21
|
+
traverser.adjust_move_index(-1)
|
|
22
|
+
traverser.move_index.should == 4
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "moves forward in the move history by 1 when its invoked with 1" do
|
|
26
|
+
traverser.move_index = 4
|
|
27
|
+
traverser.adjust_move_index(1)
|
|
28
|
+
traverser.move_index.should == 5
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "moves backward in the move history by 2 when its invoked with -2" do
|
|
32
|
+
traverser.adjust_move_index(-2)
|
|
33
|
+
traverser.move_index.should == 3
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "moves forward in the move history by 2 when its invoked with 2" do
|
|
37
|
+
traverser.move_index = 2
|
|
38
|
+
traverser.adjust_move_index(2)
|
|
39
|
+
traverser.move_index.should == 4
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "cannot move backwards beyond move index 0" do
|
|
43
|
+
traverser.move_index = 0
|
|
44
|
+
traverser.adjust_move_index(-1)
|
|
45
|
+
traverser.move_index.should == 0
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "cannot move beyond the max length" do
|
|
49
|
+
traverser.move_index = traverser.max_length
|
|
50
|
+
traverser.adjust_move_index(100)
|
|
51
|
+
traverser.move_index.should == traverser.max_length
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe "#history_board_builder" do
|
|
56
|
+
it "returns a board array representing the moves made up to move_number in history" do
|
|
57
|
+
traverser.history_board_builder(board, 3).should == ['x', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ']
|
|
58
|
+
board.board = Array.new(9, ' ')
|
|
59
|
+
traverser.history_board_builder(board, 5).should == ['x', 'o', 'x', 'o', 'x', ' ', ' ', ' ', ' ']
|
|
60
|
+
board.board = Array.new(9, ' ')
|
|
61
|
+
traverser.history_board_builder(board, 0).should == Array.new(9, ' ')
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "does not alter the original board" do
|
|
65
|
+
traverser.history_board_builder(board, 3).should_not == board.board
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "does not alter the original game history" do
|
|
69
|
+
original_history = traverser.game_history.history
|
|
70
|
+
traverser.game_history.history.should == original_history
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module TTT
|
|
4
|
+
describe RiakDB do
|
|
5
|
+
Riak.disable_list_keys_warnings = true
|
|
6
|
+
let(:setup) { Setup.new }
|
|
7
|
+
let(:players) { setup.players }
|
|
8
|
+
let(:boards) { setup.boards }
|
|
9
|
+
let(:game) { setup.new_game(player1: players.first, player2: players.first, board: boards.first) }
|
|
10
|
+
let(:riak) { setup.new_db }
|
|
11
|
+
let(:bucket) { riak.bucket }
|
|
12
|
+
|
|
13
|
+
describe "#new" do
|
|
14
|
+
it "establishes a connection with the Riak cluster" do
|
|
15
|
+
riak.client.should_not be_nil
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "#add_game" do
|
|
20
|
+
it "adds a game to the game_list bucket" do
|
|
21
|
+
@id = riak.add_game(game)
|
|
22
|
+
riak.client[bucket].get(@id).data[:game].should_not == nil
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe "#game_list" do
|
|
27
|
+
it "returns a list of games available in the specified game bucket" do
|
|
28
|
+
num_keys_in_db = riak.client[bucket].keys.length
|
|
29
|
+
riak.game_list.length.should == num_keys_in_db
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe "#get_game" do
|
|
34
|
+
it "returns a game object from the Riak datastore" do
|
|
35
|
+
cur_id = riak.cur_id
|
|
36
|
+
riak.get_game(cur_id).class.should == Game
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "returns nil if there is no game at the specified id" do
|
|
40
|
+
riak.get_game(10000000000000000000).should == nil
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "#save_game" do
|
|
45
|
+
it "saves an existing game to the Riak datastore" do
|
|
46
|
+
cur_id = riak.cur_id
|
|
47
|
+
new_game = riak.get_game(cur_id)
|
|
48
|
+
new_game.player1.side = "test"
|
|
49
|
+
riak.save_game(cur_id, new_game)
|
|
50
|
+
after_save = riak.get_game(cur_id)
|
|
51
|
+
new_game.player1.side.should == after_save.player1.side
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe "#delete_game" do
|
|
56
|
+
it "deletes an existing game from the Riak datastore" do
|
|
57
|
+
id = riak.add_game(game)
|
|
58
|
+
riak.get_game(id).class.should == Game
|
|
59
|
+
riak.delete_game(id)
|
|
60
|
+
riak.client[bucket].get_or_new(id).data.should == nil
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'ttt/config_options'
|
|
3
|
+
|
|
4
|
+
module TTT
|
|
5
|
+
describe Setup do
|
|
6
|
+
let(:setup) { Setup.new }
|
|
7
|
+
|
|
8
|
+
describe "#new_game" do
|
|
9
|
+
it "returns a new game object after instantiating the players, board, db and game history" do
|
|
10
|
+
game = setup.new_game(player1: "Human", player2: "AI Easy", board: "3x3")
|
|
11
|
+
game.player1.class.should == Human
|
|
12
|
+
game.player2.class.should == AIEasy
|
|
13
|
+
game.player1.side.should == "x"
|
|
14
|
+
game.player2.side.should == "o"
|
|
15
|
+
game.board.class.should == ThreeByThree
|
|
16
|
+
game.history.should_not be_nil
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe "#new_db" do
|
|
21
|
+
it "returns a new db object" do
|
|
22
|
+
db = setup.new_db
|
|
23
|
+
db.should respond_to(:client)
|
|
24
|
+
db.should respond_to(:bucket)
|
|
25
|
+
db.should respond_to(:cur_id)
|
|
26
|
+
db.should respond_to(:save_game)
|
|
27
|
+
db.should respond_to(:get_game)
|
|
28
|
+
db.should respond_to(:add_game)
|
|
29
|
+
db.should respond_to(:game_list)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe "#players" do
|
|
34
|
+
it "returns a list of player types supported by the library" do
|
|
35
|
+
setup.players.should == ConfigOptions::HUMAN_READABLE_PLAYERS
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "#boards" do
|
|
40
|
+
it "returns a list of board types supported by the library" do
|
|
41
|
+
setup.boards.should == ConfigOptions::HUMAN_READABLE_BOARDS
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "#db" do
|
|
46
|
+
it "returns the db const specified in the config options file" do
|
|
47
|
+
setup.db.should == ConfigOptions::DB
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe "#interactor" do
|
|
52
|
+
it "returns the interactor const specified in the config options file" do
|
|
53
|
+
setup.interactor.should == ConfigOptions::INTERACTOR
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "#new_interactor" do
|
|
58
|
+
it "returns an instance of a game interactor" do
|
|
59
|
+
setup.new_interactor.class.should == GameInteractor
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module TTT
|
|
4
|
+
describe ThreeByThreeByThree do
|
|
5
|
+
let(:board) { ThreeByThreeByThree.new }
|
|
6
|
+
|
|
7
|
+
describe "#initialize" do
|
|
8
|
+
it "board has length 27" do
|
|
9
|
+
board[].length.should == 27
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "#update" do
|
|
14
|
+
it "updates the game board after move is received" do
|
|
15
|
+
board.update(1, "x")
|
|
16
|
+
board[].should == [" ", "x", " ", " ", " ", " ", " ", " ", " ",
|
|
17
|
+
" ", " ", " ", " ", " ", " ", " ", " ", " ",
|
|
18
|
+
" ", " ", " ", " ", " ", " ", " ", " ", " "]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "#empty?" do
|
|
23
|
+
it "returns true when board is empty" do
|
|
24
|
+
board.empty?.should == true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "returns false when board is not empty" do
|
|
28
|
+
board.update(1, "x")
|
|
29
|
+
board.empty?.should == false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe "#full?" do
|
|
34
|
+
it "returns true when board is full" do
|
|
35
|
+
27.times do |n|
|
|
36
|
+
board.update(n, "o")
|
|
37
|
+
end
|
|
38
|
+
board.full?.should == true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "returns false when board isn't full" do
|
|
42
|
+
board.update(1, "x")
|
|
43
|
+
board.full?.should == false
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe "#free?" do
|
|
48
|
+
it "returns false when board is occupied at a given cell" do
|
|
49
|
+
board.update(1, "x")
|
|
50
|
+
board.free?(1).should == false
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "returns true when board is not occupied at a given cell" do
|
|
54
|
+
board.free?(0).should == true
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe "#draw_game?" do
|
|
59
|
+
it "returns false when board is not full" do
|
|
60
|
+
board.draw_game?.should == false
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "returns true when board is full" do
|
|
64
|
+
board[] = ["a", "b", "c", "d", "e", "f", "g", "h", "i",
|
|
65
|
+
"j", "k", "l", "m", "n", "o", "p", "q", "r",
|
|
66
|
+
"s", "t", "u", "v", "w", "x", "y", "z", "a"]
|
|
67
|
+
board.draw_game?.should == true
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe "#winner?" do
|
|
72
|
+
it "returns false when the board has no winner" do
|
|
73
|
+
board.winner?.should == false
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "returns true when the board has a same-ply winner" do
|
|
77
|
+
board[] = ["x", "x", "x", "o", " ", "o", " ", " ", " ",
|
|
78
|
+
" ", " ", " ", " ", " ", " ", " ", " ", " ",
|
|
79
|
+
" ", " ", " ", " ", " ", " ", " ", " ", " "]
|
|
80
|
+
board.winner?.should == true
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "returns true when the board has a multi-ply regular winner" do
|
|
84
|
+
board[] = ["x", " ", " ", " ", " ", " ", " ", " ", " ",
|
|
85
|
+
"x", " ", " ", " ", " ", " ", " ", " ", " ",
|
|
86
|
+
"x", " ", " ", " ", " ", " ", " ", " ", " "]
|
|
87
|
+
board.winner?.should == true
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "returns true when the board has a multi-ply diagonal winner" do
|
|
91
|
+
board[] = ["x", " ", " ", " ", " ", " ", " ", " ", " ",
|
|
92
|
+
" ", " ", " ", " ", "x", " ", " ", " ", " ",
|
|
93
|
+
" ", " ", " ", " ", " ", " ", " ", " ", "x"]
|
|
94
|
+
board.winner?.should == true
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "returns true when the board has a multi-ply horizontal stacked winner" do
|
|
98
|
+
board[] = ["x", " ", " ", " ", " ", " ", " ", " ", " ",
|
|
99
|
+
" ", "x", " ", " ", " ", " ", " ", " ", " ",
|
|
100
|
+
" ", " ", "x", " ", " ", " ", " ", " ", " "]
|
|
101
|
+
board.winner?.should == true
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "returns true when the board has a multi-ply horizontal stacked winner" do
|
|
105
|
+
board[] = [" ", " ", " ", " ", " ", " ", "x", " ", " ",
|
|
106
|
+
" ", " ", " ", "x", " ", " ", " ", " ", " ",
|
|
107
|
+
"x", " ", " ", " ", " ", " ", " ", " ", " "]
|
|
108
|
+
board.winner?.should == true
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe "#finished?" do
|
|
113
|
+
it "returns false when board is not full, no win, or no draw" do
|
|
114
|
+
board.finished?.should == false
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "returns true when board has a win" do
|
|
118
|
+
board.update(0, 'x')
|
|
119
|
+
board.update(1, 'x')
|
|
120
|
+
board.update(2, 'x')
|
|
121
|
+
board.finished?.should == true
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "returns true when board has a draw" do
|
|
125
|
+
board[] = ["x", "o", "x", "x", "o", "o", "o", "x", "o"]
|
|
126
|
+
board.finished?.should == true
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module TTT
|
|
4
|
+
describe ThreeByThree do
|
|
5
|
+
let(:board) { ThreeByThree.new }
|
|
6
|
+
|
|
7
|
+
describe "#initialize" do
|
|
8
|
+
it "board has length 9" do
|
|
9
|
+
board[].length.should == 9
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "#update" do
|
|
14
|
+
it "updates the game board after move is received" do
|
|
15
|
+
board.update(1, "x")
|
|
16
|
+
board[].should == [" ", "x", " ", " ", " ", " ", " ", " ", " "]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe "#empty?" do
|
|
21
|
+
it "returns true when board is empty" do
|
|
22
|
+
board.empty?.should == true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "returns false when board is not empty" do
|
|
26
|
+
board.update(1, "x")
|
|
27
|
+
board.empty?.should == false
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe "#full?" do
|
|
32
|
+
it "returns true when board is full" do
|
|
33
|
+
9.times do |n|
|
|
34
|
+
board.update(n, "o")
|
|
35
|
+
end
|
|
36
|
+
board.full?.should == true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "returns false when board isn't full" do
|
|
40
|
+
board.update(1, "x")
|
|
41
|
+
board.full?.should == false
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "#free?" do
|
|
46
|
+
it "returns false when board is occupied at a given cell" do
|
|
47
|
+
board.update(1, "x")
|
|
48
|
+
board.free?(1).should == false
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "returns true when board is not occupied at a given cell" do
|
|
52
|
+
board.free?(0).should == true
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe "#draw_game?" do
|
|
57
|
+
it "returns false when board is not full" do
|
|
58
|
+
board.draw_game?.should == false
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "returns true when board is full" do
|
|
62
|
+
board[] = ["x", "o", "x", "x", "o", "o", "o", "x", "o"]
|
|
63
|
+
board.draw_game?.should == true
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe "#winner?" do
|
|
68
|
+
it "returns false when the board has no winner" do
|
|
69
|
+
board.winner?.should == false
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "returns true when the board has a winner" do
|
|
73
|
+
board[] = ["x", "x", "x", "o", " ", "o", " ", " ", " "]
|
|
74
|
+
board.winner?.should == true
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "returns true when the board has a block winner" do
|
|
78
|
+
board[] = ["x", "x", "o", "x", "x", "o", " ", " ", " "]
|
|
79
|
+
board.winner?.should == true
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe "#block_winner?" do
|
|
84
|
+
it "returns true when the board has a block winner" do
|
|
85
|
+
board[] = ["x", "x", "o", "x", "x", "o", " ", " ", " "]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "returns false when the board has no block winner" do
|
|
89
|
+
board[] = ["x", "o", " ", " ", " ", " ", " ", " ", " "]
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
describe "#finished?" do
|
|
93
|
+
it "returns false when board is not full, no win, or no draw" do
|
|
94
|
+
board.finished?.should == false
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "returns true when board has a win" do
|
|
98
|
+
board.update(0, 'x')
|
|
99
|
+
board.update(1, 'x')
|
|
100
|
+
board.update(2, 'x')
|
|
101
|
+
board.finished?.should == true
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "returns true when board has a draw" do
|
|
105
|
+
board[] = ["x", "o", "x", "x", "o", "o", "o", "x", "o"]
|
|
106
|
+
board.finished?.should == true
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|