tres-raya 0.0.2

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.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
@@ -0,0 +1,8 @@
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
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in tres_raya.gemspec
4
+ gemspec
@@ -0,0 +1,5 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { "spec" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
data/README ADDED
@@ -0,0 +1,17 @@
1
+ Practica de Laboratorio #9: Creacion de una Gema
2
+
3
+ Tic-Tac-Toe (Tres en raya)
4
+
5
+ Clases para implementar el juego de tres en raya
6
+ Utiliza el concepto de herencia.
7
+ Hay modulos y mixins.
8
+
9
+ Clase desarrollada con rspec siguiendo la filosofia TDD
10
+ Contiene tambien pruebas unitarias Unit Testing
11
+ La clase se compila con la herramienta Travis de integracion continua.
12
+ Se comprueba la portabilidad entre distintas plataformas y versiones de Ruby.
13
+
14
+ Se deben poner los ficheros en spec para que se ejecuten ante
15
+ cualquier modificacion
16
+
17
+ Se ha creado una Gema con bundle
@@ -0,0 +1,21 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/clean'
3
+ #CLEAN.include('*.tmp')
4
+ CLOBBER.include('pkg/*.gem')
5
+
6
+ task :default => [:spec,:test]
7
+
8
+ desc "Run tres_raya.rb for tres_raya "
9
+ task :bin do
10
+ sh "ruby -Ilib bin/tres_raya.rb"
11
+ end
12
+
13
+ desc "Run rspec for tres_raya development"
14
+ task :spec do
15
+ sh "rspec -Ilib spec/tres_raya_spec.rb"
16
+ end
17
+
18
+ desc "Run test/tc_tres_raya.rb"
19
+ task :test do
20
+ sh "ruby -Ilib test/tc_tres_raya.rb"
21
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ require 'tres-raya'
3
+ # 1.9.3
4
+
5
+ if ARGV.size > 0 and ARGV[0] == "-d"
6
+ game = TresRaya::Game.new TresRaya::HumanPlayer, TresRaya::DumbPlayer
7
+ else
8
+ game = TresRaya::Game.new TresRaya::HumanPlayer, TresRaya::SmartPlayer
9
+ end
10
+ game.play
@@ -0,0 +1,21 @@
1
+ require 'tres_raya/board'
2
+ require 'tres_raya/player'
3
+ require 'tres_raya/human_player'
4
+ require 'tres_raya/dumb_player'
5
+ require 'tres_raya/smart_player'
6
+ require 'tres_raya/game'
7
+ require "tres_raya/version"
8
+
9
+ module TresRaya
10
+ end
11
+
12
+ if __FILE__ == $0
13
+ if ARGV.size > 0 and ARGV[0] == "-d"
14
+ game = TresRaya::Game.new TresRaya::HumanPlayer,
15
+ TresRaya::DumbPlayer
16
+ else
17
+ game = TresRaya::Game.new TresRaya::HumanPlayer,
18
+ TresRaya::SmartPlayer
19
+ end
20
+ game.play
21
+ end
@@ -0,0 +1,108 @@
1
+ require 'tres_raya/squares_container'
2
+
3
+ module TresRaya
4
+ class Board
5
+ attr_reader :squares
6
+
7
+ class Row
8
+ attr_reader :squares, :names
9
+
10
+ def initialize( squares, names )
11
+ @squares = squares
12
+ @names = names
13
+ end
14
+
15
+ include SquaresContainer
16
+
17
+ def to_board_name( index )
18
+ Board.index_to_name(@names[index])
19
+ end
20
+
21
+ def ==(other)
22
+ (@squares == other.squares) && (@names == other.names)
23
+ end
24
+ end
25
+
26
+ MOVES = %w{a1 a2 a3 b1 b2 b3 c1 c2 c3}
27
+ # Define constant INDICES
28
+ INDICES = Hash.new { |h, k| h[k] = MOVES.find_index(k) }
29
+
30
+ def self.name_to_index( name )# Receives "b2" and returns 4
31
+ INDICES[name]
32
+ end
33
+
34
+ def self.index_to_name( index ) # Receives the index, like 4 and returns "b2"
35
+ MOVES[index]
36
+ end
37
+
38
+ def initialize( squares )
39
+ @squares = squares # An array of Strings: [ " ", " ", " ", " ", "X", " ", " ", " ", "O"]
40
+ end
41
+
42
+ include SquaresContainer
43
+
44
+ def []( *indices )
45
+ if indices.size == 2 # board[1,2] is @squares[7]
46
+ super indices[0] + indices[1] * 3 # calls SquaresContainer [] method
47
+ elsif indices[0].is_a? Fixnum # board[7]
48
+ super indices[0]
49
+ else # board["b2"]
50
+ super Board.name_to_index(indices[0].to_s)
51
+ end
52
+ end
53
+
54
+ def []=(indice, value) # board["b2"] = "X"
55
+ m = Board.name_to_index(indice)
56
+ @squares[m] = value
57
+ end
58
+
59
+ HORIZONTALS = [ [0, 1, 2], [3, 4, 5], [6, 7, 8] ]
60
+ COLUMNS = [ [0, 3, 6], [1, 4, 7], [2, 5, 8] ]
61
+ DIAGONALS = [ [0, 4, 8], [2, 4, 6] ]
62
+ ROWS = HORIZONTALS + COLUMNS + DIAGONALS
63
+
64
+ def each_row
65
+ ROWS.each do |e|
66
+ yield Row.new(@squares.values_at(*e), e)
67
+ end
68
+ end
69
+
70
+ def moves
71
+ moves = [ ]
72
+ @squares.each_with_index do |s, i|
73
+ moves << Board.index_to_name(i) if s == " "
74
+ end
75
+ moves # returns the set of feasible moves [ "b3", "c2", ... ]
76
+ end
77
+
78
+ def won?
79
+ each_row do |row|
80
+ return "X" if row.xs == 3 # "X" wins
81
+ return "O" if row.os == 3 # "O" wins
82
+ end
83
+ return " " if blanks == 0 # tie
84
+ false
85
+ end
86
+
87
+ BOARD =<<EOS
88
+
89
+ +---+---+---+
90
+ a | 0 | 1 | 2 |
91
+ +---+---+---+
92
+ b | 3 | 4 | 5 |
93
+ +---+---+---+
94
+ c | 6 | 7 | 8 |
95
+ +---+---+---+
96
+ 1 2 3
97
+
98
+ EOS
99
+ def to_s
100
+ BOARD.gsub(/(\d)(?= \|)/) { |i| @squares[i.to_i] }
101
+ end
102
+
103
+ def ==(other)
104
+ (@squares == other.squares)
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,25 @@
1
+ module TresRaya
2
+ class DumbPlayer < Player
3
+ def move( board )
4
+ moves = board.moves
5
+ moves[rand(moves.size)]
6
+ end
7
+
8
+ def finish( final_board )
9
+ # print final_board
10
+
11
+ if final_board.won? == @mark
12
+ # print "Congratulations, you win.\n\n"
13
+ win = 1
14
+ elsif final_board.won? == " "
15
+ # print "Tie game.\n\n"
16
+ win = 0
17
+ else
18
+ # print "You lost tic-tac-toe?!\n\n"
19
+ win = -1
20
+ end
21
+ win
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ require 'tres_raya/board'
2
+
3
+ module TresRaya
4
+ class Game
5
+ def initialize( player1, player2, random = true )
6
+ if random and rand(2) == 1
7
+ @x_player = player2.new("X")
8
+ @o_player = player1.new("O")
9
+ else
10
+ @x_player = player1.new("X")
11
+ @o_player = player2.new("O")
12
+ end
13
+
14
+ @board = Board.new([" "] * 9)
15
+ end
16
+
17
+ attr_reader :x_player, :o_player
18
+
19
+ def play
20
+ until @board.won?
21
+ @board[@x_player.move(@board)] = @x_player.mark
22
+ break if @board.won?
23
+
24
+ @board[@o_player.move(@board)] = @o_player.mark
25
+ end
26
+
27
+ @o_player.finish @board
28
+ @x_player.finish @board
29
+
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ module TresRaya
2
+ class HumanPlayer < Player
3
+ def move( board )
4
+ print board
5
+
6
+ moves = board.moves
7
+ print "Your move? (format: b3) "
8
+ move = $stdin.gets
9
+ until moves.include?(move.chomp.downcase)
10
+ print "Invalid move. Try again. "
11
+ move = $stdin.gets
12
+ end
13
+ move.chomp
14
+ end
15
+
16
+ def finish( final_board )
17
+ print final_board
18
+
19
+ if final_board.won? == @mark
20
+ print "Congratulations, you win.\n\n"
21
+ elsif final_board.won? == " "
22
+ print "Tie game.\n\n"
23
+ else
24
+ print "You lost tic-tac-toe?!\n\n"
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ module TresRaya
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,57 @@
1
+ module TresRaya
2
+ class SmartPlayer < Player
3
+ def move( board )
4
+ moves = board.moves
5
+
6
+ # If I have a win, take it. If he is threatening to win, stop it.
7
+ board.each_row do |row|
8
+ if row.blanks == 1 and (row.xs == 2 or row.os == 2)
9
+ (0..2).each do |e|
10
+ return row.to_board_name(e) if row[e] == " "
11
+ end
12
+ end
13
+ end
14
+
15
+ # Take the center if open.
16
+ return "b2" if moves.include? "b2"
17
+
18
+ # Defend opposite corners.
19
+ if board[0] != @mark and board[0] != " " and board[8] == " "
20
+ return "c3"
21
+ elsif board[8] != @mark and board[8] != " " and board[0] == " "
22
+ return "a1"
23
+ elsif board[2] != @mark and board[2] != " " and board[6] == " "
24
+ return "c1"
25
+ elsif board[6] != @mark and board[6] != " " and board[2] == " "
26
+ return "a3"
27
+ end
28
+
29
+ # Defend against the special case XOX on a diagonal.
30
+ if board.xs == 2 and board.os == 1 and board[4] == "O" and
31
+ (board[0] == "X" and board[8] == "X") or
32
+ (board[2] == "X" and board[6] == "X")
33
+ return %w{a2 b1 b3 c2}[rand(4)]
34
+ end
35
+
36
+ # Or make a random move.
37
+ moves[rand(moves.size)]
38
+ end
39
+
40
+ def finish( final_board )
41
+ print final_board
42
+
43
+ if final_board.won? == @mark
44
+ print "Congratulations, you win.\n\n"
45
+ win = 1
46
+ elsif final_board.won? == " "
47
+ print "Tie game.\n\n"
48
+ win = 0
49
+ else
50
+ print "You lost tic-tac-toe?!\n\n"
51
+ win = -1
52
+ end
53
+ win
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,7 @@
1
+ module SquaresContainer
2
+ def []( index ) @squares[index] end
3
+
4
+ def blanks() @squares.find_all { |s| s == " " }.size end
5
+ def os() @squares.find_all { |s| s == "O" }.size end
6
+ def xs() @squares.find_all { |s| s == "X" }.size end
7
+ end
@@ -0,0 +1,3 @@
1
+ module TresRaya
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,36 @@
1
+ require 'tres-raya'
2
+
3
+ describe do
4
+ before :all do
5
+ @fila = TresRaya::Board::Row.new(["0","X",""],[0,1,2])
6
+ @board = TresRaya::Board.new([ " ", " ", " ", " ", "X", " ", " ", " ","O"])
7
+ @human_player = TresRaya::HumanPlayer.new("X")
8
+ @dumb_player = TresRaya::DumbPlayer.new("0")
9
+ @smart_player = TresRaya::SmartPlayer.new("0")
10
+ @gameD = TresRaya::Game.new TresRaya::SmartPlayer, TresRaya::DumbPlayer
11
+ end
12
+
13
+ it "Debe existir una clase para representar una fila del tablero" do
14
+ @fila.should == TresRaya::Board::Row.new(["0","X",""],[0,1,2])
15
+ end
16
+
17
+ it "Debe existir una clase para representar al tablero" do
18
+ @board.should == TresRaya::Board.new([ " ", " ", " ", " ", "X", " ", " ", " ","O"])
19
+ end
20
+
21
+ it "Debe existir una clase para representar al jugador humano" do
22
+ @human_player.mark.should == "X"
23
+ end
24
+
25
+ it "Debe existir una clase para representar un juego simple de la maquina" do
26
+ @dumb_player.mark.should == "0"
27
+ end
28
+
29
+ it "Debe existir una clase para representar un juego inteligente de la maquina" do
30
+ @smart_player.mark.should == "0"
31
+ end
32
+
33
+ it "Debe existir una clase para representar un juego" do
34
+ [-1,0,1].should include(@gameD.play)
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ require 'tres-raya'
2
+
3
+ require 'test/unit'
4
+
5
+ class TestTresRaya < Test::Unit::TestCase
6
+
7
+ def setup
8
+ # si se define una variable de instancia, el juego no se actualiza aleatoriamente porqu solo hay una
9
+ end
10
+
11
+ def teardown
12
+ #nada, la memoria se libera automaticamente
13
+ end
14
+
15
+ def test_play
16
+ score = []
17
+ 30.times do
18
+ ter_obj = TresRaya::Game.new TresRaya::DumbPlayer, TresRaya::DumbPlayer
19
+ score.push ter_obj.play
20
+ end
21
+ assert(score.uniq.length == 3, "score.uniq.length = #{score.uniq.length} score.length = #{score.length}")
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "tres_raya/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "tres-raya"
7
+ s.version = TresRaya::VERSION
8
+ s.authors = ["Coromoto Leon"]
9
+ s.email = ["cleon@ull.es"]
10
+ s.homepage = ""
11
+ s.summary = %q{Gema para Jugar al tres en raya}
12
+ s.description = %q{Juego de tres en raya}
13
+
14
+ s.rubyforge_project = "tres_raya"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tres-raya
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Coromoto Leon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-21 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70292343790680 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70292343790680
25
+ description: Juego de tres en raya
26
+ email:
27
+ - cleon@ull.es
28
+ executables:
29
+ - tres_en_raya.rb
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - .travis.yml
35
+ - Gemfile
36
+ - Guardfile
37
+ - README
38
+ - Rakefile
39
+ - bin/tres_en_raya.rb
40
+ - lib/tres-raya.rb
41
+ - lib/tres_raya/board.rb
42
+ - lib/tres_raya/dumb_player.rb
43
+ - lib/tres_raya/game.rb
44
+ - lib/tres_raya/human_player.rb
45
+ - lib/tres_raya/player.rb
46
+ - lib/tres_raya/smart_player.rb
47
+ - lib/tres_raya/squares_container.rb
48
+ - lib/tres_raya/version.rb
49
+ - spec/tres_raya_spec.rb
50
+ - test/tc_tres_raya.rb
51
+ - tres_raya.gemspec
52
+ homepage: ''
53
+ licenses: []
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project: tres_raya
72
+ rubygems_version: 1.8.10
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Gema para Jugar al tres en raya
76
+ test_files:
77
+ - spec/tres_raya_spec.rb
78
+ - test/tc_tres_raya.rb