Demo: Rock Paper Scissors
The robot plays rock-paper-scissors with the user. It counts down, chooses rock, paper, or scissors, moves its hand into the selected pose, and compares the result.
This demo runs in keyboard mode first, where the user enters their choice. A camera-assisted version using gesture detection may be added later. Do not describe the current version as hand-gesture recognition unless that is actually implemented.
What students learn
Students learn how robot behaviors can include randomness, user input, hand pose presets, branching logic, and a repeated game loop.
Hardware used
- Hand and finger servos
- Optional speaker for countdown
- Optional RealSense camera for a future camera-assisted mode
Concepts covered
- Random choice
- Hand pose presets
- Branching logic
- User interaction
- Game loop
- Optional vision classification
Run command
Starter code
This version uses a game loop so students can run multiple rounds without restarting. Each round is a clean sequence: countdown, choose, move, judge.
"""
Demo: Rock Paper Scissors
Purpose:
Play a round of rock-paper-scissors with the user. The robot picks randomly.
Important:
This version uses keyboard input for the user's choice.
A camera-assisted version can be added later using gesture detection.
Do not describe this as hand-recognition unless that is implemented.
"""
import random
from time import sleep
from swayform.motion import MotionClient
from swayform.audio import AudioPrompt
VALID_CHOICES = ["rock", "paper", "scissors"]
COUNTDOWN_SECONDS = 1.0
POSE_HOLD_SECONDS = 1.5
ROUNDS_TO_PLAY = 3
WINS_AGAINST = {
"rock": "scissors",
"scissors": "paper",
"paper": "rock",
}
def countdown(audio: AudioPrompt) -> None:
"""Say rock, paper, scissors aloud before the reveal."""
for word in ["Rock", "Paper", "Scissors", "Shoot!"]:
audio.say(word)
sleep(COUNTDOWN_SECONDS)
def get_user_choice() -> str:
"""Prompt the user and validate their choice."""
while True:
raw = input("Your move (rock / paper / scissors): ").strip().lower()
if raw in VALID_CHOICES:
return raw
print(f"Please enter one of: {', '.join(VALID_CHOICES)}")
def judge(robot: str, user: str) -> str:
"""Return 'robot', 'user', or 'tie'."""
if robot == user:
return "tie"
if WINS_AGAINST[robot] == user:
return "robot"
return "user"
def play_round(motion: MotionClient, audio: AudioPrompt) -> str:
"""Run one complete round. Returns winner: 'robot', 'user', or 'tie'."""
robot_choice = random.choice(VALID_CHOICES)
user_choice = get_user_choice()
countdown(audio)
motion.set_hand_pose("right_hand", robot_choice)
sleep(POSE_HOLD_SECONDS)
result = judge(robot_choice, user_choice)
print(f"Robot: {robot_choice} | You: {user_choice} | Result: {result}")
motion.set_hand_pose("right_hand", "relaxed")
return result
def main() -> None:
motion = MotionClient()
audio = AudioPrompt()
scores = {"robot": 0, "user": 0, "tie": 0}
motion.safe_pose("idle")
for round_num in range(1, ROUNDS_TO_PLAY + 1):
print(f"\n--- Round {round_num} ---")
winner = play_round(motion, audio)
scores[winner] += 1
print(f"\nFinal score — Robot: {scores['robot']} You: {scores['user']} Ties: {scores['tie']}")
motion.safe_pose("idle")
if __name__ == "__main__":
main()
Code walkthrough
get_user_choice loops until the user enters a valid move. This prevents the demo from crashing on a typo.judge("rock","scissors") in the Python shell and verify the result without running the full demo.Try changing this
- Make the game best of three rounds.
- Add sound effects or a countdown.
- Add head movement when the robot wins or loses.
- Add a scoreboard variable.
Hand poses should use tested finger positions. Do not over-close the fingers around a person's hand.
After Rock Paper Scissors, try Lab 07: Hand Pose Timing.