Turtle Graphics combines a CUI and a graphics window. The graphics window displays a turtle shape:
At the CUI prompt users can type the following commands:
quit // exit the
program
turn HEADING // turn turtle N, E, W, or S
move STEPS // move turtle STEPS pixels
in the direction of heading
For example, here's the CUI window after executing several commands:
Here's what the graphics window looks like:
Here's the viewer class:
public class TurtleViewer {
public static final int FRAME_WIDTH =
300;
public static final int FRAME_HEIGHT =
400;
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(FRAME_WIDTH,
FRAME_HEIGHT);
frame.setTitle("Frame
Viewer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create custom component:
TurtleComponent component = new
TurtleComponent();
frame.add(component);
frame.setVisible(true);
// start control loop:
component.controlLoop();
}
}
Here's the component class:
public class TurtleComponent extends JComponent {
// height & width of canvas:
private int height = 400, width = 300;
private Turtle turtle = new Turtle();
private Scanner kbd = new
Scanner(System.in);
public void paintComponent(Graphics gc)
{
// update height & width of
canvas:
height = getHeight();
width = getWidth();
Graphics2D gc2d = (Graphics2D)gc;
// for extra credit, adjust turtle's
position here to wrap
turtle.draw(gc2d);
}
public void controlLoop() {
// ???
}
}
For extra credit, make the turtle wrap around the screen if he moves too far. In other words, turtle.xc %= width, etc.
The control loop should perpetually:
1. Display a prompt
2. Read next token
3. if token = quit: System.exit(0)
4. if token = move:
read #steps
move turtle #steps (should be
positive int)
call repaint(); // causes OS to call
paintComponent
print "done"
5. if token = turn:
read direction (should be N, E, W,
or S)
turn turtle in this direction
call repaint(); // causes OS to call
paintComponent
print "done"
6. else print error
Here's the turtle class:
public class Turtle {
private int xc = 20, yc = 30;
private char heading = 'N';
private static final int shellSize =
25;
private static final int headSize = 10;
public void move(int steps) {
//
???
}
public void setHeading(char h) {
heading = h;
}
public void draw(Graphics2D gc) {
// draw shell:
Ellipse2D.Double shell =
new Ellipse2D.Double(xc, yc,
shellSize, shellSize);
gc.setColor(Color.GREEN);
gc.fill(shell);
// draw head
int xcHead = 0;
int ycHead = 0;
if (heading == 'E') {
xcHead = xc + shellSize;
ycHead = yc + shellSize/2 -
headSize/2;
} else if (heading == 'S') {
xcHead = xc + shellSize/2 -
headSize/2;
ycHead = yc + shellSize;
} else if (heading == 'W') {
xcHead = xc - headSize;
ycHead = yc + shellSize/2 -
headSize/2;
} else { // assume heading == 'N'
xcHead = xc + shellSize/2 -
headSize/2;
ycHead = yc - headSize;
}
gc.setColor(Color.BLACK);
Ellipse2D.Double head =
new Ellipse2D.Double(xcHead,
ycHead, headSize, headSize);
gc.fill(head);
}
}
The move(int steps) method increments or decrements either xc or yc by steps depending on the heading of the turtle.