Author Topic: MAKE5 Board clearing puzzle  (Read 2365 times)

0 Members and 1 Guest are viewing this topic.

Offline Dav

  • Forum Resident
  • Posts: 792
MAKE5 Board clearing puzzle
« on: January 10, 2021, 08:10:35 pm »
Here's a simple little puzzle game made on a lazy afternoon.  It's a close copy of one I was playing online.  You arrange the big colored balls in a row (5 or more) to erase them.  More balls appear randomly on the board.  Keep clearing the balls to make space on the board.  See how high a score you can get before the board gets full.

- Dav

EDIT: Updated the colors and Game Over box.

Code: QB64: [Select]
  1. '=========
  2. 'MAKE5.bas
  3. '=========
  4. 'A board clearing puzzle game.
  5. 'Clear the board of balls, score points.
  6. 'Coded by Dav, JAN/2021
  7.  
  8. 'Colored balls appear randomly on playing board.
  9. 'Move the bigger balls of same color next to each other.
  10. 'Make row/column of 5 or more balls to erase them and score.
  11.  
  12. 'Three new balls will appear after every move.
  13. 'The small balls will grow into big ones on next move.
  14. 'You can place the big balls on top of the smaller ones.
  15.  
  16. 'See how many points you can score before running out of space.
  17.  
  18. '=========================================================
  19.  
  20.  
  21. SCREEN _NEWIMAGE(600, 650, 32)
  22. _TITLE "Make5 Puzzle"
  23.  
  24. '=== define board info
  25. DIM SHARED rows, cols, size, score, hiscore
  26. rows = 9: cols = 9: size = _WIDTH / cols
  27. DIM SHARED box.v(rows * cols), box.s(rows * cols) 'value, size
  28. DIM SHARED box.x(rows * cols), box.y(rows * cols) 'x/y's
  29.  
  30. '=======
  31. restart:
  32. '=======
  33.  
  34. PLAY "MBL32O3CEGEC"
  35.  
  36. score = 0
  37.  
  38. CLS , _RGB(13, 13, 13)
  39.  
  40. bc = 1 'counter
  41. FOR c = 1 TO cols
  42.     FOR r = 1 TO rows
  43.         x = (r * size)
  44.         y = 50 + (c * size)
  45.         box.x(bc) = x - size
  46.         box.y(bc) = y - size
  47.         box.v(bc) = 0 'zero means no color, empty box
  48.         box.s(bc) = 1 ' 1 = small size piece
  49.         bc = bc + 1
  50.     NEXT
  51.  
  52. MakeNewBalls 3, 1 'add 3 big new balls to board
  53. MakeNewBalls 3, 2 'add 3 small balls to board
  54.  
  55. '====
  56. main:
  57. '====
  58.  
  59. selected = 0
  60.  
  61. UpdateBoard
  62.  
  63. second: 'Go back here when making second choice
  64.  
  65.  
  66.     'wait until mouse button up to continue
  67.     WHILE _MOUSEBUTTON(1) <> 0: n = _MOUSEINPUT: WEND
  68.  
  69.     trap = _MOUSEINPUT 'Poll mouse data
  70.  
  71.     'highlight box when a box is selected
  72.     IF selected = 1 THEN
  73.         LINE (box.x(t) + 2, box.y(t) + 2)-(box.x(t) + size - 2, box.y(t) + size - 2), _RGB(RND * 255, RND * 255, RND * 255), B
  74.         LINE (box.x(t) + 3, box.y(t) + 3)-(box.x(t) + size - 3, box.y(t) + size - 3), _RGB(RND * 255, RND * 255, RND * 255), B
  75.         LINE (box.x(t) + 4, box.y(t) + 4)-(box.x(t) + size - 4, box.y(t) + size - 4), _RGB(RND * 255, RND * 255, RND * 255), B
  76.         _DISPLAY
  77.     END IF
  78.  
  79.  
  80.     'If user clicked mouse
  81.  
  82.         'see where they clicked
  83.         mx = _MOUSEX: my = _MOUSEY
  84.  
  85.         'cycle through all Check blocks...
  86.         FOR t = 1 TO (rows * cols)
  87.  
  88.             'Block loction...
  89.             tx = box.x(t): tx2 = box.x(t) + size
  90.             ty = box.y(t): ty2 = box.y(t) + size
  91.  
  92.             'if clicked on a box clicked
  93.             IF mx >= tx AND mx <= tx2 THEN
  94.                 IF my >= ty AND my <= ty2 THEN
  95.  
  96.                     'if this is a first choice...
  97.                     IF selected = 0 THEN
  98.  
  99.                         'only select boxes not empty, with big size balls
  100.                         IF box.v(t) <> 0 AND box.s(t) = 2 THEN
  101.                             selected = 1
  102.                             SOUND 3000, .1 'made a select
  103.                             oldt = t
  104.                             oldtv = box.v(t) 'save picked box number color
  105.                             GOTO second 'now get second choice
  106.                         END IF
  107.  
  108.                     END IF
  109.  
  110.                     IF selected = 1 THEN 'making second choice
  111.  
  112.                         'if selected an empty box or small ball
  113.                         IF box.v(t) = 0 OR box.s(t) = 1 THEN
  114.  
  115.                             'swap 2nd box data
  116.                             box.v(t) = oldtv
  117.                             box.s(t) = 2
  118.                             'erase 1st box data
  119.                             box.v(oldt) = 0
  120.                             box.s(oldt) = 1
  121.                             SOUND 2000, .1
  122.                             UpdateBoard
  123.                             '===============================
  124.  
  125.                             'Grow small balls
  126.                             FOR d = 1 TO rows * cols
  127.                                 IF box.v(d) <> 0 AND box.s(d) = 1 THEN box.s(d) = 2
  128.                             NEXT
  129.  
  130.                             UpdateBoard
  131.  
  132.                             'check Rows for 5 or more done
  133.                             FOR i = 1 TO (rows * cols) STEP 9
  134.                                 CheckRow i
  135.                             NEXT
  136.  
  137.                             'Check Cols for 5 or more
  138.                             FOR i = 1 TO 9
  139.                                 CheckCol i
  140.                             NEXT
  141.  
  142.                             'See how many boxes left to use...
  143.                             howmany = 0
  144.                             FOR h = 1 TO rows * cols
  145.                                 'empty ones
  146.                                 IF box.v(h) = 0 THEN howmany = howmany + 1
  147.                             NEXT
  148.  
  149.                             'If not enough spaces left, game over
  150.                             IF howmany < 3 THEN
  151.                                 LINE (200, 250)-(400, 350), _RGB(0, 0, 0), BF
  152.                                 LINE (200, 250)-(400, 350), _RGB(255, 255, 255), B
  153.                                 PPRINT 233, 285, 18, _RGB(255, 255, 255), 0, "GAME OVER"
  154.                                 PLAY "mbl16o2bagfedc"
  155.                                 _DISPLAY: SLEEP 6
  156.                                 GOTO restart
  157.                             END IF
  158.  
  159.                             'make 3 more random small balls
  160.                             MakeNewBalls 3, 1
  161.                             GOTO main
  162.  
  163.                         ELSE
  164.  
  165.                             'if clicked on another big ball instead...
  166.                             IF box.s(t) = 2 THEN
  167.                                 'clear previous highlighted selection
  168.                                 selected = 0
  169.                                 UpdateBoard
  170.                                 selected = 1
  171.                                 oldt = t
  172.                                 oldtv = box.v(t) 'save picked box number color
  173.                                 SOUND 3000, .1
  174.                                 GOTO second
  175.                             END IF
  176.  
  177.                         END IF
  178.  
  179.                     END IF
  180.  
  181.                 END IF
  182.             END IF
  183.  
  184.         NEXT
  185.  
  186.     END IF
  187.  
  188.     _DISPLAY
  189.  
  190.     IF INKEY$ <> "" THEN GOTO restart
  191.  
  192.  
  193. SUB CheckRow (num)
  194.  
  195.     'space to hold box nums to clear
  196.     REDIM nums(9)
  197.  
  198.     'found some to clear flag
  199.     rdone = 0
  200.  
  201.     'set place and num
  202.     rc = 1
  203.     nums(1) = num
  204.  
  205.     'step through the boxes
  206.  
  207.     FOR r = (num + 1) TO (num + 8)
  208.  
  209.         'if this box is same as previous...
  210.         IF box.s(r) = 2 AND box.v(r) = box.v(nums(rc)) THEN
  211.             'store this box value in nums too
  212.             nums(rc + 1) = r
  213.             'increase how many so far
  214.             rc = rc + 1
  215.         ELSE
  216.             'bot same, so reset
  217.  
  218.             IF rdone = 0 THEN
  219.                 'no more, so start over from here
  220.                 ERASE nums
  221.                 REDIM nums(9)
  222.                 rc = 1: nums(1) = r
  223.             ELSE
  224.                 'no more can exists on line
  225.                 EXIT FOR
  226.             END IF
  227.         END IF
  228.  
  229.         'if there was 5 or more found
  230.         IF rc >= 5 THEN rdone = 1
  231.  
  232.     NEXT
  233.  
  234.     'if group was found, clear
  235.     IF rdone = 1 THEN
  236.         PLAY "mbl32o3cdefga"
  237.         'step through nums values
  238.         FOR d = 1 TO 9
  239.             IF nums(d) <> 0 THEN
  240.  
  241.                 score = score + 55 '55 points per ball
  242.  
  243.                 x = box.x(nums(d)): y = box.y(nums(d))
  244.                 LINE (x + 2, y + 2)-(x + size - 2, y + size - 2), _RGB(255, 255, 255), BF
  245.                 _DELAY .02: _DISPLAY
  246.                 LINE (x + 2, y + 2)-(x + size - 2, y + size - 2), _RGB(64, 64, 64), BF
  247.                 _DELAY .02: _DISPLAY
  248.                 box.v(nums(d)) = 0: box.s(nums(d)) = 1
  249.             END IF
  250.         NEXT
  251.     END IF
  252.  
  253.     ERASE nums
  254.  
  255.  
  256. SUB CheckCol (num)
  257.  
  258.     'space to hold box nums to clear
  259.     REDIM nums(9)
  260.  
  261.     'found some to clear flag
  262.     rdone = 0
  263.  
  264.     'set place and num
  265.     rc = 1
  266.     nums(1) = num
  267.  
  268.     'step through the boxes
  269.  
  270.     FOR r = (num + 9) TO (rows * cols) STEP 9
  271.  
  272.         'if this box is same as previous...
  273.         IF box.s(r) = 2 AND box.v(r) = box.v(nums(rc)) THEN
  274.             'store this box value in nums too
  275.             nums(rc + 1) = r
  276.             'increase how many so far
  277.             rc = rc + 1
  278.         ELSE
  279.             'bot same, so reset
  280.  
  281.             IF rdone = 0 THEN
  282.                 'no more, so start over from here
  283.                 ERASE nums
  284.                 REDIM nums(9)
  285.                 rc = 1: nums(1) = r
  286.             ELSE
  287.                 'no more can exists on line
  288.                 EXIT FOR
  289.             END IF
  290.         END IF
  291.  
  292.         'if there was 5 or more found
  293.         IF rc >= 5 THEN rdone = 1
  294.  
  295.     NEXT
  296.  
  297.     'if group was found, clear
  298.     IF rdone = 1 THEN
  299.         PLAY "mbl32o3cdefga"
  300.         'step through nums values
  301.         FOR d = 1 TO 9
  302.             IF nums(d) <> 0 THEN
  303.                 score = score + 55 'add to score
  304.                 x = box.x(nums(d)): y = box.y(nums(d))
  305.                 LINE (x + 2, y + 2)-(x + size - 2, y + size - 2), _RGB(255, 255, 255), BF
  306.                 _DELAY .02: _DISPLAY
  307.                 LINE (x + 2, y + 2)-(x + size - 2, y + size - 2), _RGB(64, 64, 64), BF
  308.                 _DELAY .02: _DISPLAY
  309.                 box.v(nums(d)) = 0: box.s(nums(d)) = 1
  310.             END IF
  311.         NEXT
  312.     END IF
  313.  
  314.     ERASE nums
  315.  
  316.  
  317.  
  318. SUB UpdateBoard
  319.  
  320.     CLS
  321.     PPRINT 20, 14, 14, _RGB(200, 200, 200), 0, "SCORE:" + LTRIM$(STR$(score))
  322.     IF score >= hiscore THEN hiscore = score
  323.     PPRINT 475, 14, 14, _RGB(200, 200, 200), 0, "HI:" + LTRIM$(STR$(hiscore))
  324.     PPRINT 220, 10, 20, _RGB(255, 255, 255), 0, "-=MAKE5=-"
  325.  
  326.     '=== draw board based on box values
  327.     bc = 1 'counter
  328.     FOR cl = 1 TO cols
  329.         FOR ro = 1 TO rows
  330.             '=== if empty box
  331.             IF box.v(bc) = 0 THEN
  332.                 LINE (box.x(bc) + 2, box.y(bc) + 2)-(box.x(bc) + size - 2, box.y(bc) + size - 2), _RGB(64, 64, 64), BF
  333.             ELSE
  334.                 LINE (box.x(bc) + 2, box.y(bc) + 2)-(box.x(bc) + size - 2, box.y(bc) + size - 2), _RGB(64, 64, 64), BF
  335.                 '=== draw color ball
  336.                 x2 = box.x(bc) + (size / 2) 'find middle of box
  337.                 y2 = box.y(bc) + (size / 2)
  338.                 IF box.s(bc) = 1 THEN sz = size / 4 ELSE sz = size / 2
  339.                 SELECT CASE box.v(bc)
  340.                     CASE IS = 1: r = 255: g = 64: b = 64 'red
  341.                     CASE IS = 2: r = 0: g = 128: b = 0 'green
  342.                     CASE IS = 3: r = 64: g = 64: b = 255 'blue
  343.                     CASE IS = 4: r = 255: g = 255: b = 0 'yellow
  344.                     CASE IS = 5: r = 255: g = 255: b = 255
  345.                 END SELECT
  346.                 CIRCLE (x2, y2), sz - 4, _RGB(r, g, b)
  347.                 PAINT (x2, y2), _RGB(r, g, b)
  348.             END IF
  349.             bc = bc + 1
  350.         NEXT
  351.     NEXT
  352.     _DISPLAY
  353.     _ICON _DISPLAY 'update app icon on taskbar
  354.  
  355. SUB MakeNewBalls (num, ballsize)
  356.     'Assign 3 new balls
  357.     ball = 0
  358.     DO
  359.         c = INT((RND * (cols * rows)) + 1)
  360.         IF box.v(c) = 0 THEN
  361.             box.v(c) = INT((RND * 5) + 1)
  362.             box.s(c) = ballsize
  363.             ball = ball + 1
  364.         END IF
  365.         IF ball = num THEN EXIT DO
  366.     LOOP
  367.  
  368. SUB PPRINT (x, y, size, clr&, trans&, text$)
  369.     orig& = _DEST
  370.     bit = 32: IF _PIXELSIZE(0) = 1 THEN bit = 256
  371.     FOR t = 0 TO LEN(text$) - 1
  372.         pprintimg& = _NEWIMAGE(16, 16, bit)
  373.         _DEST pprintimg&
  374.         CLS , trans&: COLOR clr&
  375.         PRINT MID$(text$, t + 1, 1);
  376.         _CLEARCOLOR _RGB(0, 0, 0), pprintimg&
  377.         _DEST orig&
  378.         x1 = x + (t * size): x2 = x1 + size
  379.         y1 = y: y2 = y + size
  380.         _PUTIMAGE (x1 - (size / 2), y1)-(x2, y2 + (size / 3)), pprintimg&
  381.         _FREEIMAGE pprintimg&
  382.     NEXT
  383.  
