RoCoLoco Revisited - Math puzzle.
#1
This is an update to a math adding puzzle game I posted a few years ago.  The previous version was limited and used dozens of image files for numbers.   I added a new board display method, it should look the same size on every desktop.  This version has more grid sizes, and some sound effects, and a simple Help screen.

Basically you click to remove/add numbers in the grid so that the ones left on add up to the number shown on the edges.  The rows and columns numbers must total up to the number on the edge.  Make all the edge numbers highlighted to solve the puzzle and advance to a bigger grid size.  You can change grid sizes by pressing +/- keys.  

It's nothing great, and probably could be done in half the amount of code, I just wanted to work on something today and landed on this for some reason.  

- Dav

Code: (Select All)
'============
'RoCoLoco.bas v2.0
'============
'Row & Column number adding puzzle game.
'Based on popular math game found online.
'Coded by Dav for QB64-PE, Nov/2022

'New for v2:  * Playing board now adapts to users desktop size.
'               It should displays the same on every screen.
'               (Screen size is not hardcoded to specific size)
'             * No longer uses external .jpg images for numbers.
'             * Change grid size using the +/- keys.
'             * Added HELP screen (not much) - press H for it.
'             * Added some cheap sound effects.
'
'~~~~~~~~~~~
'HOW TO PLAY:

'Click numbers inside the grid to turn them on/off.
'Each row/column of red number totals must add up to the number
'on the edge of the grid. When they do, the edge numbers will
'turn on too. You must tun on all the edge numbers to solve it.
'
'~~~~~~~~
'CONTROLS:
'
'You can change the grid size anytime by using +/- keys.
'H = Show a simple help screen
'SPACE = Generate a new puzzle grid
'ESC = Quits game

'============================================================

REDIM SHARED grid, tiles

'defalts....
grid = 5 '3x3 grid size (3 for inside tiles, 2 for edges  = 5)
gridmax = 15

'===
top:
'===

_TITLE "RoCoLoco - Working..."

tiles = grid * grid '  total number of tiles on board

SCREEN _NEWIMAGE(_DESKTOPHEIGHT * .80, _DESKTOPHEIGHT * .80, 32)

tilesize = (_DESKTOPHEIGHT * .80) / grid

CLS , _RGB(77, 77, 77)

REDIM SHARED tilev(tiles) 'make array for all titles values
REDIM SHARED tilef(tiles) 'make array for flag if tile is on/off
REDIM SHARED tilex(tiles), tiley(tiles) 'x/y positions for tiles

RANDOMIZE TIMER 'set random seed

'init x/y values for drawing tiles
bc = 1
FOR x = 1 TO grid
    FOR y = 1 TO grid
        tilex(bc) = (x * tilesize) - tilesize: tiley(bc) = (y * tilesize) - tilesize
        tilev(bc) = INT(RND * 9 + 1) '<<< for testing only, give all some data
        bc = bc + 1
    NEXT
NEXT

SCRAMTIME = TIMER

'==========
regenerate:
'==========

SOUND 500 + RND * 1000, 1

'generate random tile value and on/off settings
T = grid + 2
FOR y = 2 TO grid - 1
    regeneratex:
    makesurex = 0: thold = T
    FOR x = 2 TO grid - 1
        tilev(thold) = INT(RND * 5 + 1) 'make random number, from 1-5
        IF INT(RND * grid - (INT(RND * 1.5))) = 0 THEN
            tilef(thold) = 0 'randomly turn tile on/off
            makesurex = 1 'make sure at least one out on this column
        ELSE
            tilef(thold) = 1
        END IF
        'show something while computing...
        LINE (tilex(thold), tiley(thold))-(tilex(thold) + tilesize, tiley(thold) + tilesize), _RGB(255, 100, 100), BF
        PPRINT tilex(thold) + (tilesize / 1.8), tiley(thold) + (tilesize / 4.5), tilesize / 2, _RGB(255, 255, 255), 0, LTRIM$(STR$(tilev(thold)))
        thold = thold + 1
    NEXT
    'if row didnt have one turned off, do this column over...
    IF makesurex = 0 THEN GOTO regeneratex
    T = thold + 2
    _LIMIT 10 * grid 'slow down, let's see it.
