HiveBrain v1.2.0
Get Started
← Back to all entries
patternModerate

Four Tic-Tac-Toe boards using kTurtle

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
kturtletoeticfourboardstacusing

Problem

I am trying to learn kTurtle (slightly different from Logo) so that I can help my daughter learn to write code. I have decided that I would write a program that would play Tic-Tac-Toe with a user. So far, all I have is the Game board, and I make it more than just a single board to add to the intensity of my learning. Hopefully I can get this figured out before my daughter graduates high school.

I am using kTurtle on Ubuntu which is similar to Logo but open source (free).

What I really want to know is if I am following good programming standards as this is a little different than what I am used to coding.

#Game board 1
$CanvasX = 300
$CanvasY = 300
#$x = ask "how big do you want the canvas to be?"
canvassize $CanvasX, $CanvasY

$x=$CanvasX/2
$y=$CanvasY/2

learn gameboard $a, $b, $x, $y {
    $TwoThirdsX = ($x/3)*2
    $OneThirdX = $x/3
    go $a, $b
    dir 180
    penup
    forward $OneThirdX
    turnleft 90
    pendown
    forward $x
    penup
    turnright 90
    forward $OneThirdX
    turnright 90
    pendown
    forward $x
    penup
    turnleft 90
    forward $OneThirdX
    turnleft 90
    forward $OneThirdX
    turnleft 90
    pendown
    forward $x
    penup
    turnright 90
    forward $OneThirdX
    pendown
    turnright 90
    forward $x
}  
penwidth 1
gameboard 0, 0, $x, $y
$a=$x
$b=0
gameboard $a,$b,$x,$y
$a=$x
$b=$y
gameboard $a,$b,$x,$y
$a=0
$b=$y
gameboard $a,$b,$x,$y
penwidth 5
go $x, 0
forward 2*$x
go 0, $y
turnleft 90
forward 2*$y


Here is the finished product:

Solution

I've just installed KTurtle for Windows, and ran your code. I never thought a turtle could be so frantic! KTurtle is ..entertaining to see in action! I've played with LogoWriter back in high school, an eternity ago; this is very similar (although I was somehow expecting a 16-color, 320x240 resolution.. the shock it was!).


Save often.


