tic_tac_toe_bfox 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0b97a0ee48814d4adde4f74cd0a9218645ef8d67
4
+ data.tar.gz: be30925fff9cd631a7c7a31a2f6ea1a58af71e5f
5
+ SHA512:
6
+ metadata.gz: a3bbebb23e84bc84d4e7bf23e2236b40cbc1d65541474414f6c5773228c3051b3516c76d90f2c25db5dc1e8669481eb64cc42496872e3f8cb134b51ef10c7aa3
7
+ data.tar.gz: 2c667d703865e7374250bf9386069759010d45130bbc06f1d8c829dee39dbfbb3c941974e02bf5548069dbfd8cd1b8a4940d7457080a2d44eb169fede6d56027
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.0
5
+ before_install: gem install bundler -v 1.14.6
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ # http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/
4
+ # Programs/foodie example
5
+ gemspec
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # tic_tac_toe
2
+
3
+ **Instructions:**
4
+
5
+ 1. In order to play the game, please type **ruby main.rb** into your console.
6
+ 2. Follow the prompts to set your name and the value of your mark.
7
+ 3. Choose whether you would like to play a computer (**"C"**) or a human (**"H"**).
8
+ 4. If you choose to play a computer, further choose whether you would like to play
9
+ * an easy (**"E"**) computer: this computer selects randomly
10
+ * a difficult (**"D"**) computer: this computer is impossible to beat!
11
+ 5. Choose how many squares per row you would like. Note that 9 is the maximum, unless you are playing a difficult computer, who prefers to play with a maximum of 3 squares per row.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/bin/tictactoe ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ #below line requires tictactoe which runs program
5
+ require "tictactoe"
6
+
@@ -0,0 +1,36 @@
1
+ module TTT
2
+ class Board
3
+ attr_accessor :rows_and_cols, :squares
4
+
5
+ def initialize(args = {})
6
+ @rows_and_cols = args[:rows_and_cols]
7
+ @squares = args[:squares]
8
+ end
9
+
10
+ def change_square(display_value, new_value)
11
+ square_to_change = retrieve_square(display_value)
12
+ square_to_change.change_value(new_value)
13
+ end
14
+
15
+ def full?
16
+ return squares.full?
17
+ end
18
+
19
+ def won?
20
+ return squares.any_combination_won?
21
+ end
22
+
23
+ def display_values
24
+ return squares.display_values
25
+ end
26
+
27
+ def available_choices
28
+ return squares.available_choices
29
+ end
30
+
31
+ private
32
+ def retrieve_square(display_value)
33
+ return squares.retrieve_square(display_value)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ module TTT
2
+ class BoardPresenterTerminal
3
+ def present_board(board)
4
+ #board.display_values will return multidimensional array
5
+ display_values = board.display_values
6
+ display_values.each do |row|
7
+ row.each_with_index do |display_value, index|
8
+ #http://www.evc-cit.info/cit020/beginning-programming/chp_04/file_printf.html
9
+ printf "%2s", display_value
10
+ print " | " unless index == (row.size - 1)
11
+ end
12
+ print "\n"
13
+ puts "_"*(row.size * 5) unless row.equal? display_values.last
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,129 @@
1
+ require_relative 'io_terminal'
2
+ require_relative 'board_presenter_terminal'
3
+ require_relative 'game_config'
4
+ require_relative 'squares_factory'
5
+
6
+ module TTT
7
+ class Game
8
+ attr_accessor :board, :players, :board_presenter, :number_of_turns_taken, :config
9
+ attr_reader :io, :input_helper
10
+
11
+ def initialize(args = {})
12
+ @io = args.fetch(:io, IOTerminal.new)
13
+ @board_presenter = args.fetch(:board_presenter, BoardPresenterTerminal.new)
14
+ @input_helper = InputHelper.new(@io)
15
+ @number_of_turns_taken = 0
16
+ # below finds the user needed input needed for initial players and board configuration and stores in config object
17
+ @config = GameConfig.new(@input_helper)
18
+ @players = generate_players
19
+ @board = generate_board
20
+ end
21
+
22
+ #overriding so that io and input_helper always in harmony
23
+ def io=(new_io)
24
+ @io = new_io
25
+ self.input_helper = InputHelper.new(new_io)
26
+ end
27
+
28
+ def generate_players
29
+ player_1 = Player.new(value: config.player_1_value, name: config.player_1_name, type: :human)
30
+ player_2 = Player.new(value: config.player_2_value, name: config.player_2_name, type: config.player_2_type, difficulty_level: config.computer_difficulty_level)
31
+ [player_1, player_2]
32
+ end
33
+
34
+ def generate_board
35
+ number_of_rows_cols = config.number_of_rows_cols
36
+ Board.new(rows_and_cols: number_of_rows_cols, squares: SquaresFactory.build_empty_squares(number_of_rows_cols) )
37
+ end
38
+
39
+ def play
40
+ while !over?
41
+ print_board
42
+ square_choice = get_square_choice
43
+ #note that change_square moves current_player forward only if game is not won
44
+ change_square(square_choice, current_player.value)
45
+ end
46
+
47
+ if won?
48
+ print_board
49
+ io.present_with_new_line("#{current_player.name} wins!")
50
+ else
51
+ print_board
52
+ io.present_with_new_line("Draw!")
53
+ end
54
+ end
55
+
56
+ def get_square_choice
57
+ if current_player.type == :human
58
+ input_helper.get_square_to_change(current_player.name, available_choices)
59
+ elsif current_player.type == :computer
60
+ input_helper.computer_choosing_graphic
61
+ if current_player.difficulty_level == :difficult
62
+ perfect_move
63
+ elsif current_player.difficulty_level == :easy
64
+ random_move
65
+ end
66
+ end
67
+ end
68
+
69
+ def change_square(display_value, new_value)
70
+ board.change_square(display_value, new_value)
71
+ if !won?
72
+ move_forward_one_turn
73
+ end
74
+ end
75
+
76
+ def over?
77
+ board.full? || board.won?
78
+ end
79
+
80
+ def won?
81
+ board.won?
82
+ end
83
+
84
+ def winner
85
+ #each move is immediately proceeded by an increment to number_of_selections_made; therefore, need to rewind won to find winner
86
+ if !won?
87
+ return nil
88
+ end
89
+ current_player
90
+ end
91
+
92
+ def perfect_move
93
+ move_generator = MoveGenerator.new(self)
94
+ move_generator.minimax
95
+ move_generator.choice
96
+ end
97
+
98
+ def random_move
99
+ available_choices.sample
100
+ end
101
+
102
+ def available_choices
103
+ board.available_choices
104
+ end
105
+
106
+ def print_board
107
+ board_presenter.present_board(board)
108
+ end
109
+
110
+ def current_player
111
+ players[current_turn_player_index]
112
+ end
113
+
114
+ def move_forward_one_turn
115
+ self.number_of_turns_taken += 1
116
+ end
117
+
118
+ private
119
+
120
+ def number_of_players
121
+ players.size
122
+ end
123
+
124
+
125
+ def current_turn_player_index
126
+ (number_of_turns_taken % number_of_players)
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,71 @@
1
+ module TTT
2
+ class GameConfig
3
+ attr_accessor :input_helper
4
+
5
+ attr_accessor :player_1_name
6
+ attr_accessor :player_1_value
7
+ attr_accessor :player_2_type
8
+ attr_accessor :player_2_name
9
+ attr_accessor :player_2_value
10
+ attr_accessor :computer_difficulty_level
11
+ attr_accessor :number_of_rows_cols
12
+
13
+ def initialize(input_helper)
14
+ @input_helper = input_helper
15
+ setup
16
+
17
+ end
18
+
19
+ def setup
20
+ set_player_1_values
21
+ set_player_2_values
22
+ set_board_rows_cols
23
+ end
24
+
25
+ def set_player_1_values
26
+ self.player_1_name = input_helper.get_player_1_name
27
+ self.player_1_value = input_helper.get_player_1_value(player_1_name)
28
+ end
29
+
30
+ def set_player_2_values
31
+ self.player_2_type = input_helper.get_player_2_type
32
+ if player_2_human?
33
+ self.player_2_name = input_helper.get_player_2_name
34
+ self.player_2_value = input_helper.get_player_2_value(player_1_value)
35
+ elsif player_2_computer?
36
+ self.player_2_name = "Computer"
37
+ self.player_2_value = get_computer_value
38
+ self.computer_difficulty_level = input_helper.get_computer_difficulty_level
39
+ end
40
+ end
41
+
42
+ def set_board_rows_cols
43
+ #need this if else logic because if computer is difficult, it runs minimax, which is too slow to allow for more than 3 rows/cols
44
+ if computer_difficult?
45
+ self.number_of_rows_cols = input_helper.get_number_of_rows_cols_max_3
46
+ else
47
+ self.number_of_rows_cols = input_helper.get_number_of_rows_cols_max_9
48
+ end
49
+ end
50
+
51
+ def player_2_human?
52
+ player_2_type == :human
53
+ end
54
+
55
+ def player_2_computer?
56
+ player_2_type == :computer
57
+ end
58
+
59
+ def computer_difficult?
60
+ computer_difficulty_level == :difficult
61
+ end
62
+
63
+ def get_computer_value
64
+ if player_2_value != "O"
65
+ "O"
66
+ else
67
+ "X"
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,99 @@
1
+ module TTT
2
+ class InputHelper
3
+ attr_accessor :io
4
+
5
+ def initialize(io)
6
+ @io = io
7
+ end
8
+
9
+ def get_number_of_rows_cols_max_3
10
+ get_user_input("Please choose how many squares you would like in each row.", "Please choose number between 2 and 3.") do |input|
11
+ input.to_i >=2 && input.to_i <=3
12
+ end
13
+ end
14
+
15
+ def get_number_of_rows_cols_max_9
16
+ get_user_input("Please choose how many squares you would like in each row.", "Please choose number between 2 and 3.") do |input|
17
+ input.to_i >=2 && input.to_i <=9
18
+ end
19
+ end
20
+
21
+ def get_player_1_value(player_name = "Player 1")
22
+ user_choice = get_user_input("#{player_name}, please enter a value of either X or O", "Must be X or O. Please re-enter.") do |input|
23
+ input == 'x' || input == 'X' || input == 'o' || input == 'O'
24
+ end
25
+ user_choice.upcase
26
+ end
27
+
28
+ def get_player_2_value(taken_value)
29
+ user_choice = get_user_input("Player 2, please enter your value", "Must not be #{taken_value}, please re-enter") do |input|
30
+ input.upcase != taken_value
31
+ end
32
+ user_choice.upcase
33
+ end
34
+
35
+ def get_player_1_name
36
+ user_choice = get_user_input("Player 1, please enter your name", "Please re-enter your name, using only letters") do |input|
37
+ input =~ /^[a-zA-Z]+$/
38
+ end
39
+ user_choice.capitalize
40
+ end
41
+
42
+ def get_player_2_name
43
+ user_choice = get_user_input("Player 2, please enter your name", "Please re-enter your name, using only letters") do |input|
44
+ input =~ /^[a-zA-Z]+$/
45
+ end
46
+ user_choice.capitalize
47
+ end
48
+
49
+ def get_player_2_type
50
+ user_choice = get_user_input("Please enter \"C\" if you would like to play the Computer. Enter \"H\" if you would like to play the human sitting next to you.", "Invalid character. Please enter either C(Computer) or H(Human).") do |input|
51
+ input == 'c' || input == 'C' || input == 'h' || input == 'H'
52
+ end
53
+ user_choice = user_choice.upcase
54
+ if user_choice == "C"
55
+ :computer
56
+ elsif user_choice == "H"
57
+ :human
58
+ end
59
+ end
60
+
61
+ def get_computer_difficulty_level
62
+ user_choice = get_user_input("Please enter \"E\" if you would like to play an easy Computer. Enter \"D\" if you would like to play an extremely difficult computer.", "Invalid character. Please enter either E (Easy) or D (Difficult).") do |input|
63
+ input == 'd' || input == 'D' || input == 'e' || input == 'E'
64
+ end
65
+ user_choice = user_choice.upcase
66
+ if user_choice == "D"
67
+ :difficult
68
+ elsif user_choice == "E"
69
+ :easy
70
+ end
71
+ end
72
+
73
+ def get_square_to_change(player_name, available_choices)
74
+ get_user_input("#{player_name}, please enter the number of the square that you would like to change.", "Invalid entry. Please try again.") do |input|
75
+ available_choices.include?(input)
76
+ end
77
+ end
78
+
79
+ def get_user_input(prompt, reprompt, &block_validation)
80
+ io.present_with_new_line(prompt)
81
+ user_choice = nil
82
+ while true
83
+ user_choice = io.receive
84
+ break if block_validation.call(user_choice)
85
+ puts reprompt
86
+ end
87
+ user_choice
88
+ end
89
+
90
+ def computer_choosing_graphic
91
+ io.present("Computer choosing.")
92
+ 3.times do
93
+ sleep(0.3)
94
+ io.present(".")
95
+ end
96
+ io.present("\n")
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,25 @@
1
+ module TTT
2
+ class IOTerminal
3
+ def present(prompt)
4
+ print prompt
5
+ end
6
+
7
+ def present_with_new_line(prompt)
8
+ puts prompt
9
+ end
10
+
11
+ def receive
12
+ result = gets.chomp
13
+ if is_int?(result)
14
+ return result.to_i
15
+ else
16
+ return result.chomp
17
+ end
18
+ end
19
+
20
+ private
21
+ def is_int?(figure)
22
+ Integer(figure) rescue false
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,70 @@
1
+ module TTT
2
+ class MoveGenerator
3
+
4
+ attr_accessor :game, :choice
5
+
6
+ def initialize(game)
7
+ @game = game
8
+ end
9
+
10
+ #returns int representing display value of random available square
11
+ def random_move
12
+ available_choices.sample
13
+ end
14
+
15
+ def minimax
16
+ scores = []
17
+ choices = []
18
+ if game.over?
19
+ return score(game)
20
+ end
21
+
22
+ available_choices.each do |available_choice|
23
+ new_game_state = Marshal.load(Marshal.dump(game))
24
+ new_game_state.change_square(available_choice, game.current_player.value)
25
+ #below needed because pry indicates possible_game_state's board not updating after make_move above
26
+ # possible_game_state.game_board = possible_board_state
27
+ choices.push(available_choice)
28
+ new_move_generator = MoveGenerator.new(new_game_state)
29
+ scores.push new_move_generator.minimax
30
+ end
31
+
32
+ if game.current_player == computer_player
33
+
34
+ #https://stackoverflow.com/questions/2149802/in-ruby-what-is-the-cleanest-way-of-obtaining-the-index-of-the-largest-value-in
35
+ max_score_index = scores.each_with_index.max[1]
36
+ @choice = choices[max_score_index]
37
+ return scores[max_score_index]
38
+ else
39
+ # This is the min calculation
40
+ min_score_index = scores.each_with_index.min[1]
41
+ @choice = choices[min_score_index]
42
+ return scores[min_score_index]
43
+ end
44
+
45
+ end
46
+
47
+ private
48
+ def available_choices
49
+ game.available_choices
50
+ end
51
+
52
+ def score(game)
53
+ if game.won? && game.winner == computer_player
54
+ return +1
55
+ elsif game.won? && game.winner == player_1
56
+ return -1
57
+ else
58
+ return 0
59
+ end
60
+ end
61
+
62
+ def player_1
63
+ game.players[0]
64
+ end
65
+
66
+ def computer_player
67
+ game.players[1]
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,12 @@
1
+ module TTT
2
+ class Player
3
+ attr_accessor :value, :name, :type, :difficulty_level
4
+
5
+ def initialize(args = {})
6
+ @value = args.fetch(:value, "X")
7
+ @name = args.fetch(:name, "Player 1")
8
+ @type = args.fetch(:type, :computer)
9
+ @difficulty_level = args.fetch(:difficulty_level, nil)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ module TTT
2
+ class Square
3
+ attr_accessor :value, :display_value
4
+ attr_reader :row, :col
5
+
6
+ def initialize(args)
7
+ @value = args[:value]
8
+ @display_value = args[:display_value]
9
+ @row = args[:row]
10
+ @col = args[:col]
11
+ end
12
+
13
+ def change_value(new_value)
14
+ self.value = new_value
15
+ self.display_value = new_value
16
+ end
17
+
18
+ def empty?
19
+ return true unless full?
20
+ end
21
+
22
+ def full?
23
+ if value != nil
24
+ return true
25
+ else
26
+ return false
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,129 @@
1
+ module TTT
2
+ class Squares
3
+ attr_reader :collection_of_squares
4
+
5
+ #collection_of_squares is a multi-dimensional array
6
+
7
+ def initialize(args)
8
+ @collection_of_squares = args[:collection_of_squares]
9
+ end
10
+
11
+ def retrieve_square(display_value)
12
+ row = (display_value - 1) / number_of_rows_cols
13
+ col = (display_value - 1) % number_of_rows_cols
14
+ if row >= number_of_rows_cols || col >= number_of_rows_cols
15
+ return nil
16
+ else
17
+ return collection_of_squares[row][col]
18
+ end
19
+ end
20
+
21
+ def display_values
22
+ collection_of_squares.map do |row|
23
+ row.map do |square|
24
+ square.display_value
25
+ end
26
+ end
27
+ end
28
+
29
+ def available_choices
30
+ available_choices = Array.new
31
+ collection_of_squares.each do |row|
32
+ row.each do |square|
33
+ if square.empty?
34
+ available_choices.push(square.display_value)
35
+ end
36
+ end
37
+ end
38
+ available_choices
39
+ end
40
+
41
+ def full?
42
+ collection_of_squares.each do |row|
43
+ return false if row.all? { |square| square.full? } == false
44
+ end
45
+ return true
46
+ end
47
+
48
+ def any_combination_won?
49
+ possible_winning_combinations.any? do |possible_winning_combination|
50
+ won?(possible_winning_combination)
51
+ end
52
+ end
53
+
54
+ def won?(array)
55
+ #https://stackoverflow.com/questions/3233278/how-do-i-test-if-all-items-in-an-array-are-identical
56
+ return false if array[0].value == nil
57
+ array.all? {|square| square.value == array[0].value}
58
+ end
59
+
60
+ def number_of_rows_cols
61
+ collection_of_squares.length
62
+ end
63
+
64
+ private
65
+ def cols
66
+ number_of_rows_cols = collection_of_squares.size
67
+ cols = Array.new
68
+ col = 0
69
+ while col < number_of_rows_cols
70
+ cols.push (
71
+ collection_of_squares.map do |row|
72
+ row[col]
73
+ end
74
+ )
75
+ col += 1
76
+ end
77
+ cols
78
+ end
79
+
80
+ #return collection_of_squares because set up as multidimensional array consisting of rows
81
+ def rows
82
+ collection_of_squares
83
+ end
84
+
85
+ def l_to_r_diag
86
+ number_of_rows_cols = collection_of_squares.size
87
+ diag = Array.new
88
+ row = 0
89
+ col = 0
90
+ while row < number_of_rows_cols
91
+ diag.push (
92
+ collection_of_squares[row][col]
93
+ )
94
+ row += 1
95
+ col += 1
96
+ end
97
+ diag
98
+ end
99
+
100
+ def r_to_l_diag
101
+ number_of_rows_cols = collection_of_squares.size
102
+ diag = Array.new
103
+ row = 0
104
+ col = number_of_rows_cols - 1
105
+ while row < number_of_rows_cols
106
+ diag.push (
107
+ collection_of_squares[row][col]
108
+ )
109
+ row += 1
110
+ col -= 1
111
+ end
112
+ diag
113
+ end
114
+
115
+ def possible_winning_combinations
116
+ winning_combinations = Array.new
117
+ winning_combinations.push(l_to_r_diag, r_to_l_diag)
118
+
119
+ rows.each do |row|
120
+ winning_combinations.push(row)
121
+ end
122
+
123
+ cols.each do |col|
124
+ winning_combinations.push(col)
125
+ end
126
+ winning_combinations
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,56 @@
1
+ require_relative 'squares'
2
+ require_relative 'square'
3
+
4
+ module TTT
5
+ module SquaresFactory
6
+ def self.build_custom_squares(config, squares_class = Squares)
7
+
8
+ rows_and_cols = config.length
9
+
10
+ #create multi-dimensional array
11
+ squares = Array.new(rows_and_cols) do
12
+ Array.new(rows_and_cols)
13
+ end
14
+
15
+ squares.each_with_index do |element, row|
16
+ element.each_index do |col|
17
+ squares[row][col] = create_custom_square(config[row][col][0],config[row][col][1], row, col)
18
+ end
19
+ end
20
+
21
+ squares_class.new(collection_of_squares: squares)
22
+
23
+ end
24
+
25
+
26
+ def self.create_custom_square(display_value, value, row, col, square_class = Square)
27
+ square_class.new(display_value: display_value,
28
+ value: value,
29
+ row: row,
30
+ col: col )
31
+ end
32
+
33
+ def self.build_empty_squares(rows_and_cols, squares_class = Squares)
34
+ squares = Array.new(rows_and_cols) do
35
+ Array.new(rows_and_cols)
36
+ end
37
+
38
+ i = 1
39
+ squares.each_with_index do |element, row|
40
+ element.each_index do |col|
41
+ squares[row][col] = create_empty_square(i, row, col)
42
+ i += 1
43
+ end
44
+ end
45
+
46
+ squares_class.new(collection_of_squares: squares)
47
+ end
48
+
49
+ def self.create_empty_square(display_value, row, col, square_class = Square)
50
+ square_class.new(display_value: display_value,
51
+ value: nil,
52
+ row: row,
53
+ col: col )
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ module TTT
2
+ VERSION = "0.1.0"
3
+ end
data/lib/tictactoe.rb ADDED
@@ -0,0 +1,9 @@
1
+ Dir["./lib/tictactoe/*.rb"].each {|file| require file }
2
+
3
+ class TicTacToe
4
+ io = TTT::IOTerminal.new
5
+ board_presenter = TTT::BoardPresenterTerminal.new
6
+
7
+ game = TTT::Game.new(io: io, board_presenter: board_presenter)
8
+ game.play
9
+ end
data/tictactoe.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tictactoe/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tic_tac_toe_bfox"
8
+ spec.version = TTT::VERSION
9
+ spec.authors = ["Brett Fox"]
10
+ spec.email = ["brettfox11@gmail.com"]
11
+
12
+ spec.summary = %q{Command line tic tac toe}
13
+ spec.description = %q{In order to play the game, please type "tictactoe" at the command line.}
14
+ spec.homepage = "https://github.com/brett11/tic_tac_toe_2"
15
+
16
+ # # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ # if spec.respond_to?(:metadata)
19
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
20
+ # else
21
+ # raise "RubyGems 2.0 or newer is required to protect against " \
22
+ # "public gem pushes."
23
+ # end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(test|spec|features)/})
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_development_dependency "bundler", "~> 1.14"
33
+ spec.add_development_dependency "rake", "~> 10.0"
34
+ spec.add_development_dependency "rspec", "~> 3.0"
35
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tic_tac_toe_bfox
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brett Fox
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-09-17 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.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
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
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: In order to play the game, please type "tictactoe" at the command line.
56
+ email:
57
+ - brettfox11@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - README.md
67
+ - Rakefile
68
+ - bin/setup
69
+ - bin/tictactoe
70
+ - lib/tictactoe.rb
71
+ - lib/tictactoe/board.rb
72
+ - lib/tictactoe/board_presenter_terminal.rb
73
+ - lib/tictactoe/game.rb
74
+ - lib/tictactoe/game_config.rb
75
+ - lib/tictactoe/input_helper.rb
76
+ - lib/tictactoe/io_terminal.rb
77
+ - lib/tictactoe/move_generator.rb
78
+ - lib/tictactoe/player.rb
79
+ - lib/tictactoe/square.rb
80
+ - lib/tictactoe/squares.rb
81
+ - lib/tictactoe/squares_factory.rb
82
+ - lib/tictactoe/version.rb
83
+ - tictactoe.gemspec
84
+ homepage: https://github.com/brett11/tic_tac_toe_2
85
+ licenses: []
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.6.10
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Command line tic tac toe
107
+ test_files: []