make5.jpg
* make5.jpg (Filesize: 77.14 KB, Dimensions: 618x695, Views: 226)
« Last Edit: January 11, 2021, 08:57:26 pm by Dav »

Offline Dimster

  • Forum Resident
  • Posts: 500
Re: MAKE5 Board clearing puzzle
« Reply #1 on: January 11, 2021, 09:43:32 am »
Hi Dav.. The balls wouldn't erase for me. Is it a complete block of 25 large balls (ie 5 x 5) or does just a row a/o column of 5 large balls cause it to erase?

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: MAKE5 Board clearing puzzle
« Reply #2 on: January 11, 2021, 09:47:56 am »
They weren't erasing for me either until I realized might be difference between yellow and green. ;-))

Offline Dav

  • Forum Resident
  • Posts: 792
Re: MAKE5 Board clearing puzzle
« Reply #3 on: January 11, 2021, 09:52:37 am »
You have make a line of 5 or more balls of the same color to erase them. 

- Dav

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: MAKE5 Board clearing puzzle
« Reply #4 on: January 11, 2021, 10:01:54 am »
Too close for detecting differences specially right after I get up:
 
image_2021-01-11_100144.png

Offline Dav

  • Forum Resident
  • Posts: 792
Re: MAKE5 Board clearing puzzle
« Reply #5 on: January 11, 2021, 10:06:00 am »
Yeah, I think I should adjust the colors again - on my old laptop it's sometimes hard to tell close colors apart unless I'm viewing the screen at the perfect angle.