KTurtle works on Windows, but it sometimes crashes when you click to run your script. Save often; save every time you want to run it, and it's workable. Also whatever you do, don't undock the code pane, it seems impossible to dock it back into the IDE afterwards (and restarting the IDE won't help). If you have access to KTurtle on Ubuntu, by all means don't bother with Windows (assuming it's more stable on Ubuntu).

So I ran it again, at a slower speed.. first thing I'm noticing is that you're missing a clear at the beginning of the script (/program?), so that successive executions start off an empty canvas.

Your algorithm is drawing the 4 boards clockwise, starting top-left. Each board is made of 2 horizontal and 2 vertical lines, which means if you skip drawing the larger/bolder lines in the center, the canvas looks like this:

Your algorithm takes good care of not drawing the same line twice and gets the job done, but there's no separation of concerns whatsoever - as was mentioned in @Sjlver's answer, you need abstractions; teaching a kid how to get things done is nice, teaching the kid how to think in terms of abstractions is even nicer. I would go by @Sjlver's recommendation and create a command responsible for drawing a single square (learn square), and use a repeat loop to keep the code DRY:

learn square $x, $y, $size {
    go $x, $y
    repeat 4 {
        edge $size, 90
    }
}

learn edge $size $angle {
    forward $size
    turnright $angle
}


Notice the square command is only responsible for drawing 4 edges at the specified coordinates - the edge command is responsible for drawing a single line and turning the turtle in the specified direction. It is not responsible for knowing whether or not the pen is up or down.

I like that you're using penup and pendown instead of the shorthand pu and pd - you've used the easier-to-read ones and that's good.

So, now you have a command that can draw a square; now you need one that draws 9 of them to draw a board:

learn board $x, $y {
    for $w = 0 to 2 {
        for $h = 0 to 2 {
            square $x + $w * $boxSize, $y + $h * $boxSize, $boxSize
        }
    }
}


And now you can have code like this:

$boardSize = 150
$boxSize = $boardSize/3

# number of boards to draw in each direction:
$boards = 2

clear
pendown
penwidth 1

for $x = 0 to $boards-1 {
    for $y = 0 to $boards-1 {
        board $x * $boardSize, $y * $boardSize
    }
}


It's slower than your code, and it's not as efficient (pretty much every line get drawn more than once), but thinking in abstractions, in terms of functions that do only one thing, is more important than getting a script to do what you need it to do.

This is the result:

Now you want have a black border around each board, right? The code to do that is pretty much already written!

penwidth 5
for $x = 0 to $boards - 1 {
    for $y = 0 to $boards - 1 {
        square $x * $boardSize, $y * $boardSize, $boardSize
    }
}


Now this leaves the "script" part doing 3 things: declaring global-scope variables, drawing the boards, and drawing the outlines. Here's the final script, with the result:

learn square $x, $y, $size {
    go $x, $y
    repeat 4 {
        edge $size, 90
    }
}

learn edge $size, $angle {
    turnright $angle
    forward $size
}

learn board $x, $y {
    for $w = 0 to 2 {
        for $h = 0 to 2 {
            square $x+$w*$boxSize, $y+$h*$boxSize, $boxSize
        }
    }
}

learn drawBoards {
    for $x = 0 to $boards-1 {
        for $y = 0 to $boards-1 {
            board $x*$boardSize, $y*$boardSize
        }
    }
}

learn drawOutlines {
    for $x = 0 to $boards-1 {
        for $y = 0 to $boards-1 {
            square $x*$boardSize, $y*$boardSize, $boardSize
        }
    }
}

$boardSize = 150
$boxSize = $boardSize/3
$boards = 2

clear
pendown

penwidth 1
drawBoards

penwidth 5
drawOutlines


The "script" part is now only in charge of controlling the high-level stuff; the lower-level actual looping and drawing is abstracted away into commands with meaningful names, that start with a verb, and as a bonus, the turtle ends up right in the middle!

Code Snippets

learn square $x, $y, $size {
    go $x, $y
    repeat 4 {
        edge $size, 90
    }
}

learn edge $size $angle {
    forward $size
    turnright $angle
}
learn board $x, $y {
    for $w = 0 to 2 {
        for $h = 0 to 2 {
            square $x + $w * $boxSize, $y + $h * $boxSize, $boxSize
        }
    }
}
$boardSize = 150
$boxSize = $boardSize/3

# number of boards to draw in each direction:
$boards = 2

clear
pendown
penwidth 1

for $x = 0 to $boards-1 {
    for $y = 0 to $boards-1 {
        board $x * $boardSize, $y * $boardSize
    }
}
penwidth 5
for $x = 0 to $boards - 1 {
    for $y = 0 to $boards - 1 {
        square $x * $boardSize, $y * $boardSize, $boardSize
    }
}
learn square $x, $y, $size {
    go $x, $y
    repeat 4 {
        edge $size, 90
    }
}

learn edge $size, $angle {
    turnright $angle
    forward $size
}

learn board $x, $y {
    for $w = 0 to 2 {
        for $h = 0 to 2 {
            square $x+$w*$boxSize, $y+$h*$boxSize, $boxSize
        }
    }
}

learn drawBoards {
    for $x = 0 to $boards-1 {
        for $y = 0 to $boards-1 {
            board $x*$boardSize, $y*$boardSize
        }
    }
}

learn drawOutlines {
    for $x = 0 to $boards-1 {
        for $y = 0 to $boards-1 {
            square $x*$boardSize, $y*$boardSize, $boardSize
        }
    }
}

$boardSize = 150
$boxSize = $boardSize/3
$boards = 2

clear
pendown

penwidth 1
drawBoards

penwidth 5
drawOutlines

Context

StackExchange Code Review Q#53828, answer score: 11

Revisions (0)

No revisions yet.