tictactoe_tracypholmes 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.
- checksums.yaml +7 -0
- data/lib/tictactoe_tracypholmes/board.rb +65 -0
- data/lib/tictactoe_tracypholmes/game.rb +91 -0
- data/lib/tictactoe_tracypholmes/player.rb +9 -0
- data/lib/tictactoe_tracypholmes/players/computer.rb +50 -0
- data/lib/tictactoe_tracypholmes/players/human.rb +16 -0
- data/lib/tictactoe_tracypholmes/version.rb +3 -0
- data/lib/tictactoe_tracypholmes.rb +86 -0
- metadata +121 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 8a3874e0a3ee824e9bdfff5667e3242bb00789e7
|
|
4
|
+
data.tar.gz: 9874eed6d560c03f590b80a03d15cd1de45fbf20
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 872da366ce623288786ea4ddf2c5a5c9d1e5fd78e2ffc603c02730060d7baceafe60820b2124a224eb25d20691194339afcdf1e18951505ebb675f9b15b41182
|
|
7
|
+
data.tar.gz: 1a33743b43556866295ed95d70d3702b83daf61795f35d2a42dd58912fbb0a71daa3218c01fb200d4950e50981df7c0ba5d4b83ca15562636ba52f2233dcab97
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
class Board
|
|
2
|
+
attr_accessor :cells
|
|
3
|
+
|
|
4
|
+
def initialize()
|
|
5
|
+
reset!
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def reset!
|
|
9
|
+
@cells = Array.new(9, " ")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def display
|
|
13
|
+
puts " #{cells[0]} | #{cells[1]} | #{cells[2]} "
|
|
14
|
+
puts '-----------'
|
|
15
|
+
puts " #{cells[3]} | #{cells[4]} | #{cells[5]} "
|
|
16
|
+
puts '-----------'
|
|
17
|
+
puts " #{cells[6]} | #{cells[7]} | #{cells[8]} "
|
|
18
|
+
puts "\n"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def input_index(input) # this one line is all over the place!
|
|
22
|
+
input.to_i - 1
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# position method
|
|
26
|
+
def position(input)
|
|
27
|
+
@cells[input_index(input)]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# define full here - every element on the board contains "X" or "O"
|
|
31
|
+
def full?
|
|
32
|
+
@cells.all? do |mark|
|
|
33
|
+
mark == 'X' || mark == 'O'
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# define turn_count here
|
|
38
|
+
def turn_count
|
|
39
|
+
counter = 0
|
|
40
|
+
@cells.each do |occupied_spot|
|
|
41
|
+
counter += 1 if occupied_spot != ' '
|
|
42
|
+
end
|
|
43
|
+
counter
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# taken? method
|
|
47
|
+
def taken?(input)
|
|
48
|
+
exxo = position(input)
|
|
49
|
+
exxo != " " ? true:false
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# valid_move? method here
|
|
53
|
+
def valid_move?(input)
|
|
54
|
+
if position(input) == " " && input.to_i.between?(1, 9)
|
|
55
|
+
true # input on the board && input not taken
|
|
56
|
+
else
|
|
57
|
+
false # return false or nil here for invalid move
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# define update
|
|
62
|
+
def update(input, player)
|
|
63
|
+
@cells[input_index(input)] = player.token
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'tictactoe_tracypholmes/version'
|
|
2
|
+
require 'tictactoe_tracypholmes/players/computer'
|
|
3
|
+
require 'tictactoe_tracypholmes/players/human'
|
|
4
|
+
require 'tictactoe_tracypholmes/board'
|
|
5
|
+
require 'tictactoe_tracypholmes/player'
|
|
6
|
+
require 'tictactoe_tracypholmes'
|
|
7
|
+
require 'colorize'
|
|
8
|
+
|
|
9
|
+
module TictactoeTracypholmes
|
|
10
|
+
class Game
|
|
11
|
+
WIN_COMBINATIONS = [
|
|
12
|
+
[0, 1, 2],
|
|
13
|
+
[3, 4, 5],
|
|
14
|
+
[6, 7, 8],
|
|
15
|
+
[0, 3, 6],
|
|
16
|
+
[1, 4, 7],
|
|
17
|
+
[2, 5, 8],
|
|
18
|
+
[0, 4, 8],
|
|
19
|
+
[6, 4, 2]
|
|
20
|
+
].freeze
|
|
21
|
+
|
|
22
|
+
attr_accessor :board, :player_1, :player_2
|
|
23
|
+
|
|
24
|
+
# need to add name somewhere in the initialization?
|
|
25
|
+
|
|
26
|
+
def initialize(player_1 = Players::Human.new('X'), player_2 = Players::Human.new('O'), board = Board.new)
|
|
27
|
+
@player_1 = player_1
|
|
28
|
+
@player_2 = player_2
|
|
29
|
+
@board = board
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# define current_player here
|
|
33
|
+
def current_player
|
|
34
|
+
@board.turn_count.even? ? player_1 : player_2
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# over? here - won, is a draw, or full
|
|
38
|
+
def over?
|
|
39
|
+
won? || draw?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def won?
|
|
43
|
+
WIN_COMBINATIONS.detect do |win_combo|
|
|
44
|
+
if @board.cells[win_combo[0]] == @board.cells[win_combo[1]] &&
|
|
45
|
+
@board.cells[win_combo[1]] == @board.cells[win_combo[2]] &&
|
|
46
|
+
(@board.cells[win_combo[0]] == 'X' || @board.cells[win_combo[0]] == 'O')
|
|
47
|
+
return win_combo
|
|
48
|
+
else
|
|
49
|
+
false
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# define draw? here
|
|
55
|
+
def draw?
|
|
56
|
+
!won? && board.full?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# define winner here
|
|
60
|
+
def winner
|
|
61
|
+
if win_combo = won?
|
|
62
|
+
@board.cells[win_combo.first]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# define turn method here
|
|
67
|
+
def turn # work on this dadgum method
|
|
68
|
+
move = current_player.move(@board)
|
|
69
|
+
unless board.valid_move?(move)
|
|
70
|
+
puts 'NOT a valid move. Play again, please!'.red
|
|
71
|
+
turn
|
|
72
|
+
end
|
|
73
|
+
@board.update(move, current_player)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# define #play here
|
|
77
|
+
def play
|
|
78
|
+
until over? # until the game is over
|
|
79
|
+
@board.display
|
|
80
|
+
turn # take turns
|
|
81
|
+
end
|
|
82
|
+
if won?
|
|
83
|
+
@board.display
|
|
84
|
+
puts "Congratulations #{winner}!".green
|
|
85
|
+
elsif draw?
|
|
86
|
+
@board.display
|
|
87
|
+
puts "Cat's Game!".yellow
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'tictactoe_tracypholmes/board'
|
|
2
|
+
require 'tictactoe_tracypholmes/player'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module TictactoeTracypholmes
|
|
6
|
+
module Players
|
|
7
|
+
class Players::Computer < Player # represents a computer player of Tic Tac Toe. Implement a #move method that accepts a board and returns the move the computer wants to make in the form of a 1-9 string.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def move(board)
|
|
11
|
+
move = nil
|
|
12
|
+
|
|
13
|
+
# Center move if possible
|
|
14
|
+
if !board.taken?(5)
|
|
15
|
+
move = '5'
|
|
16
|
+
# If player2 and the scoundrel took 5, goto the first position
|
|
17
|
+
elsif board.turn_count == 1
|
|
18
|
+
move = '1'
|
|
19
|
+
# Go for the corners! Presumes you went first
|
|
20
|
+
elsif board.turn_count == 2
|
|
21
|
+
move = [1, 3, 7, 9].find{|i| !board.taken?(i)}.to_s
|
|
22
|
+
|
|
23
|
+
# Player2 side strategy
|
|
24
|
+
elsif board.turn_count == 3 && (board.position(1) == board.position(9) || board.position(3) == board.position(7))
|
|
25
|
+
move = "2"
|
|
26
|
+
|
|
27
|
+
# You worked hard on these combinations - let's see who has the best combos thus far
|
|
28
|
+
else Game::WIN_COMBINATIONS.find do |c|
|
|
29
|
+
|
|
30
|
+
# Do I have a winner?
|
|
31
|
+
if c.select{|i| board.position(i+1) == token}.size == 2 && c.any?{|i| board.position(i+1) == " "}
|
|
32
|
+
move = c.select{|i| !board.taken?(i+1)}.first.to_i.+(1).to_s
|
|
33
|
+
|
|
34
|
+
# No winner - let's block the other guy
|
|
35
|
+
elsif c.select{|i| board.position(i+1) != " " && board.position(i+1) != token}.size == 2 && c.any?{|i| board.position(i+1) == " "}
|
|
36
|
+
move = c.select{|i| !board.taken?(i+1)}.first.to_i.+(1).to_s
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# No one has a winner, let's play out the corners and sides if possible
|
|
41
|
+
move = [1, 3, 7, 9, 2, 4, 6, 8].find{|i| !board.taken?(i)}.to_s if move == nil
|
|
42
|
+
end
|
|
43
|
+
move
|
|
44
|
+
|
|
45
|
+
# input = (1..9).to_a.sample
|
|
46
|
+
# input.to_s
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'tictactoe_tracypholmes/player'
|
|
2
|
+
|
|
3
|
+
module TictactoeTracypholmes
|
|
4
|
+
module Players
|
|
5
|
+
class Human < Player
|
|
6
|
+
# move method
|
|
7
|
+
|
|
8
|
+
attr_accessor :input
|
|
9
|
+
|
|
10
|
+
def move(board)
|
|
11
|
+
puts 'Please make a move by entering a number from 1 - 9.'
|
|
12
|
+
gets.chomp
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require 'tictactoe_tracypholmes/version'
|
|
2
|
+
require 'tictactoe_tracypholmes/game'
|
|
3
|
+
require 'colorize'
|
|
4
|
+
|
|
5
|
+
module TictactoeTracypholmes
|
|
6
|
+
class TicTacToeCLI
|
|
7
|
+
def initialize; end
|
|
8
|
+
|
|
9
|
+
puts %q[
|
|
10
|
+
_____ _ _____ _____
|
|
11
|
+
|_ _(_) ____ _|_ _ ____ _|__ ___
|
|
12
|
+
| | | |/ __|| |/ _` |/ __|| |/ _ \ / _ \
|
|
13
|
+
| | | | (__ | | (_| | (__ | | (_) | __/
|
|
14
|
+
|_| |_|\___||_|\__,_|\___||_|\___/ \___|
|
|
15
|
+
].green
|
|
16
|
+
puts 'Hi! Welcome to the battlezone. Tic Tac Toe is the name of the game!'
|
|
17
|
+
|
|
18
|
+
puts 'Please enter your name so that we can provide the best experience:'
|
|
19
|
+
name = gets.chomp
|
|
20
|
+
puts "Thanks #{name}! What kind of game would you like to play?"
|
|
21
|
+
|
|
22
|
+
def call
|
|
23
|
+
puts 'Enter 1 to play against the computer.'
|
|
24
|
+
puts 'Enter 2 to play against a human.'
|
|
25
|
+
puts 'Enter 00110011 to watch the computers battle to their circuits.'
|
|
26
|
+
puts "WHISPERS 'or enter wargames if you want to have a good time'"
|
|
27
|
+
puts "\nYou may also enter 'q' to Quit"
|
|
28
|
+
game_type = gets.chomp
|
|
29
|
+
first_move = ''
|
|
30
|
+
|
|
31
|
+
if game_type == 'q'
|
|
32
|
+
puts 'Hate to see you go. Have a nice day!'.green
|
|
33
|
+
abort
|
|
34
|
+
elsif game_type == '2' # hum vs hum
|
|
35
|
+
Game.new.play
|
|
36
|
+
puts "OMG that was fun, wasn't it, Player? Would you like to play another game?"
|
|
37
|
+
merry_go_round
|
|
38
|
+
elsif game_type == '00110011' # comp vs comp
|
|
39
|
+
Game.new(Players::Computer.new('X'), Players::Computer.new('O'), Board.new).play
|
|
40
|
+
puts "OMG that was fun, wasn't it? Would you like to play another game?"
|
|
41
|
+
merry_go_round
|
|
42
|
+
elsif game_type == 'wargames' # comp on comp crime for 100
|
|
43
|
+
counter = 0
|
|
44
|
+
until counter == 100
|
|
45
|
+
counter += 1
|
|
46
|
+
Game.new(Players::Computer.new('X'), Players::Computer.new('O')).play
|
|
47
|
+
puts "OMG that was fun, wasn't it? Would you like to play another game?"
|
|
48
|
+
merry_go_round
|
|
49
|
+
end
|
|
50
|
+
elsif game_type == '1' # hum vs comp
|
|
51
|
+
puts "So umm...who's going first?!"
|
|
52
|
+
puts "\nIf you want to go first, Player, choose 'X'. Otherwise, choose 'O'"
|
|
53
|
+
first_move = gets.strip.upcase
|
|
54
|
+
while first_move != 'X' && first_move != 'O'
|
|
55
|
+
puts 'Cmon, son! What are you doing?! Enter X or O, please.'.red
|
|
56
|
+
first_move = gets.strip.upcase
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
game = nil
|
|
61
|
+
if first_move == 'X'
|
|
62
|
+
Game.new(Players::Human.new('X'), Players::Computer.new('O'), Board.new).play
|
|
63
|
+
else
|
|
64
|
+
Game.new(Players::Computer.new('X'), Players::Human.new('O'), Board.new).play
|
|
65
|
+
end
|
|
66
|
+
puts "OMG that was fun, wasn't it? Would you like to play another game?"
|
|
67
|
+
merry_go_round
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def merry_go_round
|
|
71
|
+
input = gets.chomp
|
|
72
|
+
while input != 'Y' || input != 'N'
|
|
73
|
+
puts "Please enter 'Y' or 'N'.".red
|
|
74
|
+
case input
|
|
75
|
+
when 'Y'
|
|
76
|
+
call
|
|
77
|
+
when 'N'
|
|
78
|
+
puts 'Aww man! Ok. See you later!'
|
|
79
|
+
abort
|
|
80
|
+
else
|
|
81
|
+
merry_go_round
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: tictactoe_tracypholmes
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- tracypholmes
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2017-01-18 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.13'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.13'
|
|
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: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: pry
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: colorize
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 0.8.1
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 0.8.1
|
|
83
|
+
description: TicTacToe game with somewhat unbeatable AI
|
|
84
|
+
email:
|
|
85
|
+
- tracyholmes@gmail.com
|
|
86
|
+
executables: []
|
|
87
|
+
extensions: []
|
|
88
|
+
extra_rdoc_files: []
|
|
89
|
+
files:
|
|
90
|
+
- lib/tictactoe_tracypholmes.rb
|
|
91
|
+
- lib/tictactoe_tracypholmes/board.rb
|
|
92
|
+
- lib/tictactoe_tracypholmes/game.rb
|
|
93
|
+
- lib/tictactoe_tracypholmes/player.rb
|
|
94
|
+
- lib/tictactoe_tracypholmes/players/computer.rb
|
|
95
|
+
- lib/tictactoe_tracypholmes/players/human.rb
|
|
96
|
+
- lib/tictactoe_tracypholmes/version.rb
|
|
97
|
+
homepage: https://github.com/tracypholmes/tictactoe_tracypholmes
|
|
98
|
+
licenses:
|
|
99
|
+
- MIT
|
|
100
|
+
metadata: {}
|
|
101
|
+
post_install_message:
|
|
102
|
+
rdoc_options: []
|
|
103
|
+
require_paths:
|
|
104
|
+
- lib
|
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
|
+
requirements:
|
|
112
|
+
- - ">="
|
|
113
|
+
- !ruby/object:Gem::Version
|
|
114
|
+
version: '0'
|
|
115
|
+
requirements: []
|
|
116
|
+
rubyforge_project:
|
|
117
|
+
rubygems_version: 2.6.7
|
|
118
|
+
signing_key:
|
|
119
|
+
specification_version: 4
|
|
120
|
+
summary: TictTacToe with AI
|
|
121
|
+
test_files: []
|