- Dav

Offline Dimster

  • Forum Resident
  • Posts: 500
Re: MAKE5 Board clearing puzzle
« Reply #6 on: January 11, 2021, 03:31:38 pm »
Thanks Dav - Works great. Not sure where my mind was - so obvious now that the game called for 5 of the same color. Sometimes the obvious is so hard to spot.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: MAKE5 Board clearing puzzle
« Reply #7 on: January 11, 2021, 08:31:54 pm »
@Dav  and surely you meant to change the colors in 9PM edit?

Here is distinctive set:
Code: QB64: [Select]
  1.                     CASE IS = 1: r = 255: g = 64: b = 64 'red
  2.                     CASE IS = 2: r = 0: g = 128: b = 0 'green
  3.                     CASE IS = 3: r = 64: g = 64: b = 255 'blue
  4.                     CASE IS = 4: r = 255: g = 255: b = 0 'yellow
  5.                     CASE IS = 5: r = 255: g = 255: b = 255
  6.  

Hey Dav, if I set up 4 going horizontal and 4 vertical and then put the 5th for both where they meet, shouldn't that clear both, 9 pieces?

Green at the meeting place:
 
image_2021-01-11_205052.png
« Last Edit: January 11, 2021, 08:51:02 pm by bplus »

Offline Dav

  • Forum Resident
  • Posts: 792
