diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cf6b96e --- /dev/null +++ b/LICENSE @@ -0,0 +1,3 @@ +== cb + +Put appropriate LICENSE for your project here. diff --git a/README b/README new file mode 100644 index 0000000..f853101 --- /dev/null +++ b/README @@ -0,0 +1,3 @@ +== cb + +You should document your project here. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..58a7ede --- /dev/null +++ b/Rakefile @@ -0,0 +1,50 @@ +# +# To change this template, choose Tools | Templates +# and open the template in the editor. + + +require 'rubygems' +require 'rake' +require 'rake/clean' +require 'rake/gempackagetask' +require 'rake/rdoctask' +require 'rake/testtask' +require 'spec/rake/spectask' + +spec = Gem::Specification.new do |s| + s.name = 'cb' + s.version = '0.0.1' + s.has_rdoc = true + s.extra_rdoc_files = ['README', 'LICENSE'] + s.summary = 'Your summary here' + s.description = s.summary + s.author = '' + s.email = '' + # s.executables = ['your_executable_here'] + s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,spec}/**/*") + s.require_path = "lib" + s.bindir = "bin" +end + +Rake::GemPackageTask.new(spec) do |p| + p.gem_spec = spec + p.need_tar = true + p.need_zip = true +end + +Rake::RDocTask.new do |rdoc| + files =['README', 'LICENSE', 'lib/**/*.rb'] + rdoc.rdoc_files.add(files) + rdoc.main = "README" # page to start on + rdoc.title = "cb Docs" + rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder + rdoc.options << '--line-numbers' +end + +Rake::TestTask.new do |t| + t.test_files = FileList['test/**/*.rb'] +end + +Spec::Rake::SpecTask.new do |t| + t.spec_files = FileList['spec/**/*.rb'] +end \ No newline at end of file diff --git a/bin/codebreaker b/bin/codebreaker new file mode 100755 index 0000000..89944d0 --- /dev/null +++ b/bin/codebreaker @@ -0,0 +1,3 @@ +#! /usr/bin/env ruby +require 'codebreaker/game' +require 'codebreaker/generator' diff --git a/features/codebreaker_starts_game.feature b/features/codebreaker_starts_game.feature new file mode 100644 index 0000000..b750055 --- /dev/null +++ b/features/codebreaker_starts_game.feature @@ -0,0 +1,11 @@ +Feature: code-breaker starts game + + As a code-breaker + I want to start a game + So that I can break the code + + Scenario: start game + Given I am not yet playing + When I start a new game + Then I should see "Welcome to Codebreaker!" + And I should see "Enter guess:" \ No newline at end of file diff --git a/features/codebreaker_submits_guess.feature b/features/codebreaker_submits_guess.feature new file mode 100644 index 0000000..7594979 --- /dev/null +++ b/features/codebreaker_submits_guess.feature @@ -0,0 +1,50 @@ +Feature: code-breaker submits guess + + The code-breaker submits a guess of four colored + pegs. The game marks the guess with black and + white "marker" pegs. + + For each peg in the guess that matches the color + and position of a peg in the secret code, the + mark includes one black peg. For each additional + peg in the guess that matches the color but not + the position of a peg in the secret code, a + white peg is added to the mark. + + Scenario Outline: submit guess + Given the secret code is + When I guess + Then the mark should be + + Scenarios: all colors correct + | code | guess | mark | + | r g y c | r g y c | bbbb | + | r g y c | r g c y | bbww | + | r g y c | y r g c | bwww | + | r g y c | c r g y | wwww | + + Scenarios: 3 colors correct + | code | guess | mark | + | r g y c | w g y c | bbb | + | r g y c | w r y c | bbw | + | r g y c | w r g c | bww | + | r g y c | w r g y | www | + + Scenarios: 2 colors correct + | code | guess | mark | + | r g y c | w g w c | bb | + | r g y c | w r w c | bw | + | r g y c | g w c w | ww | + + Scenarios: 1 color correct + | code | guess | mark | + | r g y c | r w w w | b | + | r g y c | w w r w | w | + + Scenarios: dups in guess match color in code + | code | guess | mark | + | r y g c | r y g g | bbb | + | r y g c | r y c c | bbb | + | r y g c | g y r g | bww | + + diff --git a/features/game_generates_secret_code.feature b/features/game_generates_secret_code.feature new file mode 100644 index 0000000..a58269c --- /dev/null +++ b/features/game_generates_secret_code.feature @@ -0,0 +1,11 @@ +Feature: game generates random secret code + In order to keep the codebreaker game interesting + I want the game to generate a random secret code each time I play + + Scenario: 10,000 games + Given 6 colors + And 4 positions + When I play 10,000 games + Then each color should appear between 1500 and 1800 times in each position + And each color should appear no more than once in each secret code + diff --git a/features/step_definitions/codebreaker_steps.rb b/features/step_definitions/codebreaker_steps.rb new file mode 100644 index 0000000..e4133c0 --- /dev/null +++ b/features/step_definitions/codebreaker_steps.rb @@ -0,0 +1,67 @@ +def messenger + @messenger ||= StringIO.new +end + +def game + @game ||= Codebreaker::Game.new(messenger) +end + +def messages_should_include(message) + messenger.string.split("\n").should include(message) +end + + +def fixnum_from(string) + string.scan(/\d/).join.to_i +end + + +Given /^I am not yet playing$/ do +end + + +Given /^the secret code is (. . . .)$/ do |code| + game.start(stub('generator', :code => code.split)) +end + + +When /^I guess (. . . .)$/ do |code| + game.guess(code.split) +end + + +When /^I start a new game$/ do + game.start(stub('generator', :code => %[r g y c])) +end + + +Then /^I should see "([^\"]*)"$/ do |message| + messages_should_include(message) +end + +Then /^the mark should be (.*)$/ do |mark| + messages_should_include(mark) +end + +Given /^6 colors$/ do +end + +Given /^4 positions$/ do +end + + + +When /^I play (.*) games$/ do |number| + generator = Codebreaker::Generator.new + fixnum_from(number).times do + game.start(generator) + end +end + +Then /^each color should appear between 1500 and 1800 times in each position$/ do + pending +end + +Then /^each color should appear no more than once in each secret code$/ do + pending +end diff --git a/features/support/env.rb b/features/support/env.rb new file mode 100644 index 0000000..1044f8e --- /dev/null +++ b/features/support/env.rb @@ -0,0 +1,3 @@ +$LOAD_PATH << File.join(File.dirname(__FILE__),"..","..","lib") +require 'codebreaker' +require 'spec/stubs/cucumber' \ No newline at end of file diff --git a/lib/codebreaker.rb b/lib/codebreaker.rb new file mode 100644 index 0000000..0be55c3 --- /dev/null +++ b/lib/codebreaker.rb @@ -0,0 +1 @@ +require 'codebreaker/game' \ No newline at end of file diff --git a/lib/codebreaker/game.rb b/lib/codebreaker/game.rb new file mode 100644 index 0000000..83c5d54 --- /dev/null +++ b/lib/codebreaker/game.rb @@ -0,0 +1,26 @@ +module Codebreaker + class Game + def initialize(messenger) + @messenger = messenger + end + + def start(generator) + @code = generator.code + @messenger.puts "Welcome to Codebreaker!" + @messenger.puts "Enter guess:" + end + + def guess(guess) + result = [nil,nil,nil,nil] + guess.each_with_index do |peg, index| + if @code[index] == peg + result[index] = "b" + elsif @code.include?(peg) + result[@code.index(peg)] ||= "w" + end + end + @messenger.puts result.compact.sort.join + end + + end +end \ No newline at end of file diff --git a/lib/generator.rb b/lib/generator.rb new file mode 100644 index 0000000..1215cdf --- /dev/null +++ b/lib/generator.rb @@ -0,0 +1,6 @@ +module Codebreaker + class Generator + def code + end + end +end diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/nbproject/private/rake-d.txt b/nbproject/private/rake-d.txt new file mode 100644 index 0000000..97346a1 --- /dev/null +++ b/nbproject/private/rake-d.txt @@ -0,0 +1,19 @@ +clean=Remove any temporary products. +clobber=Remove any generated file. +clobber_package=Remove package products +clobber_rdoc=Remove rdoc products +doc= +doc/rdoc= +doc/rdoc/index.html= +gem=Build the gem file cb-0.0.1.gem +package=Build all the packages +pkg= +pkg/cb-0.0.1= +pkg/cb-0.0.1.gem= +pkg/cb-0.0.1.tgz= +pkg/cb-0.0.1.zip= +rdoc=Build the rdoc HTML Files +repackage=Force a rebuild of the package files +rerdoc=Force a rebuild of the RDOC files +spec=Run specs +test=Run tests diff --git a/nbproject/project.properties b/nbproject/project.properties new file mode 100644 index 0000000..454d35a --- /dev/null +++ b/nbproject/project.properties @@ -0,0 +1,6 @@ +main.file= +platform.active=Ruby +source.encoding=UTF-8 +spec.src.dir=spec +src.dir=lib +test.src.dir=test diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..7f0735a --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,16 @@ + + + org.netbeans.modules.ruby.rubyproject + + + cb + + + + + + + + + + diff --git a/spec/codebreaker/game_spec.rb b/spec/codebreaker/game_spec.rb new file mode 100644 index 0000000..8088270 --- /dev/null +++ b/spec/codebreaker/game_spec.rb @@ -0,0 +1,65 @@ +require File.join(File.dirname(__FILE__), "..","spec_helper") + +module Codebreaker + describe Game do + before(:each) do + @messenger = mock("messenger").as_null_object + @game = Game.new(@messenger) + end + + context "starting up" do + + it "should send a welcome message" do + @messenger.should_receive(:puts).with("Welcome to Codebreaker!") + @game.start(stub('generator', :code => %w[r g y c])) + end + + it "should prompt for the first guess" do + @messenger.should_receive(:puts).with("Enter guess:") + @game.start(stub('generator', :code => %w[r g y c])) + end + end + + context "marking a guess" do + context "with all 4 colors correct in the correct places" do + it "should mark the guess with bbbb" do + @game.start(stub('generator', :code => %w[r g y c])) + @messenger.should_receive(:puts).with("bbbb") + @game.guess(%w[r g y c]) + end + end + context "with all 4 colors correct and 2 in the correct places" do + it "should mark the guess with bbww" do + @game.start(stub('generator', :code => %w[r g y c])) + @messenger.should_receive(:puts).with("bbww") + @game.guess(%w[r g c y]) + end + end + context "with all 4 colors correct and 1 in the correct place" do + it "should mark the guess with bwww" do + @game.start(stub('generator', :code => %w[r g y c])) + @messenger.should_receive(:puts).with("bwww") + @game.guess(%w[y r g c]) + end + end + context "with three colors correct in the correct places" do + it "should mark the guess with bbb" do + @game.start(stub('generator', :code => %w[r g y c])) + @messenger.should_receive(:puts).with("bbb") + @game.guess(%w[r g y w]) + end + end + context "with duplicates in the guess that match a peg in the code" do + context "by color and position" do + it "should add a single b to the mark" do + @game.start(stub('generator', :code => %w[r y g c])) + @messenger.should_receive(:puts).with("bbb") + @game.guess(%w[r y g g]) + end + end + end + end + end +end + + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..7527914 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,3 @@ +$LOAD_PATH << File.join(File.dirname(__FILE__),"..","lib") +require 'spec' +require 'codebreaker' \ No newline at end of file