Rock Paper Scissors
Level: Beginner 15–30 minConcepts: Algorithms
Solutions: C# | TypeScript | Python
Rock Paper Scissors is a game involving two players making pre-defined hand gestures at each other. The gesture that each player uses is played against the other, with a winner being decided based on the rules being used.
The three gestures used in base Rock Paper Scissors are… well… rock, paper, and scissors. The way these are scored is as such: Rock beats Scissors, Scissors beats Paper, and Paper beats Rock. It gets a lot more complicated when you introduce new gestures, but let’s keep it simple for now.
Now create a backend for the game that we can use to hook up to our many game clients we’re going to be creating.
Test Cases
| Player Move | Opponent Move | Result |
|---|---|---|
| Paper | Scissors | Player Loses |
| Paper | Paper | Tie |
| Rock | Scissors | Player Wins |
| Rock | Paper | Player Loses |
| Rock | Rock | Tie |
| Scissors | Paper | Player Wins |
| Scissors | Rock | Player Loses |
| Scissors | Scissors | Tie |
Bonus
Extend the game engine to include the rules for Rock, Paper, Scissors and Spock. The new moves to include are:
- Spock smashes Scissors
- Paper disproves Spock
- Spock vaporizes Rock
After implementing the additional rules make sure your code has no if statements.
Reference Walkthrough
Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/rock-paper-scissors. Nine scenarios — the full 3×3 matrix of plays from player 1’s perspective — are shared across all three languages, each a single pure function decide(Play, Play) → Outcome. The Spock extension and the no-if-statements constraint from the bonus section are intentionally out of scope for the reference; the three-way base game is sufficient to demonstrate the F1 shape with typed enums.
- C# (.NET 8, xUnit, FluentAssertions 6.12.0) — walkthrough
- TypeScript (Node 20, Vitest 1.6, TS 5 strict) — walkthrough
- Python (3.11, pytest) — walkthrough
This kata ships in Agent Full-Bake mode at high gear (F1 tier): the algorithm is small enough to land as one commit per language, with a brief walkthrough noting there are no builders — but the plays and outcomes are modelled as typed enums (C# enum, TypeScript string-literal unions, Python StrEnum) rather than bare strings. The closed set of three plays and three outcomes is the ubiquitous language, and typed enums prevent "Rock" vs "rock" drift at call sites. See the repo’s Gears section for when high gear is the right call.
Related reading
- Katas Are Rehearsal, Not Performance
You don't practice TDD on production code. You practice on katas and bring the muscle memory to production. The gap between knowing TDD and doing TDD is reps. - The Contract Test Is the Only Witness the Agent Cannot Author
A test the agent wrote against code the same agent wrote shares the agent's blind spot: a misunderstanding in the implementation becomes a matching misunderstanding in the test, the bar goes green, and the bug ships certified. Consumer-driven contract tests are the only category where a second team publishes the assertion the first team has to satisfy. That separation of authorship is exactly what tamper-resistant test design demanded, applied at the integration seam. - Cohesion Is the Coverage of the Agent Era
Agent-generated codebases pass every structural-modularity metric while fragmenting the domain concept the team was trying to encode. Coverage measured whether a line ran. Mutation score measured whether an assertion pinned behavior. Cohesion is the next axis, and it measures whether the codebase's concepts are traversable end-to-end.