oxo 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 57d6bbd4f6bdd8eefcd5c93ec1db4645b9ee8cc3
4
+ data.tar.gz: 1a5f97f7dbb659b20951af02d1bddc5852b518f3
5
+ SHA512:
6
+ metadata.gz: 31d6af29d95dfd648649b8f55906d1909b86fa4b8f1ef1fa9ce8160c36fc75b3cebb7eafa2e7a2f4171742e48be48ad380ee618e7e2971594fdddb3e9b016302
7
+ data.tar.gz: 475eb3b11dc66209b9c5d4ca76be472dbdd7de717f081191b6de95057f20f349f41e85ec263a12151cb9a7c3af07b27ef7951a6739f705e46cc651be5807377e
@@ -0,0 +1,42 @@
1
+ oxo
2
+ ===
3
+
4
+ `oxo` is a command line Tic-tac-toe game written in [Ruby][ruby].
5
+
6
+ ## Getting Started
7
+
8
+ Start a game with
9
+
10
+ ``` sh
11
+ $ oxo
12
+ ```
13
+
14
+ and have fun!
15
+
16
+ ## Documentation
17
+
18
+ Use `oxo --help` to display a brief help message.
19
+
20
+ ## Installation
21
+
22
+ Use `gem install oxo` to install from RubyGems.org.
23
+
24
+ ## Requirements
25
+
26
+ - [Ruby][ruby] 2.0.0 or higher
27
+
28
+ ## Reporting Bugs
29
+
30
+ Report bugs on the `oxo` home page: <https://github.com/stomar/oxo/>
31
+
32
+ ## License
33
+
34
+ Copyright &copy; 2016 Marcus Stollsteimer
35
+
36
+ `oxo` is free software: you can redistribute it and/or modify it under
37
+ the terms of the GNU General Public License version 3 or later (GPLv3+),
38
+ see [www.gnu.org/licenses/gpl.html](http://www.gnu.org/licenses/gpl.html).
39
+ There is NO WARRANTY, to the extent permitted by law.
40
+
41
+
42
+ [ruby]: https://www.ruby-lang.org/
@@ -0,0 +1,27 @@
1
+ require "rake/testtask"
2
+
3
+
4
+ def gemspec_file
5
+ "oxo.gemspec"
6
+ end
7
+
8
+
9
+ task :default => [:test]
10
+
11
+ Rake::TestTask.new do |t|
12
+ t.pattern = "test/**/test_*.rb"
13
+ t.verbose = true
14
+ t.warning = true
15
+ end
16
+
17
+
18
+ desc "Build gem"
19
+ task :build do
20
+ sh "gem build #{gemspec_file}"
21
+ end
22
+
23
+
24
+ desc "Remove generated files"
25
+ task :clean do
26
+ FileUtils.rm(Dir.glob("*.gem"))
27
+ end
data/bin/oxo ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "oxo"
4
+
5
+ OXO::Application.new.run
@@ -0,0 +1,175 @@
1
+ require "optparse"
2
+
3
+ require "oxo/version"
4
+ require "oxo/board"
5
+ require "oxo/computer"
6
+ require "oxo/human"
7
+
8
+ # == Name
9
+ #
10
+ # oxo - a command line Tic-tac-toe game
11
+ #
12
+ # == See also
13
+ #
14
+ # Use <tt>oxo --help</tt> to display a brief help message.
15
+ #
16
+ # The full documentation for +oxo+ is available on the
17
+ # project home page.
18
+ #
19
+ # == Author
20
+ #
21
+ # Copyright (C) 2016 Marcus Stollsteimer
22
+ #
23
+ # License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
24
+ #
25
+ module OXO
26
+
27
+ PROGNAME = "oxo"
28
+
29
+ COPYRIGHT = <<-copyright.gsub(/^ +/, "")
30
+ Copyright (C) 2016 Marcus Stollsteimer.
31
+ License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
32
+ This is free software: you are free to change and redistribute it.
33
+ There is NO WARRANTY, to the extent permitted by law.
34
+ copyright
35
+
36
+
37
+ class Optionparser
38
+
39
+ # Parses the command line options from +argv+.
40
+ # (+argv+ is cleared).
41
+ # Might print out help or version information.
42
+ #
43
+ # +argv+ - array with the command line options
44
+ #
45
+ # Returns a hash containing the option parameters.
46
+ def self.parse!(argv)
47
+
48
+ options = {
49
+ :delay => 0
50
+ }
51
+
52
+ opt_parser = OptionParser.new do |opt|
53
+ opt.banner = "Usage: #{PROGNAME} [options]"
54
+ opt.separator %q{
55
+ oxo is a command line Tic-tac-toe game.
56
+
57
+ Options:
58
+ }.gsub(/^ +/, "")
59
+
60
+ # process --version and --help first,
61
+ # exit successfully (GNU Coding Standards)
62
+ opt.on_tail("-h", "--help", "Print a brief help message and exit.") do
63
+ puts opt_parser
64
+ puts "\nReport bugs on the #{PROGNAME} home page: <#{HOMEPAGE}>"
65
+ exit
66
+ end
67
+
68
+ opt.on_tail("-v", "--version",
69
+ "Print a brief version information and exit.") do
70
+ puts "#{PROGNAME} #{VERSION}"
71
+ puts COPYRIGHT
72
+ exit
73
+ end
74
+
75
+ opt.on("-d", "--delay SECONDS", Float,
76
+ "Set delay time for oxo's moves.") do |d|
77
+ options[:delay] = d
78
+ end
79
+
80
+ opt.separator ""
81
+ end
82
+ opt_parser.parse!(argv)
83
+
84
+ # nothing should be left in argv
85
+ raise(ArgumentError, "wrong number of arguments") unless argv.empty?
86
+
87
+ options
88
+ end
89
+ end
90
+
91
+
92
+ class Application
93
+
94
+ ERRORCODE = {:general => 1, :usage => 2}
95
+
96
+ def initialize
97
+ begin
98
+ options = Optionparser.parse!(ARGV)
99
+ rescue => e
100
+ usage_fail(e.message)
101
+ end
102
+
103
+ @delay = options[:delay]
104
+ end
105
+
106
+ def run
107
+ board = Board.new
108
+
109
+ case beginning_side
110
+ when :quit
111
+ return
112
+ when :human
113
+ players = [Human.new(:X), Computer.new(:O, delay: @delay)]
114
+ puts board
115
+ when :computer
116
+ players = [Computer.new(:X, delay: @delay), Human.new(:O)]
117
+ end
118
+
119
+ game_over = false
120
+
121
+ until game_over
122
+ player = players.first
123
+ move = player.make_move(board)
124
+
125
+ break if move == :quit
126
+
127
+ board.place(player.color, move[0], move[1])
128
+
129
+ puts board
130
+ puts "Move of #{player.name} was: #{(move[0] - 1) * 3 + move[1]}"
131
+
132
+ if board.win?(player.color)
133
+ puts "#{player.name} wins!"
134
+ game_over = true
135
+ elsif board.full?
136
+ puts "It's a draw."
137
+ game_over = true
138
+ end
139
+
140
+ players.rotate!
141
+ end
142
+ end
143
+
144
+ private
145
+
146
+ def beginning_side
147
+ choices = {
148
+ "1" => :human, "" => :human,
149
+ "2" => :computer,
150
+ "0" => :quit, "q" => :quit
151
+ }
152
+
153
+ answer = nil
154
+ until choices.keys.include?(answer)
155
+ print "Beginning side (1=Human, 2=Computer, 0/q=quit)? "
156
+ answer = gets.chomp
157
+ end
158
+
159
+ choices[answer]
160
+ end
161
+
162
+ # Prints an error message and exits.
163
+ def general_fail(message)
164
+ warn "#{PROGNAME}: #{message}"
165
+ exit ERRORCODE[:general]
166
+ end
167
+
168
+ # Prints an error message and a short help information, then exits.
169
+ def usage_fail(message)
170
+ warn "#{PROGNAME}: #{message}"
171
+ warn "Use `#{PROGNAME} --help' for valid options."
172
+ exit ERRORCODE[:usage]
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,72 @@
1
+ module OXO
2
+ class Board
3
+
4
+ attr_accessor :rows, :cols
5
+
6
+ def initialize
7
+ @rows, @cols = 3, 3
8
+ @board = Array.new(@rows) { Array.new(@cols) }
9
+ end
10
+
11
+ def legal_move?(row, col)
12
+ on_board?(row, col) && !piece_at(row, col)
13
+ end
14
+
15
+ def place(color, row, col)
16
+ return unless legal_move?(row, col)
17
+ @board[row-1][col-1] = color
18
+ end
19
+
20
+ def legal_moves
21
+ empty_squares = []
22
+
23
+ 1.upto(rows) do |row|
24
+ 1.upto(cols) do |col|
25
+ empty_squares << [row, col] unless piece_at(row, col)
26
+ end
27
+ end
28
+
29
+ empty_squares
30
+ end
31
+
32
+ def full?
33
+ !@board.flatten.include? nil
34
+ end
35
+
36
+ def win?(color)
37
+ @board.each {|row| return true if row.uniq == [color] }
38
+ @board.transpose.each {|col| return true if col.uniq == [color] }
39
+ return true if @board.flatten.values_at(0, 4, 8).uniq == [color]
40
+ return true if @board.flatten.values_at(2, 4, 6).uniq == [color]
41
+
42
+ false
43
+ end
44
+
45
+ def to_s
46
+ output = "\n"
47
+ hline = "+---" * @cols << "+\n"
48
+
49
+ characters = @board.map {|row| row.map {|pos| pos.to_s.ljust(1) } }
50
+
51
+ output << hline
52
+ characters.each do |row|
53
+ output << "| " << row.join(" | ") << " |" << "\n"
54
+ output << hline
55
+ end
56
+
57
+ output + "\n"
58
+ end
59
+
60
+ private
61
+
62
+ def on_board?(row, col)
63
+ (1..@rows).include?(row) && (1..@cols).include?(col)
64
+ end
65
+
66
+ def piece_at(row, col)
67
+ return unless on_board?(row, col)
68
+
69
+ @board[row-1][col-1]
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,21 @@
1
+ module OXO
2
+ class Computer
3
+
4
+ attr_reader :color
5
+
6
+ def initialize(color, delay: 0)
7
+ @color = color
8
+ @delay = delay
9
+ end
10
+
11
+ def name
12
+ "oxo"
13
+ end
14
+
15
+ def make_move(board)
16
+ sleep @delay
17
+
18
+ board.legal_moves.sample
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,46 @@
1
+ module OXO
2
+ class Human
3
+
4
+ attr_reader :color
5
+
6
+ def initialize(color)
7
+ @color = color
8
+ end
9
+
10
+ def name
11
+ "Human"
12
+ end
13
+
14
+ def make_move(board)
15
+ move = :illegal
16
+
17
+ while move == :illegal
18
+ print "Your move (1...9, 0/q=quit)? "
19
+ answer = gets.chomp
20
+
21
+ move = parse_answer(answer, board)
22
+
23
+ puts "Illegal move: #{answer}" if move == :illegal
24
+ end
25
+
26
+ move
27
+ end
28
+
29
+ private
30
+
31
+ def parse_answer(answer, board)
32
+ case answer
33
+ when "0", "q", "quit"
34
+ :quit
35
+ when /\d/
36
+ number = answer.to_i
37
+ row = (number - 1) / board.rows + 1
38
+ col = (number - 1) % board.cols + 1
39
+
40
+ board.legal_move?(row, col) ? [row, col] : :illegal
41
+ else
42
+ :illegal
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,5 @@
1
+ module OXO
2
+ VERSION = "0.1.0"
3
+ DATE = "2016-04-27"
4
+ HOMEPAGE = "https://github.com/stomar/oxo/"
5
+ end
@@ -0,0 +1,40 @@
1
+ require_relative "lib/oxo/version"
2
+
3
+ version = OXO::VERSION
4
+ date = OXO::DATE
5
+ homepage = OXO::HOMEPAGE
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "oxo"
9
+ s.version = version
10
+ s.date = date
11
+
12
+ s.summary = "oxo is a command line Tic-tac-toe game."
13
+ s.description = s.summary
14
+
15
+ s.authors = ["Marcus Stollsteimer"]
16
+ s.email = "sto.mar@web.de"
17
+ s.homepage = homepage
18
+
19
+ s.license = "GPL-3.0"
20
+
21
+ s.required_ruby_version = ">= 2.0.0"
22
+
23
+ s.add_development_dependency "rake", "~> 11.1"
24
+ s.add_development_dependency "minitest", "~> 5.8"
25
+
26
+ s.executables = ["oxo"]
27
+ s.bindir = "bin"
28
+
29
+ s.require_paths = ["lib"]
30
+
31
+ s.files = %w[
32
+ oxo.gemspec
33
+ README.md
34
+ Rakefile
35
+ ] +
36
+ Dir.glob("{bin,lib,test}/**/*")
37
+
38
+ s.extra_rdoc_files = %w[README.md]
39
+ s.rdoc_options = ["--charset=UTF-8", "--main=README.md"]
40
+ end
@@ -0,0 +1,15 @@
1
+ require "minitest/autorun"
2
+ require "oxo/board"
3
+
4
+
5
+ describe OXO::Board do
6
+
7
+ before do
8
+ @board = OXO::Board.new
9
+ end
10
+
11
+ it "should have the correct size" do
12
+ @board.rows.must_equal 3
13
+ @board.cols.must_equal 3
14
+ end
15
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oxo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Marcus Stollsteimer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '11.1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '11.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.8'
41
+ description: oxo is a command line Tic-tac-toe game.
42
+ email: sto.mar@web.de
43
+ executables:
44
+ - oxo
45
+ extensions: []
46
+ extra_rdoc_files:
47
+ - README.md
48
+ files:
49
+ - README.md
50
+ - Rakefile
51
+ - bin/oxo
52
+ - lib/oxo.rb
53
+ - lib/oxo/board.rb
54
+ - lib/oxo/computer.rb
55
+ - lib/oxo/human.rb
56
+ - lib/oxo/version.rb
57
+ - oxo.gemspec
58
+ - test/test_board.rb
59
+ homepage: https://github.com/stomar/oxo/
60
+ licenses:
61
+ - GPL-3.0
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options:
65
+ - "--charset=UTF-8"
66
+ - "--main=README.md"
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 2.0.0
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 2.5.1
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: oxo is a command line Tic-tac-toe game.
85
+ test_files: []