x_and_os 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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +10 -0
- data/README.md +47 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/bin/x_and_os +4 -0
- data/cla/tic_tac_toe/application.rb +88 -0
- data/cla/tic_tac_toe/computer_player.rb +21 -0
- data/cla/tic_tac_toe/display.rb +56 -0
- data/cla/tic_tac_toe/game_manager.rb +72 -0
- data/cla/tic_tac_toe/human_player.rb +18 -0
- data/cla/tic_tac_toe/nameable.rb +16 -0
- data/cla/tic_tac_toe/ui.rb +13 -0
- data/cla/tic_tac_toe.rb +1 -0
- data/lib/x_and_os/board.rb +103 -0
- data/lib/x_and_os/game.rb +28 -0
- data/lib/x_and_os/game_master.rb +139 -0
- data/lib/x_and_os/version.rb +3 -0
- data/lib/x_and_os.rb +6 -0
- data/x_and_os.gemspec +22 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0d992babe9dd2b0f2ccde30604920cf3e8cc0f72
|
4
|
+
data.tar.gz: fbe6d30630b944476bc9a32e309970ec0745958f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8ad4a9fb34a1f47d4b610b2a7fee71524cea7c6cad5028c94f713b5151d59f0ae441212c1047f1306101c3ad0c8ae9e436069e9991f9fa00f63d1b406424468f
|
7
|
+
data.tar.gz: 2594b09d691adcb49bd15830ef2309441f63aa1e361e60315e4f448ac86fe2080dc1df6912a612af04c6634841595253e4644be1dec79129d33bc82d0bf01945
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# XAndOs
|
2
|
+
|
3
|
+
XAndOs provides the basic structure and game logic to easily create the game Tic Tac Toe.
|
4
|
+
It also comes with a mini CLA to play Tic Tac Toe in the command line.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'x_and_os'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install x_and_os
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
### Game
|
25
|
+
TODO
|
26
|
+
### Board
|
27
|
+
TODO
|
28
|
+
### Game Mastery
|
29
|
+
TODO
|
30
|
+
|
31
|
+
### Command Line App
|
32
|
+
You can use XAndOs to play Tic Tac Toe in the command line
|
33
|
+
`x_and_os`
|
34
|
+
|
35
|
+
## Development
|
36
|
+
|
37
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
38
|
+
|
39
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
1. Fork it ( https://github.com/[my-github-username]/x_and_os/fork )
|
44
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
45
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
46
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
47
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "x_and_os"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/bin/x_and_os
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
require_relative './game_manager'
|
2
|
+
require_relative './ui'
|
3
|
+
|
4
|
+
module TicTacToe
|
5
|
+
class Application
|
6
|
+
def initialize(argv)
|
7
|
+
start_app
|
8
|
+
end
|
9
|
+
|
10
|
+
def start_app
|
11
|
+
UI.output
|
12
|
+
UI.output 'Welcome to TicTacToe'
|
13
|
+
UI.output 'Quick Game?'
|
14
|
+
settings unless UI.receive =~ /^y/i
|
15
|
+
loop do
|
16
|
+
play
|
17
|
+
UI.output
|
18
|
+
UI.output 'Play again?'
|
19
|
+
break unless UI.receive =~ /^y/i
|
20
|
+
UI.output
|
21
|
+
UI.output 'Change settings?'
|
22
|
+
settings if UI.receive =~ /^y/i
|
23
|
+
end
|
24
|
+
|
25
|
+
UI.output
|
26
|
+
UI.output 'Thank you for playing.'
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def settings
|
32
|
+
choose_player
|
33
|
+
choose_board_size
|
34
|
+
end
|
35
|
+
|
36
|
+
def choose_player
|
37
|
+
UI.output
|
38
|
+
UI.output 'Choose Player : '
|
39
|
+
UI.output ' p: player'
|
40
|
+
UI.output ' c: computer'
|
41
|
+
UI.output
|
42
|
+
UI.output 'Player 1'
|
43
|
+
@player_one = player_type(UI.receive)
|
44
|
+
UI.output
|
45
|
+
UI.output 'Player 2'
|
46
|
+
@player_two = player_type(UI.receive)
|
47
|
+
UI.output
|
48
|
+
end
|
49
|
+
|
50
|
+
def choose_board_size
|
51
|
+
UI.output
|
52
|
+
UI.output 'Enter Board Size :'
|
53
|
+
UI.output ' 3: 3x3'
|
54
|
+
UI.output ' 4: 4x4'
|
55
|
+
UI.output ' N: NxN'
|
56
|
+
UI.output
|
57
|
+
size = UI.receive
|
58
|
+
@board_size = (size.to_i >= 1) ? size : 3
|
59
|
+
UI.output
|
60
|
+
end
|
61
|
+
|
62
|
+
def play
|
63
|
+
GameManager.new(player_one, player_two, board_size).play
|
64
|
+
end
|
65
|
+
|
66
|
+
def player_one
|
67
|
+
@player_one ||= HumanPlayer
|
68
|
+
end
|
69
|
+
|
70
|
+
def player_two
|
71
|
+
@player_two ||= ComputerPlayer
|
72
|
+
end
|
73
|
+
|
74
|
+
def board_size
|
75
|
+
@board_size ||= 3
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def player_type(player)
|
80
|
+
if player =~ /^p/i
|
81
|
+
HumanPlayer
|
82
|
+
elsif player =~ /^c/i
|
83
|
+
ComputerPlayer
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'x_and_os'
|
2
|
+
require_relative './nameable'
|
3
|
+
|
4
|
+
module TicTacToe
|
5
|
+
class ComputerPlayer
|
6
|
+
include Nameable
|
7
|
+
|
8
|
+
attr_reader :board, :marker
|
9
|
+
|
10
|
+
def initialize(args)
|
11
|
+
@board = args[:board]
|
12
|
+
@marker = args[:marker]
|
13
|
+
@game_master = XAndOs::GameMaster.new(board: board, marker: marker)
|
14
|
+
end
|
15
|
+
|
16
|
+
def move
|
17
|
+
@game_master.best_move
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative './ui'
|
2
|
+
|
3
|
+
module TicTacToe
|
4
|
+
module Display
|
5
|
+
|
6
|
+
def self.game_board(board)
|
7
|
+
height = board.length
|
8
|
+
width = board.first.length
|
9
|
+
padding = (width * height).to_s.length
|
10
|
+
|
11
|
+
UI.output
|
12
|
+
board.each_with_index do |row, row_index|
|
13
|
+
row_with_move_numbers = blank_cells_to_numbers(row, row_index)
|
14
|
+
|
15
|
+
padded_row = add_padding_to_row(row_with_move_numbers, padding)
|
16
|
+
|
17
|
+
UI.output "\t " + padded_row.join(' | ')
|
18
|
+
UI.output divider(width, padding) unless row_index + 1 >= height
|
19
|
+
end
|
20
|
+
|
21
|
+
UI.output
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def self.divider(width, padding)
|
27
|
+
dividers = []
|
28
|
+
width.times do
|
29
|
+
dividers << ('-' * padding)
|
30
|
+
end
|
31
|
+
|
32
|
+
"\t #{dividers.join('-+-')}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.add_padding_to_row(row, padding)
|
36
|
+
row.map do |cell|
|
37
|
+
format_string = "%-#{padding}s"
|
38
|
+
format_string % cell.to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.blank_cells_to_numbers(row, row_index)
|
43
|
+
previous_cells_count = row.length * row_index
|
44
|
+
|
45
|
+
row.map.with_index do |cell, column_index|
|
46
|
+
column_number = column_index + 1
|
47
|
+
not_blank(cell) ? cell : previous_cells_count + column_number
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.not_blank(str)
|
52
|
+
/\S+/ =~ str.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'x_and_os'
|
2
|
+
require_relative './human_player'
|
3
|
+
require_relative './computer_player'
|
4
|
+
require_relative './display'
|
5
|
+
require_relative './ui'
|
6
|
+
|
7
|
+
module TicTacToe
|
8
|
+
class GameManager
|
9
|
+
include Display
|
10
|
+
|
11
|
+
attr_reader :player1, :player2, :turns
|
12
|
+
|
13
|
+
def initialize(player_1_class = HumanPlayer, player_2_class = ComputerPlayer, board_size = 3)
|
14
|
+
@game = XAndOs::Game.new(rows: board_size, columns: board_size)
|
15
|
+
@player1 = player_1_class.new(marker: 'x', board: board)
|
16
|
+
@player2 = player_2_class.new(marker: 'o', board: board)
|
17
|
+
@turns = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def current_player
|
21
|
+
turns.even? ? player1 : player2
|
22
|
+
end
|
23
|
+
|
24
|
+
def last_player
|
25
|
+
turns.odd? ? player1 : player2
|
26
|
+
end
|
27
|
+
|
28
|
+
def board
|
29
|
+
@game.board
|
30
|
+
end
|
31
|
+
|
32
|
+
def play
|
33
|
+
print_intructions
|
34
|
+
loop do
|
35
|
+
if @game.winner?
|
36
|
+
Display.game_board(board.grid)
|
37
|
+
UI.output "#{last_player.name} wins!!"
|
38
|
+
break
|
39
|
+
elsif @game.draw?
|
40
|
+
Display.game_board(board.grid)
|
41
|
+
UI.output "It's a draw!!"
|
42
|
+
break
|
43
|
+
else
|
44
|
+
move
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def move
|
50
|
+
player = current_player
|
51
|
+
|
52
|
+
Display.game_board(board.grid)
|
53
|
+
UI.output "#{player.name}'s turn."
|
54
|
+
|
55
|
+
cell = player.move
|
56
|
+
|
57
|
+
until @game.add_move(cell, player.marker)
|
58
|
+
UI.output "\nSorry, invalid entry. Please try again\n\n"
|
59
|
+
cell = player.move
|
60
|
+
end
|
61
|
+
|
62
|
+
@turns += 1
|
63
|
+
end
|
64
|
+
|
65
|
+
def print_intructions
|
66
|
+
UI.output 'Choose a number between 1 and 9 to mark space in the grid'
|
67
|
+
UI.output 'Place 3 marks in a horizontal, vertical, or diagonal row to win.'
|
68
|
+
UI.output
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative './nameable'
|
2
|
+
require_relative './ui'
|
3
|
+
|
4
|
+
module TicTacToe
|
5
|
+
class HumanPlayer
|
6
|
+
include Nameable
|
7
|
+
|
8
|
+
attr_reader :board, :marker
|
9
|
+
|
10
|
+
def initialize(args = {})
|
11
|
+
@marker = args[:marker]
|
12
|
+
end
|
13
|
+
|
14
|
+
def move
|
15
|
+
move = UI.receive
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/cla/tic_tac_toe.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative './tic_tac_toe/application'
|
@@ -0,0 +1,103 @@
|
|
1
|
+
class XAndOs::Board
|
2
|
+
attr_reader :grid, :default_value, :rows, :columns
|
3
|
+
|
4
|
+
def initialize(rows = 3, columns = 3, default_value = ' ')
|
5
|
+
@default_value = default_value
|
6
|
+
@rows = rows.to_i
|
7
|
+
@columns = columns.to_i
|
8
|
+
@grid = new_grid
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_cell(cell_num, value)
|
12
|
+
row, column = human_to_grid(cell_num)
|
13
|
+
if grid[row][column] == default_value
|
14
|
+
grid[row][column] = value
|
15
|
+
else
|
16
|
+
false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_cell(cell_num)
|
21
|
+
row, column = human_to_grid(cell_num)
|
22
|
+
grid[row][column]
|
23
|
+
end
|
24
|
+
|
25
|
+
def diagonal_rows
|
26
|
+
left_to_right = (0...rows).map { |i| grid[i][i] }
|
27
|
+
right_to_left = (0...rows).map { |i| grid[i][columns - (i + 1)] }
|
28
|
+
[left_to_right, right_to_left]
|
29
|
+
end
|
30
|
+
|
31
|
+
def vertical_rows
|
32
|
+
grid.transpose
|
33
|
+
end
|
34
|
+
|
35
|
+
def horizontal_rows
|
36
|
+
grid
|
37
|
+
end
|
38
|
+
|
39
|
+
def all_rows
|
40
|
+
diagonal_rows + vertical_rows + horizontal_rows
|
41
|
+
end
|
42
|
+
|
43
|
+
def complete_rows
|
44
|
+
all_rows.reject do |row|
|
45
|
+
uniq_values = row.uniq
|
46
|
+
uniq_values.include?(default_value) || uniq_values.count > 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def all_lines
|
51
|
+
temp_board = self.class.new(rows, columns)
|
52
|
+
num_of_cells = rows * columns
|
53
|
+
|
54
|
+
(1..num_of_cells).each do |i|
|
55
|
+
temp_board.set_cell(i,i)
|
56
|
+
end
|
57
|
+
|
58
|
+
temp_board.all_rows
|
59
|
+
end
|
60
|
+
|
61
|
+
def count_cells
|
62
|
+
@total_cells ||= rows * columns
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_cells value
|
66
|
+
grid.flatten.map.with_index { |val, i| i + 1 if val == value }.compact
|
67
|
+
end
|
68
|
+
|
69
|
+
def free_cells
|
70
|
+
find_cells default_value
|
71
|
+
end
|
72
|
+
|
73
|
+
def cell_locations
|
74
|
+
store = Hash.new {|h,k| h[k] = [] }
|
75
|
+
|
76
|
+
grid.flatten.map.with_index.inject(store) do |store, (cell, index)|
|
77
|
+
if cell != default_value
|
78
|
+
store[cell].push(index + 1)
|
79
|
+
end
|
80
|
+
store
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def human_to_grid(cell_num)
|
87
|
+
cell_num = cell_num.to_i - 1
|
88
|
+
[row_number(cell_num), column_number(cell_num)]
|
89
|
+
end
|
90
|
+
|
91
|
+
def row_number(cell_num)
|
92
|
+
cell_num / columns
|
93
|
+
end
|
94
|
+
|
95
|
+
def column_number(cell_num)
|
96
|
+
cell_num - (row_number(cell_num) * columns)
|
97
|
+
end
|
98
|
+
|
99
|
+
def new_grid
|
100
|
+
Array.new(rows) { Array.new(columns, default_value) }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class XAndOs::Game
|
2
|
+
|
3
|
+
attr_reader :board
|
4
|
+
|
5
|
+
def initialize(args = {})
|
6
|
+
rows = args[:rows] || 3
|
7
|
+
columns = args[:columns] || 3
|
8
|
+
@board = args[:board] || XAndOs::Board.new(rows,columns)
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_move(cell, marker = get_marker)
|
12
|
+
self if board.set_cell(cell, marker)
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_marker
|
16
|
+
(board.count_cells - board.free_cells.size).even? ? 'X' : 'O'
|
17
|
+
end
|
18
|
+
|
19
|
+
def winner?
|
20
|
+
board.complete_rows.count >= 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def draw?
|
24
|
+
board.free_cells.size <= 0
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module XAndOs
|
2
|
+
class GameMaster
|
3
|
+
attr_reader :board, :marker
|
4
|
+
def initialize(args = {})
|
5
|
+
@board = args[:board]
|
6
|
+
@marker = args[:marker]
|
7
|
+
@move_args = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def best_move(args={})
|
11
|
+
@move_args = args
|
12
|
+
move = win || block || fork_move || force_block || block_fork
|
13
|
+
return move if move
|
14
|
+
|
15
|
+
if first_move
|
16
|
+
1
|
17
|
+
else
|
18
|
+
center || corner || available_moves.sample
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def winning_lines
|
23
|
+
@winning_lines ||= build_winning_lines
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def mastery_board
|
29
|
+
@mastery_board = @move_args[:board] || board
|
30
|
+
end
|
31
|
+
|
32
|
+
def current_marker
|
33
|
+
@current_marker = @move_args[:marker] || marker
|
34
|
+
end
|
35
|
+
|
36
|
+
def build_winning_lines
|
37
|
+
mastery_board.all_lines
|
38
|
+
end
|
39
|
+
|
40
|
+
def total_cells
|
41
|
+
mastery_board.count_cells
|
42
|
+
end
|
43
|
+
|
44
|
+
def available_moves
|
45
|
+
mastery_board.free_cells
|
46
|
+
end
|
47
|
+
|
48
|
+
def moves_made
|
49
|
+
mastery_board.find_cells(current_marker)
|
50
|
+
end
|
51
|
+
|
52
|
+
def opponent_moves
|
53
|
+
(1..9).to_a - (moves_made + available_moves)
|
54
|
+
end
|
55
|
+
|
56
|
+
def first_move
|
57
|
+
available_moves.size == total_cells
|
58
|
+
end
|
59
|
+
|
60
|
+
def win
|
61
|
+
wining_moves(moves_made).sample
|
62
|
+
end
|
63
|
+
|
64
|
+
def block
|
65
|
+
wining_moves(opponent_moves).sample
|
66
|
+
end
|
67
|
+
|
68
|
+
def fork_move
|
69
|
+
fork_moves(moves_made).sample
|
70
|
+
end
|
71
|
+
|
72
|
+
def force_block
|
73
|
+
force_block_moves.sample
|
74
|
+
end
|
75
|
+
|
76
|
+
def block_fork
|
77
|
+
fork_moves(opponent_moves).sample
|
78
|
+
end
|
79
|
+
|
80
|
+
def center
|
81
|
+
# no center move for even numbered total cells
|
82
|
+
if mastery_board.count_cells.odd?
|
83
|
+
center_cell = (mastery_board.count_cells + 1) / 2
|
84
|
+
center_cell if available_moves.include?(center_cell)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def corner
|
89
|
+
available_moves.select do |move|
|
90
|
+
corner_moves.include?(move)
|
91
|
+
end.sample
|
92
|
+
end
|
93
|
+
|
94
|
+
def wining_moves(moves_made)
|
95
|
+
winning_lines.map do |line|
|
96
|
+
arr = line - moves_made
|
97
|
+
|
98
|
+
next unless arr.size == 1
|
99
|
+
|
100
|
+
available_moves.include?(arr.first) ? arr.first : nil
|
101
|
+
end.compact
|
102
|
+
end
|
103
|
+
|
104
|
+
def fork_moves(moves_made, moves_left = available_moves)
|
105
|
+
moves_left.map do |move|
|
106
|
+
future_moves = moves_made.dup << move
|
107
|
+
|
108
|
+
(wining_moves future_moves).size > 1 ? move : nil
|
109
|
+
end.compact
|
110
|
+
end
|
111
|
+
|
112
|
+
def force_block_moves
|
113
|
+
winning_lines.map do |line|
|
114
|
+
next unless (line & opponent_moves).empty? && (line & moves_made).any?
|
115
|
+
|
116
|
+
moves = line - moves_made
|
117
|
+
|
118
|
+
safe_moves(moves, line)
|
119
|
+
end.flatten.compact
|
120
|
+
end
|
121
|
+
|
122
|
+
def safe_moves(moves, line)
|
123
|
+
moves.map do |move|
|
124
|
+
forced_move = (line - (moves_made << move)).first
|
125
|
+
|
126
|
+
opponent_future_moves = opponent_moves << forced_move
|
127
|
+
|
128
|
+
wining_moves(opponent_future_moves).size < 2 ? move : nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def corner_moves
|
133
|
+
# To be improved to dynamically work out corners
|
134
|
+
# and move logic to board
|
135
|
+
[1,3,7,9]
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
data/lib/x_and_os.rb
ADDED
data/x_and_os.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'x_and_os/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "x_and_os"
|
8
|
+
spec.version = XAndOs::VERSION
|
9
|
+
spec.authors = ["Jonny"]
|
10
|
+
spec.email = ["jonny.adshead@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Tic tac toe command line game}
|
13
|
+
spec.description = %q{Basic modules that allow you to build a tic tac toe game and a small cla to play Tic Tac Toe in the command line}
|
14
|
+
spec.homepage = "http://github.com/JAdshead/xandos"
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
|
+
spec.bindir = "bin"
|
17
|
+
spec.executables = ["x_and_os"]
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
21
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: x_and_os
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jonny
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-09 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.9'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: Basic modules that allow you to build a tic tac toe game and a small
|
42
|
+
cla to play Tic Tac Toe in the command line
|
43
|
+
email:
|
44
|
+
- jonny.adshead@gmail.com
|
45
|
+
executables:
|
46
|
+
- x_and_os
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- ".gitignore"
|
51
|
+
- ".rspec"
|
52
|
+
- ".travis.yml"
|
53
|
+
- Gemfile
|
54
|
+
- README.md
|
55
|
+
- Rakefile
|
56
|
+
- bin/console
|
57
|
+
- bin/setup
|
58
|
+
- bin/x_and_os
|
59
|
+
- cla/tic_tac_toe.rb
|
60
|
+
- cla/tic_tac_toe/application.rb
|
61
|
+
- cla/tic_tac_toe/computer_player.rb
|
62
|
+
- cla/tic_tac_toe/display.rb
|
63
|
+
- cla/tic_tac_toe/game_manager.rb
|
64
|
+
- cla/tic_tac_toe/human_player.rb
|
65
|
+
- cla/tic_tac_toe/nameable.rb
|
66
|
+
- cla/tic_tac_toe/ui.rb
|
67
|
+
- lib/x_and_os.rb
|
68
|
+
- lib/x_and_os/board.rb
|
69
|
+
- lib/x_and_os/game.rb
|
70
|
+
- lib/x_and_os/game_master.rb
|
71
|
+
- lib/x_and_os/version.rb
|
72
|
+
- x_and_os.gemspec
|
73
|
+
homepage: http://github.com/JAdshead/xandos
|
74
|
+
licenses: []
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 2.4.8
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Tic tac toe command line game
|
96
|
+
test_files: []
|