Re: MAKE5 Board clearing puzzle
« Reply #8 on: January 11, 2021, 09:03:19 pm »
Those colors look perfect, @bplus. I edited the code and put them in.  Thanks! 

Yes, you are correct - the game should be set up to clear both of those, but I didn't get around to coding it in.  Made the same mistake with the 10x10 puzzle.  I will get working on it when I get back home tonight.

Edit: also, the original game i was playing only allowed pieces to move if they had a clear path. The only way i can figure to do that is adapt a floodfill routine i used for another puzzle.  I may do that.  I was reading about shortest path algos, but they are a bit beyond my understanding at the moment.

- Dav
« Last Edit: January 11, 2021, 09:17:05 pm by Dav »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: MAKE5 Board clearing puzzle
« Reply #9 on: January 11, 2021, 09:43:23 pm »
Quote
Edit: also, the original game i was playing only allowed pieces to move if they had a clear path. The only way i can figure to do that is adapt a floodfill routine i used for another puzzle.  I may do that.  I was reading about shortest path algos, but they are a bit beyond my understanding at the moment.

There are different kinds of paths:
Any path as long as it goes from A to B no matter how round about or a path that has to fit inside the rectangle that contains the 2 cells at corners (which makes sense to me for this game)?

Can you only move horizontally or vertically or allow diagonal?

