Back

Activity 3.3 Designing with Methods: Stepwise Refinement

divider

Introduction

Designing with Methods

Breaking Down Problems Step by Step

What Is Stepwise Refinement?

Stepwise refinement is the process of starting with a broad goal and gradually dividing it into smaller, more manageable tasks.

Each step adds more detail until your program is complete and ready to run.

Why Use Stepwise Refinement?

  • Organization: Plan before coding. Avoid writing everything in main().
  • Focus: Build and test one small part at a time.
  • Reusability: Each method can be reused or replaced later.
  • Debugging: When something breaks, you know exactly where to look.

Example of Refinement

Suppose we want to build a simple dice game. Instead of writing the whole game at once, we can break it down:

  1. Roll a single die
  2. Roll two dice and calculate the total
  3. Apply the game rules for a round
  4. Repeat rounds until the player quits

Each step becomes a method. Together, they form a complete game.

Our Goal

We'll design a simplified version of the dice game Craps using stepwise refinement.

Each method will handle one small, focused task to make the code easier to test and read.

'F' → Fullscreen

Objectives

  • icon Apply stepwise refinement to design a small game.
  • icon Use parameters and return values to control program flow.
  • icon Refactor working code into clean, reusable methods.
divider

Activity Tasks

  • icon Create a new Java file named CrapsGame.
  • icon Build and run after each step. Do not skip ahead.
divider

Task 1: Roll a Single Die (print only)

  • icon Implement rollDie() that prints the die result.
  • icon Call it several times from main().
Program.java
import java.util.Scanner;
public class Program
{
public static void main(String[] args)
{
System.out.println("--- CRAPS ---");
// Call several times to verify randomness
rollDie();
rollDie();
rollDie();
}
// Step 1: print the die result (no return yet)
static void rollDie()
{
int die = (int)(Math.random() * 6) + 1;
System.out.println("Rolled: " + die);
}
}
divider

Task 2: Return Instead of Print

  • icon Modify rollDie() to return the value.
  • icon Print in main() after the call.
Program.java
import java.util.Scanner;
public class Program
{
public static void main(String[] args)
{
System.out.println("--- CRAPS ---");
int d1 = rollDie();
int d2 = rollDie();
System.out.println("You rolled: " + d1 + " and " + d2);
}
// Step 2: now return the value instead of printing
static int rollDie()
{
return (int)(Math.random() * 6) + 1;
}
}
divider

Task 3: Roll Two Dice

  • icon Create rollDice() that calls rollDie() twice, prints the breakdown, and returns the total.
  • icon Create promptRoll() for user input.
Program.java
import java.util.Scanner;
public class Program
{
public static void main(String[] args)
{
System.out.println("--- CRAPS ---");
promptRoll();
int total = rollDice();
System.out.println("Total: " + total); // Test variable for correctness
}
static int rollDie()
{
return (int)(Math.random() * 6) + 1;
}
// Step 3: compose method to roll two dice
static int rollDice()
{
int die1 = rollDie();
int die2 = rollDie();
int total = die1 + die2;
System.out.println("You rolled " + die1 + " + " + die2 + " = " + total);
return total;
}
// Roll dice input
static void promptRoll()
{
Scanner input = new Scanner(System.in);
System.out.print("Press Enter to roll...");
input.nextLine(); // simple pause
}
}
divider

Task 4: Come-Out Roll Rules

  • icon Write evaluateComeOutRoll(int roll) to print the outcome and return whether the round is over.
  • icon If the round continues, set point = roll.
Program.java
import java.util.Scanner;
public class Program
{
public static void main(String[] args)
{
System.out.println("--- CRAPS ---");
int point = 0;
promptRoll();
int roll = rollDice();
boolean roundOver = evaluateComeOutRoll(roll);
if (!roundOver)
{
point = roll;
System.out.println("The point is now " + point + ".");
// Next task: loop while not over and resolve the point.
}
}
static int rollDie()
{
return (int)(Math.random() * 6) + 1;
}
static int rollDice()
{
5 collapsed lines
int d1 = rollDie();
int d2 = rollDie();
int total = d1 + d2;
System.out.println("You rolled " + d1 + " + " + d2 + " = " + total);
return total;
}
static void promptRoll()
{
3 collapsed lines
Scanner input = new Scanner(System.in);
System.out.print("Press Enter to roll...");
input.nextLine(); // simple pause
}
// Step 4: come-out evaluation
static boolean evaluateComeOutRoll(int roll)
{
if (roll == 7 || roll == 11)
{
System.out.println("Rolled a " + roll + "! You win!");
return true;
}
else if (roll == 2 || roll == 3 || roll == 12)
{
System.out.println("Rolled a " + roll + ". You lose.");
return true;
}
else
{
System.out.println("Rolled a " + roll + ".");
return false;
}
}
}
divider

Task 5: Resolve the Point

  • icon Add evaluatePointRoll(int roll, int point) and loop until win/lose.
Program.java
import java.util.Scanner;
public class Program
{
public static void main(String[] args)
{
System.out.println("--- CRAPS ---");
int point = 0;
boolean gameOver;
promptRoll();
int roll = rollDice();
gameOver = evaluateComeOutRoll(roll);
if (!gameOver)
{
point = roll;
System.out.println("The point is now " + point + ".");
// Step 5: keep rolling until win (hit point) or lose (7)
while (!gameOver)
{
promptRoll();
roll = rollDice();
gameOver = evaluatePointRoll(roll, point);
}
}
System.out.println("Thanks for playing!");
}
static int rollDie()
{
return (int)(Math.random() * 6) + 1;
}
static int rollDice()
{
5 collapsed lines
int d1 = rollDie();
int d2 = rollDie();
int total = d1 + d2;
System.out.println("You rolled " + d1 + " + " + d2 + " = " + total);
return total;
}
static void promptRoll()
{
3 collapsed lines
Scanner input = new Scanner(System.in);
System.out.print("Press Enter to roll...");
input.nextLine(); // simple pause
}
static boolean evaluateComeOutRoll(int roll)
{
15 collapsed lines
if (roll == 7 || roll == 11)
{
System.out.println("Rolled a " + roll + "! You win!");
return true;
}
else if (roll == 2 || roll == 3 || roll == 12)
{
System.out.println("Rolled a " + roll + ". You lose.");
return true;
}
else
{
System.out.println("Rolled a " + roll + ".");
return false;
}
}
// Step 5: resolve after point is set
static boolean evaluatePointRoll(int roll, int point)
{
if (roll == point)
{
System.out.println("Rolled a " + roll + "! You win!");
return true;
}
else if (roll == 7)
{
System.out.println("Rolled a 7. You lose.");
return true;
}
else
{
System.out.println("Rolled a " + roll + ". Still shooting for " + point + ".");
return false;
}
}
}
divider

Sample Output

Sample Output
--- CRAPS ---
Press Enter to roll...
You rolled 4 + 3 = 7
Rolled a 7! You win!
Thanks for playing!
divider

Reflection Questions

  1. Which method did you write first, and why was that a good starting point?
  2. How did return values help you control the game flow?
  3. After refactoring, what does main() focus on now?
divider

Submission

Submit your completed .java file and reflection answers to the appropriate dropbox.

Activity Complete