# \[Quiz\] Turtle Graphics (#104)

**URL:** <https://www.ruby-forum.com/t/quiz-turtle-graphics-104/78649>\
**Category:** Ruby\
**Created:** [December 7, 2006, 4:17pm UTC](https://www.ruby-forum.com/t/quiz-turtle-graphics-104/78649 "2006-12-07T16:17:13Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![davidtl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/35a633/32.png) [@davidtl](https://www.ruby-forum.com/u/davidtl)\
**Post date:** [December 7, 2006, 4:17pm UTC](https://www.ruby-forum.com/t/quiz-turtle-graphics-104/78649/1 "2006-12-07T16:17:13Z")

</div>

My second solution.  
This solution pass the unit test.  
It tests all parameters also makes sure 0.0 \<= @heading \< 360.0

# Created by Morton G. on November 02, 2006.

# Modified on November 14, 2006

# turtle.rb

# An implementation of Turtle Procedure Notation (TPN) as described in

# H. Abelson & A. diSessa, “Turtle Geometry”, MIT Press, 1981.

# 

# Turtles navigate by traditional geographic coordinates: X-axis

pointing

# east, Y-axis pointing north, and angles measured clockwise from the

# Y-axis (north) in degrees.

class Turtle  
include Math # turtles understand math methods  
DEG = Math::PI / 180.0

attr\_accessor :track  
alias run instance\_eval

def initialize  
clear  
end

attr\_reader :xy, :heading

# Place the turtle at [x, y]. The turtle does not draw when it

changes

# position.

def xy=(coords)  
@xy = point(coords)  
end

# Set the turtle’s heading to .

def heading=(degrees)  
@heading = degree(degrees)  
end

# Raise the turtle’s pen. If the pen is up, the turtle will not draw;

# i.e., it will cease to lay a track until a pen\_down command is

given.  
def pen\_up  
@pen = false  
end

# Lower the turtle’s pen. If the pen is down, the turtle will draw;

# i.e., it will lay a track until a pen\_up command is given.

def pen\_down  
@pen = true  
end

# Is the pen up?

def pen\_up?  
!pen\_down?  
end

# Is the pen down?

def pen\_down?  
@pen  
end

# Places the turtle at the origin, facing north, with its pen up.

# The turtle does not draw when it goes home.

def home  
@xy = point([0.0, 0.0])  
@heading = 0.0  
pen\_up  
end

# Homes the turtle and empties out it’s track.

def clear  
home  
@track = []  
end

# Turn right through the angle .

def right(degrees)  
degrees = degree(degrees)  
@heading = degree(@heading + degrees)  
end

# Turn left through the angle .

def left(degrees)  
right(-degrees)  
end

# Move forward by turtle steps.

def forward(steps)  
raise ArgumentError unless steps.is\_a?(Numeric)  
angle = (90 - @heading) \* DEG  
x = @xy.x + steps \* cos(angle)  
y = @xy.y + steps \* sin(angle)  
go [x,y]  
end

# Move backward by turtle steps.

def back(steps)  
forward(-steps)  
end

# Move to the given point.

def go(pt)  
pt = point(pt)  
if pen\_down?  
if !@track.empty? && @track.last.last == @xy  
@track.last \<\< pt  
else  
@track \<\< [@xy, pt]  
end  
end  
@xy = pt  
end

# Turn to face the given point.

def toward(pt)  
pt = point(pt)  
@heading = degree(90 - atan2(pt.y - @xy.y, pt.x - @xy.x) / DEG)  
end

# Return the distance between the turtle and the given point.

def distance(pt)  
pt = point(pt)  
sqrt((@xy.x - pt.x) \*\* 2 + (@xy.y - pt.y) \*\* 2)  
end

# Traditional abbreviations for turtle commands.

alias fd forward  
alias bk back  
alias rt right  
alias lt left  
alias pu pen\_up  
alias pd pen\_down  
alias pu? pen\_up?  
alias pd? pen\_down?  
alias set\_h heading=  
alias set\_xy xy=  
alias face toward  
alias dist distance

private

def point(pt)  
raise ArgumentError unless pt.is\_a?(Array) &&  
pt.size == 2 && pt.all? {|e| e.is\_a?(Numeric) }  
pt = pt.dup  
def pt.x; self[0]; end  
def pt.y; self[1]; end  
pt  
end

def degree(degrees)  
raise ArgumentError unless degrees.is\_a?(Numeric)  
degrees += 360.0 while degrees \< 0.0  
degrees -= 360.0 while degrees \>= 360.0  
degrees  
end  
end

---

<div class="post-metadata">

**Author:** ![davidtl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/35a633/32.png) [@davidtl](https://www.ruby-forum.com/u/davidtl)\
**Post date:** [December 7, 2006, 7:50pm UTC](https://www.ruby-forum.com/t/quiz-turtle-graphics-104/78649/2 "2006-12-07T19:50:24Z")

</div>

David T. wrote:

> ```
> degrees += 360.0 while degrees < 0.0
> degrees -= 360.0 while degrees >= 360.0
> 
> ```

These two lines can be replaced with:

degrees %= 360

And the resulting method will run much faster if the degrees argument is  
large.