I bet those little circles have the purpose to block your paths.

I was thinking this game reminds me of Click O' Mania again you had it by another crazy name some time ago and Tetris again and 10x10 :)


Anyway the image to remember in shortest pathfinding is to imagine an ever increasing square qrid around your start cell the first group represent the first step you can take, 4 or 8 neighbors depending on stepping rules the 2nd 1 cell larger on all sides is the second step... continue outward until the board is covered. For each cell in the new frame not stepped on yet you see where you can step to from there. You make a temp array and label all places you can visit in 1 step and then label all places where you can visit in 2 steps.... keep going until you hit your target cell or can't step anywhere else from where you've been. When you hit your target cell you backtrack 9, 8, 7, 6... 1, start.

https://www.qb64.org/forum/index.php?topic=410.msg2878#msg2878
« Last Edit: January 11, 2021, 09:45:19 pm by bplus »

Offline Dav

  • Forum Resident
  • Posts: 792
Re: MAKE5 Board clearing puzzle
« Reply #10 on: January 11, 2021, 10:47:52 pm »
Thanks you, @bplus.  I'll chew on that a while.  And thanks for the link - I had forgotten about that one.  (the original game only allow Hor/vert, not diag).

Back home.  Will get cracking on it...

- Dav
« Last Edit: January 11, 2021, 11:10:44 pm by Dav »