tictactoe_alu3286 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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - jruby-18mode # JRuby in 1.8 mode
5
+ - jruby-19mode # JRuby in 1.9 mode
6
+ - rbx-18mode
7
+ - rbx-19mode
8
+ - 1.8.7
9
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tictactoe_alu3286.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,6 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
6
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 alu3286
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # TictactoeAlu3286
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'tictactoe_alu3286'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install tictactoe_alu3286
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
30
+
31
+ Enunciado de la práctica:
32
+
33
+ Considere el desarrollo de una aplicación para jugar al tres en raya.
34
+ El objetivo de esta práctica es la creación de una Gema en Ruby para el juego de tres en raya. Para ello se ha de utilizar la herramienta Bundler (http://gembundler.com/)
35
+ 1.- Utilizar bundle para crear la estructura estandar de una gema.
36
+ Véanse railcast: gems with bundler y el blog polishing rubies
37
+ bundle gem tictactoe
38
+ 2.- Partiendo de la implementacion del juego que está disponible en github separar a los jugadores en diferentes ficheros y utilizarlos como plugins.
39
+ 3.- Escribir un conjunto de pruebas unitarias (Unit Testing)
40
+ test/tc_tictactoe.rb
41
+ 4.- Escribir un fichero de espectativas de comportamiento (BDD)
42
+ spec/tictactoe_spec.rb
43
+ 5.- Realizar un seguimiento continuo de las pruebas (Continuous Testing)
44
+ guard
45
+ 6.- Comprobar el correcto funcionamiento en distintas plataformas (Continuous Integration)
46
+ travis
47
+ 7.- Indique la URL del repositorio github o bitbucket que ha desarrollado.
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ $:.unshift File.dirname(__FILE__) + 'lib'
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new
7
+ task :default => :spec
8
+
9
+ desc "Run TicTacToe game vs smart player"
10
+ task :smart do
11
+ sh "ruby -Ilib bin/tictactoe_game.rb"
12
+ end
13
+
14
+ desc "Run TicTacToe game vs dumb player"
15
+ task :dumb do
16
+ sh "ruby -Ilib bin/tictactoe_game.rb -d"
17
+ end
18
+
19
+ desc "Run rspec with --format documentation"
20
+ task :doc do
21
+ sh "rspec -Ilib spec/*.rb --format documentation"
22
+ end
23
+
24
+ desc "Run HumanPlayer tests"
25
+ task :hp_test do
26
+ sh "ruby -Ilib test/tc_humanplayer.rb"
27
+ end
28
+
29
+ desc "Run SmartPlayer tests"
30
+ task :sp_test do
31
+ sh "ruby -Ilib test/tc_smartplayer.rb"
32
+ end
33
+
34
+ desc "Run DumbPlayer tests"
35
+ task :dp_test do
36
+ sh "ruby -Ilib test/tc_dumbplayer.rb"
37
+ end
@@ -0,0 +1,12 @@
1
+ require "tictactoe_alu3286"
2
+
3
+ if __FILE__ == $0
4
+ if ARGV.size > 0 and ARGV[0] == "-d"
5
+ game = TictactoeAlu3286::Game.new TictactoeAlu3286::HumanPlayer,
6
+ TictactoeAlu3286::DumbPlayer
7
+ else
8
+ game = TictactoeAlu3286::Game.new TictactoeAlu3286::HumanPlayer,
9
+ TictactoeAlu3286::SmartPlayer
10
+ end
11
+ game.play
12
+ end
data/lib/.DS_Store ADDED
Binary file
@@ -0,0 +1,36 @@
1
+ require "tictactoe_alu3286/version"
2
+ require "tictactoe_alu3286/humanplayer"
3
+ require "tictactoe_alu3286/smartplayer"
4
+ require "tictactoe_alu3286/dumbplayer"
5
+ require "tictactoe_alu3286/board"
6
+
7
+ module TictactoeAlu3286
8
+ class Game
9
+ def initialize( player1, player2, random = true )
10
+ if random and rand(2) == 1
11
+ @x_player = player2.new("X")
12
+ @o_player = player1.new("O")
13
+ else
14
+ @x_player = player1.new("X")
15
+ @o_player = player2.new("O")
16
+ end
17
+
18
+ @board = Board.new([" "] * 9)
19
+ end
20
+
21
+ attr_reader :x_player, :o_player
22
+
23
+ def play
24
+ until @board.won?
25
+ @board[@x_player.move(@board)] = @x_player.mark
26
+ break if @board.won?
27
+
28
+ @board[@o_player.move(@board)] = @o_player.mark
29
+ end
30
+
31
+ @o_player.finish @board
32
+ @x_player.finish @board
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,104 @@
1
+ module TictactoeAlu3286
2
+ module SquaresContainer
3
+ def []( index ) @squares[index] end
4
+
5
+ def blanks() @squares.find_all { |s| s == " " }.size end
6
+ def os() @squares.find_all { |s| s == "O" }.size end
7
+ def xs() @squares.find_all { |s| s == "X" }.size end
8
+ end
9
+
10
+ class Board
11
+ class Row
12
+ def initialize( squares, names )
13
+ @squares = squares
14
+ @names = names
15
+ end
16
+
17
+ include SquaresContainer
18
+
19
+ def to_board_name( index )
20
+ Board.index_to_name(@names[index])
21
+ end
22
+ end
23
+
24
+ MOVES = %w{a1 a2 a3 b1 b2 b3 c1 c2 c3}
25
+ # Define constant INDICES
26
+ INDICES = Hash.new { |h, k| h[k] = MOVES.find_index(k) }
27
+
28
+ def self.name_to_index( name )# Receives "b2" and returns 4
29
+ INDICES[name]
30
+ end
31
+
32
+ def self.index_to_name( index ) # Receives the index, like 4 and returns "b2"
33
+ MOVES[index]
34
+ end
35
+
36
+ def initialize( squares )
37
+ @squares = squares # An array of Strings: [ " ", " ", " ", " ", "X", " ", " ", " ", "O"]
38
+ end
39
+
40
+ include SquaresContainer
41
+
42
+ def []( *indices )
43
+ if indices.size == 2 # board[1,2] is @squares[7]
44
+ super indices[0] + indices[1] * 3 # calls SquaresContainer [] method
45
+ elsif indices[0].is_a? Fixnum # board[7]
46
+ super indices[0]
47
+ else # board["b2"]
48
+ super Board.name_to_index(indices[0].to_s)
49
+ end
50
+ end
51
+
52
+ def []=(indice, value) # board["b2"] = "X"
53
+ m = Board.name_to_index(indice)
54
+ @squares[m] = value
55
+ end
56
+
57
+ HORIZONTALS = [ [0, 1, 2], [3, 4, 5], [6, 7, 8] ]
58
+ COLUMNS = [ [0, 3, 6], [1, 4, 7], [2, 5, 8] ]
59
+ DIAGONALS = [ [0, 4, 8], [2, 4, 6] ]
60
+ ROWS = HORIZONTALS + COLUMNS + DIAGONALS
61
+
62
+ def each_row
63
+ ROWS.each do |e|
64
+ yield Row.new(@squares.values_at(*e), e)
65
+ end
66
+ end
67
+
68
+ def moves
69
+ moves = [ ]
70
+ @squares.each_with_index do |s, i|
71
+ moves << Board.index_to_name(i) if s == " "
72
+ end
73
+ moves # returns the set of feasible moves [ "b3", "c2", ... ]
74
+ end
75
+
76
+ def won?
77
+ each_row do |row|
78
+ return "X" if row.xs == 3 # "X" wins
79
+ return "O" if row.os == 3 # "O" wins
80
+ end
81
+ return " " if blanks == 0 # tie
82
+ false
83
+ end
84
+
85
+ BOARD =<<EOS
86
+
87
+ +---+---+---+
88
+ a | 0 | 1 | 2 |
89
+ +---+---+---+
90
+ b | 3 | 4 | 5 |
91
+ +---+---+---+
92
+ c | 6 | 7 | 8 |
93
+ +---+---+---+
94
+ 1 2 3
95
+
96
+ EOS
97
+ def to_s
98
+ BOARD.gsub(/(\d)(?= \|)/) { |i| @squares[i.to_i] }
99
+ end
100
+
101
+ end
102
+ end
103
+
104
+
@@ -0,0 +1,10 @@
1
+ require "tictactoe_alu3286/player"
2
+
3
+ module TictactoeAlu3286
4
+ class DumbPlayer < Player
5
+ def move( board )
6
+ moves = board.moves
7
+ moves[rand(moves.size)]
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,30 @@
1
+ require "tictactoe_alu3286/player"
2
+
3
+ module TictactoeAlu3286
4
+ class HumanPlayer < Player
5
+ def move( board )
6
+ print board
7
+
8
+ moves = board.moves
9
+ print "Your move? (format: b3) "
10
+ move = $stdin.gets
11
+ until moves.include?(move.chomp.downcase)
12
+ print "Invalid move. Try again. "
13
+ move = $stdin.gets
14
+ end
15
+ move.chomp
16
+ end
17
+
18
+ def finish( final_board )
19
+ print final_board
20
+
21
+ if final_board.won? == @mark
22
+ print "Congratulations, you win.\n\n"
23
+ elsif final_board.won? == " "
24
+ print "Tie game.\n\n"
25
+ else
26
+ print "You lost tic-tac-toe?!\n\n"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,16 @@
1
+ module TictactoeAlu3286
2
+ class Player
3
+ def initialize( mark )
4
+ @mark = mark # "X" or "O" or " "
5
+ end
6
+
7
+ attr_reader :mark
8
+
9
+ def move( board )
10
+ raise NotImplementedError, "Player subclasses must define move()."
11
+ end
12
+
13
+ def finish( final_board )
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,42 @@
1
+ require "tictactoe_alu3286/player"
2
+
3
+ module TictactoeAlu3286
4
+ class SmartPlayer < Player
5
+ def move( board )
6
+ moves = board.moves
7
+
8
+ # If I have a win, take it. If he is threatening to win, stop it.
9
+ board.each_row do |row|
10
+ if row.blanks == 1 and (row.xs == 2 or row.os == 2)
11
+ (0..2).each do |e|
12
+ return row.to_board_name(e) if row[e] == " "
13
+ end
14
+ end
15
+ end
16
+
17
+ # Take the center if open.
18
+ return "b2" if moves.include? "b2"
19
+
20
+ # Defend opposite corners.
21
+ if board[0] != @mark and board[0] != " " and board[8] == " "
22
+ return "c3"
23
+ elsif board[8] != @mark and board[8] != " " and board[0] == " "
24
+ return "a1"
25
+ elsif board[2] != @mark and board[2] != " " and board[6] == " "
26
+ return "c1"
27
+ elsif board[6] != @mark and board[6] != " " and board[2] == " "
28
+ return "a3"
29
+ end
30
+
31
+ # Defend against the special case XOX on a diagonal.
32
+ if board.xs == 2 and board.os == 1 and board[4] == "O" and
33
+ (board[0] == "X" and board[8] == "X") or
34
+ (board[2] == "X" and board[6] == "X")
35
+ return %w{a2 b1 b3 c2}[rand(4)]
36
+ end
37
+
38
+ # Or make a random move.
39
+ moves[rand(moves.size)]
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ module TictactoeAlu3286
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,12 @@
1
+ require "tictactoe_alu3286"
2
+
3
+ describe TictactoeAlu3286::DumbPlayer do
4
+ before :each do
5
+ @dp = TictactoeAlu3286::DumbPlayer.new("X")
6
+ end
7
+
8
+ it "Debe existir un metodo move" do
9
+ @dp.respond_to?("move").should == true
10
+ end
11
+
12
+ end
@@ -0,0 +1,15 @@
1
+ require "tictactoe_alu3286"
2
+
3
+ describe TictactoeAlu3286::HumanPlayer do
4
+ before :each do
5
+ @hp = TictactoeAlu3286::HumanPlayer.new("X")
6
+ end
7
+
8
+ it "Debe existir un metodo move" do
9
+ @hp.respond_to?("move").should == true
10
+ end
11
+
12
+ it "Debe existir un metodo finish" do
13
+ @hp.respond_to?("finish").should == true
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ require "tictactoe_alu3286"
2
+
3
+ describe TictactoeAlu3286::SmartPlayer do
4
+ before :each do
5
+ @sp = TictactoeAlu3286::SmartPlayer.new("X")
6
+ end
7
+
8
+ it "Debe existir un metodo move" do
9
+ @sp.respond_to?("move").should == true
10
+ end
11
+
12
+ end
@@ -0,0 +1,12 @@
1
+ require "tictactoe_alu3286"
2
+ require "test/unit"
3
+
4
+ class TestDumbPlayer < Test::Unit::TestCase
5
+ def setup
6
+ @dp = TictactoeAlu3286::DumbPlayer.new("X")
7
+ end
8
+
9
+ def test_implements_move
10
+ assert_equal true, @dp.respond_to?("move")
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ require "tictactoe_alu3286"
2
+ require "test/unit"
3
+
4
+ class TestHumanPlayer < Test::Unit::TestCase
5
+ def setup
6
+ @hp = TictactoeAlu3286::HumanPlayer.new("X")
7
+ end
8
+
9
+ def test_implements_move
10
+ assert_equal true, @hp.respond_to?("move")
11
+ end
12
+
13
+ def test_implements_finish
14
+ assert_equal true, @hp.respond_to?("finish")
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ require "tictactoe_alu3286"
2
+ require "test/unit"
3
+
4
+ class TestSmartPlayer < Test::Unit::TestCase
5
+ def setup
6
+ @sp = TictactoeAlu3286::SmartPlayer.new("X")
7
+ end
8
+
9
+ def test_implements_move
10
+ assert_equal true, @sp.respond_to?("move")
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/tictactoe_alu3286/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["alu3286"]
6
+ gem.email = ["eaculed@gmail.com"]
7
+ gem.description = %q{Juego de tres en raya}
8
+ gem.summary = %q{Tres en raya}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "tictactoe_alu3286"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = TictactoeAlu3286::VERSION
17
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tictactoe_alu3286
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - alu3286
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-26 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Juego de tres en raya
15
+ email:
16
+ - eaculed@gmail.com
17
+ executables:
18
+ - tictactoe_game.rb
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - .travis.yml
24
+ - Gemfile
25
+ - Guardfile
26
+ - LICENSE
27
+ - README.md
28
+ - Rakefile
29
+ - bin/tictactoe_game.rb
30
+ - lib/.DS_Store
31
+ - lib/tictactoe_alu3286.rb
32
+ - lib/tictactoe_alu3286/board.rb
33
+ - lib/tictactoe_alu3286/dumbplayer.rb
34
+ - lib/tictactoe_alu3286/humanplayer.rb
35
+ - lib/tictactoe_alu3286/player.rb
36
+ - lib/tictactoe_alu3286/smartplayer.rb
37
+ - lib/tictactoe_alu3286/version.rb
38
+ - spec/dumbplayer_spec.rb
39
+ - spec/humanplayer_spec.rb
40
+ - spec/smartplayer_spec.rb
41
+ - test/tc_dumbplayer.rb
42
+ - test/tc_humanplayer.rb
43
+ - test/tc_smartplayer.rb
44
+ - tictactoe_alu3286.gemspec
45
+ homepage: ''
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.24
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Tres en raya
69
+ test_files:
70
+ - spec/dumbplayer_spec.rb
71
+ - spec/humanplayer_spec.rb
72
+ - spec/smartplayer_spec.rb
73
+ - test/tc_dumbplayer.rb
74
+ - test/tc_humanplayer.rb
75
+ - test/tc_smartplayer.rb