NEXT

'now check rows left to right for on/off, if none off, regenerate
FOR x = 0 TO grid - 3
    makesurex = 0
    FOR y = grid + 2 TO (grid * grid) - grid - 2 STEP grid
        IF tilef(y + x) = 0 THEN makesurex = 1
    NEXT
    IF makesurex = 0 THEN GOTO regenerate
NEXT

IF TIMER < (SCRAMTIME + 1) THEN GOTO regenerate

'compute left/right edges totals
FOR y = 0 TO grid - 3
    total = 0
    FOR x = grid + 2 TO (grid * grid) - grid - 2 STEP grid
        IF tilef(y + x) = 1 THEN
            total = total + tilev(y + x)
        END IF
    NEXT
    tilev(y + x) = total 'set total data to tile
NEXT

'compute top/bottom edges
FOR x = grid + 2 TO (grid * grid) - grid - 2 STEP grid
    total = 0
    FOR y = 0 TO grid - 3
        IF tilef(y + x) = 1 THEN
            total = total + tilev(y + x)
        END IF
    NEXT
    tilev(y + x) = total
NEXT

'Lastly, mark all inside grid tiles as on, hiding generated solution.
FOR T = grid + 2 TO (grid * grid) - grid - 1
    'skip the outside rows
    FOR tt = 1 TO grid * grid STEP grid
        IF T = tt THEN GOTO skipmark
        IF T = tt + (grid - 1) THEN GOTO skipmark
    NEXT
    tilef(T) = 1
    skipmark:
NEXT

GOSUB RedrawBoard

tit$ = "RoCoLoco" + STR$(grid - 2) + "x" + LTRIM$(STR$(grid - 2)) + " | H = Help"
_TITLE tit$
_ICON _DISPLAY

DO
    'wait until mouse button up to continue
    WHILE _MOUSEBUTTON(1) <> 0: n = _MOUSEINPUT: WEND

    trap = _MOUSEINPUT
    IF _MOUSEBUTTON(1) THEN
        mx = _MOUSEX: my = _MOUSEY
        'cycle through tiles
        FOR T = grid + 2 TO (grid * grid) - grid - 1
            'skip the outside rows
            FOR tt = 1 TO grid * grid STEP grid
                IF T = tt THEN GOTO skip
                IF T = tt + (grid - 1) THEN GOTO skip
            NEXT

            tx = tilex(T): tx2 = tilex(T) + tilesize
            ty = tiley(T): ty2 = tiley(T) + tilesize

            IF mx >= tx AND mx <= tx2 THEN
                IF my >= ty AND my <= ty2 THEN

                    IF tilef(T) = 0 THEN
                        tilef(T) = 1: 'mark it on
                        SOUND 2500, .1
                    ELSE
                        tilef(T) = 0: 'mark it off
                        SOUND 2000, .1
                    END IF

                    GOSUB RedrawBoard

                    'check for win

                END IF
            END IF
            skip:
        NEXT

    END IF

    k$ = UCASE$(INKEY$)
    IF k$ <> "" THEN

        'ESC key quits
        IF k$ = CHR$(27) THEN SYSTEM

        'space key generates new board
        IF k$ = " " THEN GOTO top

        IF k$ = "+" THEN
            IF grid < 15 THEN grid = grid + 1: GOTO top
        END IF

        IF k$ = "-" THEN
            IF grid > 5 THEN grid = grid - 1: GOTO top
        END IF

        IF k$ = "H" THEN
            back& = _COPYIMAGE(_DISPLAY)
            CLS , _RGB(77, 77, 77)
            ps = (_DESKTOPHEIGHT * .80) / 5
            PPRINT ps / 2 + 2, ps / 3 + 2, ps / 3, _RGB(255, 255, 255), 0, "ROCOLOCO HELP"
            PPRINT ps / 2, ps / 3, ps / 3, _RGB(255, 100, 100), 0, "ROCOLOCO HELP"
            PPRINT ps / 2, (ps / 3) * 3, ps / 6, _RGB(196, 196, 196), 0, "Click on the numbers to"
            PPRINT ps / 2, (ps / 3) * 4, ps / 6, _RGB(196, 196, 196), 0, "turn them On or Off."
            PPRINT ps / 2, (ps / 3) * 5, ps / 6, _RGB(196, 196, 196), 0, "Rows And Columns must"
            PPRINT ps / 2, (ps / 3) * 6, ps / 6, _RGB(196, 196, 196), 0, "add up to the number on"
            PPRINT ps / 2, (ps / 3) * 7, ps / 6, _RGB(196, 196, 196), 0, "the edges. When correct,"
            PPRINT ps / 2, (ps / 3) * 8, ps / 6, _RGB(196, 196, 196), 0, "edges will turn white."
            PPRINT ps / 2, (ps / 3) * 9, ps / 6, _RGB(196, 196, 196), 0, "Make all edges white to"
            PPRINT ps / 2, (ps / 3) * 10, ps / 6, _RGB(196, 196, 196), 0, "solve the math puzzle."
            PPRINT ps / 2, (ps / 3) * 11, ps / 6, _RGB(196, 196, 196), 0, "Use +/- keys to change"
            PPRINT ps / 2, (ps / 3) * 12, ps / 6, _RGB(196, 196, 196), 0, "the size of the grid."
            PPRINT ps / 2, (ps / 3) * 14, ps / 6, _RGB(255, 255, 255), 0, "   - PRESS ANY KEY - "
            A$ = INPUT$(1)
            _PUTIMAGE (0, 0), back&
            _FREEIMAGE back&
        END IF

    END IF

