Friday, November 7, 2014

Kata: Unconditional rock, paper, scissors in Ruby

Yesterday Álvaro García (@alvarobiz) and I paired working on a possible solution to the Unconditional rock, paper, scissors kata that I facilitated in the recent SCBCN14 event.

This is the last version of the tests so far:

require File.join(File.dirname(__FILE__), "rock_paper_scissors")
require 'test/unit'
class TestRockPaperScissors < Test::Unit::TestCase
def setup
@game = Game.new
@paper = Paper.new
@rock = Rock.new
@scissors = Scissors.new
end
def test_paper_against_paper
assert_that(
GameHand.with(@paper).against(@paper)
.results_in("Two Papers, no one wins")
)
end
def test_paper_against_rock
assert_that(
GameHand.with(@paper).against(@rock)
.results_in("Paper wins against Rock")
)
end
def test_paper_against_scissors
assert_that(
GameHand.with(@paper).against(@scissors)
.results_in("Scissors wins against Paper")
)
end
def test_scissors_against_paper
assert_that(
GameHand.with(@scissors).against(@paper)
.results_in("Scissors wins against Paper")
)
end
def test_scissors_against_rock
assert_that(
GameHand.with(@scissors).against(@rock)
.results_in("Rock wins against Scissors")
)
end
def test_scissors_against_scissors
assert_that(
GameHand.with(@scissors).against(@scissors)
.results_in("Two Scissors, no one wins")
)
end
def test_rock_against_paper
assert_that(
GameHand.with(@rock).against(@paper)
.results_in("Paper wins against Rock")
)
end
def test_rock_against_rock
assert_that(
GameHand.with(@rock).against(@rock)
.results_in("Two Rocks, no one wins")
)
end
def test_rock_against_scissors
assert_that(
GameHand.with(@rock).against(@scissors)
.results_in("Rock wins against Scissors")
)
end
def assert_that(predicate_result)
assert(predicate_result)
end
end
class GameHand
def initialize(gesture)
@gesture1 = gesture
end
class << self
def with(gesture)
new(gesture)
end
end
def against(gesture)
@gesture2 = gesture
self
end
def results_in(expected)
result = Game.new().hand(@gesture1, @gesture2)
result.to_s == expected
end
end

And this is the last version of the code:

class Game
def hand(gesture1, gesture2)
gesture1.play_against(gesture2)
end
end
class Gesture
def win_against(other)
Victory.new(self, other)
end
def tie_with(other)
Tie.new(other)
end
end
class Paper < Gesture
def play_against(other)
other.play_against_paper(self)
end
def play_against_paper(paper)
tie_with(paper)
end
def play_against_scissors(scissors)
scissors.play_against_paper(self)
end
def play_against_rock(rock)
win_against(rock)
end
def to_s
"Paper"
end
def to_plural_s
to_s + "s"
end
end
class Rock < Gesture
def play_against(other)
other.play_against_rock(self)
end
def play_against_paper(paper)
paper.play_against_rock(self)
end
def play_against_scissors(scissors)
win_against(scissors)
end
def play_against_rock(rock)
tie_with(rock)
end
def to_s
"Rock"
end
def to_plural_s
to_s + "s"
end
end
class Scissors < Gesture
def play_against(other)
other.play_against_scissors(self)
end
def play_against_paper(paper)
win_against(paper)
end
def play_against_scissors(scissors)
tie_with(scissors)
end
def play_against_rock(rock)
rock.play_against_scissors(self)
end
def to_s
"Scissors"
end
def to_plural_s
to_s
end
end
class Victory
def initialize(winner, loser)
@winner = winner
@loser = loser
end
def to_s
@winner.to_s + " wins against " + @loser.to_s
end
end
class Tie
def initialize(gesture)
@gesture = gesture
end
def to_s
"Two " + @gesture.to_plural_s + ", no one wins"
end
end

We managed to write the code without having to use conditionals in any moment.

You can follow the process if you like since we did commits after every passing test and every refactoring.

You can check the code in this GitHub repository.

As usual it was a pleasure to do pair programming with Álvaro.

No comments:

Post a Comment