15puzzle.bac

'
' The Fifteen-puzzle: http://en.wikipedia.org/wiki/Fifteen_puzzle
'
' Created on a boring sunday afternoon - February 2012, PvE
'
' - 1.0: initial release
' - 1.1: some beautifications
'
' This HTML page generated as follows:
' # enscript --color --style=emacs --language=html --highlight=bacon 15puzzle.bac -p - | expand -t 4 > 15puzzle.bac.html
' 
'------------------------------------------------------------------------------------------

INCLUDE "hug.bac", INIT, HUGOPTIONS, WINDOW, CALLBACK, CANVAS, SQUARE, OUT, MOUSE, FRAME, STOCK, ATTACH, DISPLAY, FOCUS, MSGDIALOG, SHOW, HIDE, QUIT, TEXT, MARK

INIT
HUGOPTIONS("NOSCALING")

DECLARE Situation[6][6]
DECLARE Move

'---------------------------------------------------------------------------------------------

SUB Randomize_Board

    LOCAL i, x, y

    ' Initialize situation
 FOR y = 0 TO 5
        FOR x = 0 TO 5
            IF x = 0 OR x = 5 OR y = 0 OR y = 5 THEN
                Situation[x][y] = -1
            ELSE
                Situation[x][y] = x+(y-1)*4
            END IF
        NEXT
    NEXT
    Situation[4][4] = 0

    ' Start randomization
 FOR i = 1 TO 200

        ' Find the empty space
     FOR y = 1 TO 4
            FOR x = 1 TO 4
                IF Situation[x][y] = 0 THEN BREAK 2
            NEXT
        NEXT

        ' Decide which direction to swap
     SELECT RANDOM(4)
            CASE 0
                IF Situation[x][y-1] = -1 THEN CONTINUE
                Situation[x][y] = Situation[x][y-1]
                Situation[x][y-1] = 0
            CASE 1
                IF Situation[x+1][y] = -1 THEN CONTINUE
                Situation[x][y] = Situation[x+1][y]
                Situation[x+1][y] = 0
            CASE 2
                IF Situation[x][y+1] = -1 THEN CONTINUE
                Situation[x][y] = Situation[x][y+1]
                Situation[x][y+1] = 0
            CASE 3
                IF Situation[x-1][y] = -1 THEN CONTINUE
                Situation[x][y] = Situation[x-1][y]
                Situation[x-1][y] = 0
        END SELECT
    NEXT

END SUB

'---------------------------------------------------------------------------------------------

SUB Draw_Board

    LOCAL x, y

    FOR y = 1 TO 4
        FOR x = 1 TO 4
            IF Situation[x][y] = 0 THEN
                SQUARE("#FFFFFF", (x-1)*70, (y-1)*70, 70, 70, 1)
            ELSE
                SQUARE("#8080FF", (x-1)*60+(x-1)*10+5, (y-1)*60+(y-1)*10+5, 60, 60, 1)
                SQUARE("#0000FF", (x-1)*60+(x-1)*10, (y-1)*60+(y-1)*10, 60, 60, 1)
                SQUARE("#000000", (x-1)*60+(x-1)*10, (y-1)*60+(y-1)*10, 60, 60, 0)
                OUT(STR$(Situation[x][y]), "#FFFF00", "#0000FF", (x-1)*65+(x-1)*5+24, (y-1)*65+(y-1)*5+24)
            END IF
        NEXT
    NEXT

END SUB

'---------------------------------------------------------------------------------------------

SUB Clicked

    LOCAL x, y, xpos, ypos, solved

    xpos = MOUSE(0)
    ypos = MOUSE(1)

    IF xpos > 0 AND xpos < 70 THEN x = 1
    IF xpos > 70 AND xpos < 140 THEN x = 2
    IF xpos > 140 AND xpos < 210 THEN x = 3
    IF xpos > 210 AND xpos < 280 THEN x = 4

    IF ypos > 0 AND ypos < 70 THEN y = 1
    IF ypos > 70 AND ypos < 140 THEN y = 2
    IF ypos > 140 AND ypos < 210 THEN y = 3
    IF ypos > 210 AND ypos < 280 THEN y = 4

    ' Check validity of move
 IF Situation[x][y] != 0 THEN
        IF Situation[x][y-1] = 0 THEN
            Situation[x][y-1] = Situation[x][y]
            Situation[x][y] = 0
            INCR Move
        END IF
        IF Situation[x+1][y] = 0 THEN
            Situation[x+1][y] = Situation[x][y]
            Situation[x][y] = 0
            INCR Move
        END IF
        IF Situation[x][y+1] = 0 THEN
            Situation[x][y+1] = Situation[x][y]
            Situation[x][y] = 0
            INCR Move
        END IF
        IF Situation[x-1][y] = 0 THEN
            Situation[x-1][y] = Situation[x][y]
            Situation[x][y] = 0
            INCR Move
        END IF
        Draw_Board
    END IF

    ' Check game end
 FOR y = 1 TO 4
        FOR x = 1 TO 4
            IF Situation[x][y] = x+(y-1)*4 THEN INCR solved
        NEXT
    NEXT

    IF solved = 15 THEN
        TEXT(enddlg, "Well done, solved in " & STR$(Move) & " moves!")
        SHOW(enddlg)
    END IF

END SUB

'---------------------------------------------------------------------------------------------

SUB Handle_Answer(NUMBER dialog, int button)

    HIDE(dialog)

    IF button = GTK_RESPONSE_YES THEN
        Randomize_Board
        Draw_Board
        Move = 0
    END IF

END SUB

'---------------------------------------------------------------------------------------------

SUB Show_Question

    SHOW(infdlg)

END SUB

'---------------------------------------------------------------------------------------------

window = WINDOW("The Fifteen-puzzle", 300, 350)
frame = FRAME(290, 290)
ATTACH(window, frame, 5, 5)
PROPERTY(window, "icon-name", "gtk-about")

canvas = CANVAS(280, 280)
ATTACH(window, canvas, 10, 10)
CALLBACK(canvas, Clicked)

exitbutton = STOCK("gtk-quit", 90, 40)
ATTACH(window, exitbutton, 205, 305)
CALLBACK(exitbutton, QUIT)

newbutton = STOCK("gtk-new", 90, 40)
ATTACH(window, newbutton, 5, 305)
CALLBACK(newbutton, Show_Question)

txt = MARK("Created with\n     BaCon!", 90, 40)
ATTACH(window, txt, 100, 305)

infdlg = MSGDIALOG("Create another game?", 300, 130, 2, 4)
CALLBACK(infdlg, Handle_Answer)

enddlg = MSGDIALOG("Well done!", 300, 100, 0, 2)
CALLBACK(enddlg, HIDE)

Randomize_Board
Draw_Board

FOCUS(exitbutton)
DISPLAY

Generated by GNU Enscript 1.6.5.90.