LOOP

END

'========================================================================================
RedrawBoard:
'===========

win = 1

'Draw inside grid numbers first
FOR d = grid + 2 TO (grid * grid) - grid - 1
    'skiping the outside rows
    FOR dd = 1 TO grid * grid STEP grid
        IF d = dd THEN GOTO skipit
        IF d = dd + (grid - 1) THEN GOTO skipit
    NEXT
    IF tilef(d) = 1 THEN
        'on
        LINE (tilex(d), tiley(d))-(tilex(d) + tilesize, tiley(d) + tilesize), _RGB(255, 100, 100), BF
        PPRINT tilex(d) + (tilesize / 1.8), tiley(d) + (tilesize / 4.5), tilesize / 2, _RGB(255, 255, 255), 0, LTRIM$(STR$(tilev(d)))
    ELSE
        'off
        LINE (tilex(d), tiley(d))-(tilex(d) + tilesize, tiley(d) + tilesize), _RGB(77, 77, 77), BF
        PPRINT tilex(d) + (tilesize / 1.8), tiley(d) + (tilesize / 4.5), tilesize / 2, _RGB(96, 96, 96), 0, LTRIM$(STR$(tilev(d)))
    END IF
    skipit:
NEXT

'compute and draw left/right edges
FOR y = 0 TO grid - 3
    total = 0
    FOR x = grid + 2 TO (grid * grid) - grid - 2 STEP grid
        IF tilef(y + x) = 1 THEN
            total = total + tilev(y + x)
        END IF
    NEXT
    IF tilev(y + x) = total THEN
        'if total match, highlight it
        LINE (tilex(y + x), tiley(y + x))-(tilex(y + x) + tilesize, tiley(y + x) + tilesize), _RGB(255, 255, 255), BF 'right side
        IF LEN(LTRIM$(STR$(tilev(y + x)))) = 2 THEN
            PPRINT tilex(y + x) + (tilesize / 2.5), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(32, 32, 32), 0, LTRIM$(STR$(tilev(y + x)))
        ELSE
            PPRINT tilex(y + x) + (tilesize / 1.7), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(32, 32, 32), 0, LTRIM$(STR$(tilev(y + x)))
        END IF
        LINE (tilex(y + x) - (tilex(y + x)), tiley(y + x))-((tilex(y + x) - (tilex(y + x))) + tilesize, tiley(y + x) + tilesize), _RGB(255, 255, 255), BF 'left side
        IF LEN(LTRIM$(STR$(tilev(y + x)))) = 2 THEN
            PPRINT tilex(y + x) - tilex(y + x) + (tilesize / 2.5), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(32, 32, 32), 0, LTRIM$(STR$(tilev(y + x)))
        ELSE
            PPRINT tilex(y + x) - tilex(y + x) + (tilesize / 1.7), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(32, 32, 32), 0, LTRIM$(STR$(tilev(y + x)))
        END IF

    ELSE
        'total doesnt match, don't highlight edge
        win = 0
        LINE (tilex(y + x), tiley(y + x))-(tilex(y + x) + tilesize, tiley(y + x) + tilesize), _RGB(77, 77, 77), BF 'right side
        LINE (tilex(y + x), tiley(y + x))-(tilex(y + x) + tilesize, tiley(y + x) + tilesize), _RGB(196, 196, 196), B 'right side
        IF LEN(LTRIM$(STR$(tilev(y + x)))) = 2 THEN
            PPRINT tilex(y + x) + (tilesize / 2.5), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(196, 196, 196), 0, LTRIM$(STR$(tilev(y + x)))
        ELSE
            PPRINT tilex(y + x) + (tilesize / 1.7), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(195, 196, 196), 0, LTRIM$(STR$(tilev(y + x)))
        END IF
        LINE (tilex(y + x) - (tilex(y + x)), tiley(y + x))-((tilex(y + x) - (tilex(y + x))) + tilesize, tiley(y + x) + tilesize), _RGB(77, 77, 77), BF 'left side
        LINE (tilex(y + x) - (tilex(y + x)), tiley(y + x))-((tilex(y + x) - (tilex(y + x))) + tilesize, tiley(y + x) + tilesize), _RGB(196, 196, 196), B 'left side
        IF LEN(LTRIM$(STR$(tilev(y + x)))) = 2 THEN
            PPRINT tilex(y + x) - tilex(y + x) + (tilesize / 2.5), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(196, 196, 196), 0, LTRIM$(STR$(tilev(y + x)))
        ELSE
            PPRINT tilex(y + x) - tilex(y + x) + (tilesize / 1.7), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(196, 196, 196), 0, LTRIM$(STR$(tilev(y + x)))
        END IF

    END IF

NEXT

'compute and draw top/bottom edges
FOR x = grid + 2 TO (grid * grid) - grid - 2 STEP grid
    total = 0
    FOR y = 0 TO grid - 3
        IF tilef(y + x) = 1 THEN
            total = total + tilev(y + x)
        END IF
    NEXT
    IF tilev(y + x) = total THEN
        'total matches, hight top/bottom
        LINE (tilex(y + x), tiley(y + x))-(tilex(y + x) + tilesize, tiley(y + x) + tilesize), _RGB(255, 255, 255), BF 'bottom
        IF LEN(LTRIM$(STR$(tilev(y + x)))) = 2 THEN
            PPRINT tilex(y + x) + (tilesize / 2.5), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(32, 32, 32), 0, LTRIM$(STR$(tilev(y + x)))
        ELSE
            PPRINT tilex(y + x) + (tilesize / 1.7), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(32, 32, 32), 0, LTRIM$(STR$(tilev(y + x)))
        END IF
        LINE (tilex(y + x), tiley(y + x) - tiley(y + x))-(tilex(y + x) + tilesize, (tiley(y + x) - tiley(y + x)) + tilesize), _RGB(255, 255, 255), BF 'top
        IF LEN(LTRIM$(STR$(tilev(y + x)))) = 2 THEN
            PPRINT tilex(y + x) + (tilesize / 2.5), tiley(y + x) - tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(32, 32, 32), 0, LTRIM$(STR$(tilev(y + x)))
        ELSE
            PPRINT tilex(y + x) + (tilesize / 1.7), tiley(y + x) - tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(32, 32, 32), 0, LTRIM$(STR$(tilev(y + x)))
        END IF
    ELSE
        'doesnt' match, dont hightlight top/bottom edges
        win = 0
        LINE (tilex(y + x), tiley(y + x))-(tilex(y + x) + tilesize, tiley(y + x) + tilesize), _RGB(77, 77, 77), BF 'bottom
        LINE (tilex(y + x), tiley(y + x))-(tilex(y + x) + tilesize, tiley(y + x) + tilesize), _RGB(196, 196, 196), B 'bottom
        IF LEN(LTRIM$(STR$(tilev(y + x)))) = 2 THEN
            PPRINT tilex(y + x) + (tilesize / 2.5), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(196, 196, 196), 0, LTRIM$(STR$(tilev(y + x)))
        ELSE
            PPRINT tilex(y + x) + (tilesize / 1.7), tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(196, 196, 196), 0, LTRIM$(STR$(tilev(y + x)))
        END IF
        LINE (tilex(y + x), tiley(y + x) - tiley(y + x))-(tilex(y + x) + tilesize, (tiley(y + x) - tiley(y + x)) + tilesize), _RGB(77, 77, 77), BF 'top
        LINE (tilex(y + x), tiley(y + x) - tiley(y + x))-(tilex(y + x) + tilesize, (tiley(y + x) - tiley(y + x)) + tilesize), _RGB(196, 196, 196), B 'top
        IF LEN(LTRIM$(STR$(tilev(y + x)))) = 2 THEN
            PPRINT tilex(y + x) + (tilesize / 2.5), tiley(y + x) - tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(196, 196, 196), 0, LTRIM$(STR$(tilev(y + x)))
        ELSE
            PPRINT tilex(y + x) + (tilesize / 1.7), tiley(y + x) - tiley(y + x) + (tilesize / 3.2), tilesize / 3, _RGB(196, 196, 196), 0, LTRIM$(STR$(tilev(y + x)))
        END IF

    END IF
NEXT



'see if puzzle completed
IF win = 1 THEN
    PLAY "mbl16o2cdedefgabagfedc"

    'remove unused numbers
    FOR T = grid + 2 TO (grid * grid) - grid - 1
        'skip the outside rows
        FOR tt = 1 TO grid * grid STEP grid
            IF T = tt THEN GOTO skipcheck
            IF T = tt + (grid - 1) THEN GOTO skipcheck
        NEXT
        IF tilef(T) = 0 THEN
            LINE (tilex(T), tiley(T))-(tilex(T) + tilesize, tiley(T) + tilesize), _RGB(77, 77, 77), BF
        END IF
        skipcheck:
    NEXT

    _DELAY 5

    IF grid < 15 THEN grid = grid + 1

    GOTO top
END IF


RETURN


SUB PPRINT (x, y, SquareSize, clr&, trans&, text$)
    orig& = _DEST
    bit = 32: IF _PIXELSIZE(0) = 1 THEN bit = 256
    FOR t = 0 TO LEN(text$) - 1
        pprintimg& = _NEWIMAGE(16, 16, bit)
        _DEST pprintimg&
        CLS , trans&: COLOR clr&
        PRINT MID$(text$, t + 1, 1);
        _CLEARCOLOR _RGB(0, 0, 0), pprintimg&
        _DEST orig&
        x1 = x + (t * SquareSize): x2 = x1 + SquareSize
        y1 = y: y2 = y + SquareSize
        _PUTIMAGE (x1 - (SquareSize / 2), y1)-(x2, y2 + (SquareSize / 3)), pprintimg&
        _FREEIMAGE pprintimg&
    NEXT
END SUB

Find my programs here in Dav's QB64 Corner
Reply
#2
5 seconds to win


[Image: math.png]
Write name of program in 1st line to copy & paste & save filename.bas
Insert program pictures: press print-screen-shot button
Open paint & Paste & Save as PNG
Add picture file to program topic

Russia looks world from future. Big data is peace data.
I never recommend anything & always write only about myself
Reply
#3
Hi Dav, works fine, missed your Halloween update ;-))
b = b + ...
Reply
#4
@DANILIN: Thanks for trying it.  Yes the first 3x3 grid level is very easy, it gets harder, going up to 13x13. You may jump to the larger grids using the + key.

@bplus: Thanks!.  I regret not finishing up on the Halloween game.   Maybe next year....

- Dav

Find my programs here in Dav's QB64 Corner
Reply
#5
line 101
timegame = Timer

line 357
Locate 2, 1: Print Timer - timegame
_Delay 1

result: time of game & pause for print screen
Write name of program in 1st line to copy & paste & save filename.bas
Insert program pictures: press print-screen-shot button
Open paint & Paste & Save as PNG
Add picture file to program topic

Russia looks world from future. Big data is peace data.
I never recommend anything & always write only about myself
Reply




Users browsing this thread: 3 Guest(s)