Author Topic: Quick Minesweeper  (Read 10708 times)

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Quick Minesweeper
« on: August 01, 2019, 10:02:05 pm »
A quick game of Minesweeper:
Code: QB64: [Select]
  1. OPTION _EXPLICIT 'Bplus 2019-08-01
  2. DEFINT A-Z '      9 squares 60 x 60 pixels = 540 x 540 screen
  3. CONST xmax = 540, ymax = 540, sq = 60, arrD = 9, mines = 13
  4. _TITLE STR$(mines) + " Mine-sweeper: left click cell to reveal, right click to mark mine (red)"
  5. SCREEN _NEWIMAGE(xmax, ymax, 32)
  6. _SCREENMOVE 300, 10
  7. TYPE boardType
  8.     id AS INTEGER '0 to 8 neighbor mines
  9.     reveal AS INTEGER ' 1 for marked, 0 hidden, -1 for revealed
  10.     mine AS INTEGER '0 or -1
  11. REDIM SHARED b(0 TO arrD + 1, 0 TO arrD + 1) AS boardType 'oversize the board to make it easy to count mines
  12. DIM SHARED restart
  13. DIM gameOver, cc, cr, mbN, c, r
  14. restart = 1
  15.     gameOver = 0
  16.     WHILE gameOver = 0
  17.         IF restart THEN initialize
  18.         mbN = 0
  19.         getCell cc, cr, mbN
  20.         'LOCATE 1, 1: PRINT cc, cr, mbN
  21.         IF mbN = 1 AND b(cc, cr).reveal = 0 THEN
  22.             IF b(cc, cr).mine THEN 'ka boom
  23.                 FOR r = 1 TO arrD 'show all mines
  24.                     FOR c = 1 TO arrD
  25.                         IF b(c, r).mine THEN b(c, r).reveal = -1: showCell c, r
  26.                     NEXT
  27.                 NEXT
  28.                 cText xmax / 2, ymax / 2, 72, &HFF000000, "KA - BOOOMMMM!"
  29.                 cText xmax / 2 - 4, ymax / 2 - 4, 64, &HFFFF0000, "KA - BOOOMMMM!"
  30.                 cText xmax / 2 - 8, ymax / 2 - 8, 56, &HFFFFFF00, "KA - BOOOMMMM!"
  31.                 gameOver = -1
  32.                 _DELAY 7
  33.             ELSE
  34.                 b(cc, cr).reveal = -1: showCell cc, cr
  35.                 IF b(cc, cr).id = 0 THEN sweepZeros cc, cr
  36.             END IF
  37.         ELSEIF mbN = 2 THEN
  38.             IF b(cc, cr).reveal = 1 THEN
  39.                 b(cc, cr).reveal = 0: showCell cc, cr
  40.             ELSE
  41.                 IF b(cc, cr).reveal = 0 THEN b(cc, cr).reveal = 1: showCell cc, cr
  42.             END IF
  43.         END IF
  44.         IF TFwin THEN
  45.             cText xmax / 2, ymax / 2, 30, &HFF001144, "You found all the free cells!"
  46.             cText xmax / 2 - 1, ymax / 2 - 2, 30, &HFF3399BB, "You found all the free cells!"
  47.             _DELAY 5
  48.             gameOver = -1
  49.         END IF
  50.         _LIMIT 60
  51.     WEND
  52.     restart = 1
  53.  
  54. SUB initialize ()
  55.     DIM minesPlaced, rx, ry, x, y, nMines
  56.     restart = 0
  57.     REDIM b(0 TO arrD + 1, 0 TO arrD + 1) AS boardType
  58.     minesPlaced = 0
  59.     WHILE minesPlaced < mines
  60.         rx = INT(RND * arrD) + 1: ry = INT(RND * arrD) + 1
  61.         IF b(rx, ry).mine = 0 THEN
  62.             b(rx, ry).mine = -1: minesPlaced = minesPlaced + 1
  63.         END IF
  64.     WEND
  65.     'count mines amoung the neighbors
  66.     FOR y = 1 TO arrD
  67.         FOR x = 1 TO arrD
  68.             IF b(x, y).mine <> -1 THEN 'not already a mine
  69.                 nMines = b(x - 1, y - 1).mine + b(x - 1, y).mine + b(x - 1, y + 1).mine
  70.                 nMines = nMines + b(x, y - 1).mine + b(x, y + 1).mine
  71.                 nMines = nMines + b(x + 1, y - 1).mine + b(x + 1, y).mine + b(x + 1, y + 1).mine
  72.                 b(x, y).id = -nMines
  73.             ELSE
  74.                 b(x, y).id = 0
  75.             END IF
  76.             b(x, y).reveal = 0
  77.             showCell x, y
  78.         NEXT
  79.     NEXT
  80.  
  81. SUB showCell (c, r)
  82.     DIM x, y, clr AS _UNSIGNED LONG
  83.     x = (c - 1) * sq: y = (r - 1) * sq
  84.     SELECT CASE b(c, r).reveal
  85.         CASE -1: IF b(c, r).mine THEN clr = &HFF883300 ELSE clr = &HFFFFFFFF 'revealed  white with number of mine neighbors
  86.         CASE 0: clr = &HFF008800 'hidden green
  87.         CASE 1: clr = &HFFFF0000 'marked red
  88.     END SELECT
  89.     LINE (x, y)-STEP(sq - 1, sq - 1), clr, BF
  90.     LINE (x, y)-STEP(sq - 1, sq - 1), &HFF000000, B
  91.     IF b(c, r).reveal = -1 THEN
  92.         IF b(c, r).id > 0 THEN cText x + 30, y + 30, 50, &HFF000000, _TRIM$(STR$(b(c, r).id))
  93.         IF b(c, r).mine = -1 THEN cText x + 30, y + 30, 50, &HFFFFFFFF, "*"
  94.     END IF
  95.  
  96. FUNCTION TFwin
  97.     DIM c, x, y
  98.     FOR y = 1 TO arrD
  99.         FOR x = 1 TO arrD
  100.             IF b(x, y).reveal = -1 AND b(x, y).mine = 0 THEN c = c + 1
  101.         NEXT
  102.     NEXT
  103.     IF c = arrD * arrD - mines THEN TFwin = -1
  104.  
  105. SUB getCell (returnCol AS INTEGER, returnRow AS INTEGER, mbNum AS INTEGER)
  106.     DIM m, mx, my, mb1, mb2
  107.     mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  108.     IF mb1 THEN mbNum = 1
  109.     IF mb2 THEN mbNum = 2
  110.     IF mb1 OR mb2 THEN '                      get last place mouse button was down
  111.         WHILE mb1 OR mb2 '                    wait for mouse button release as a "click"
  112.             m = _MOUSEINPUT: mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  113.             mx = _MOUSEX: my = _MOUSEY
  114.         WEND
  115.         returnCol = INT(mx / sq) + 1: returnRow = INT(my / sq) + 1
  116.     END IF
  117.  
  118. SUB sweepZeros (col, row) ' recursive sweep with Rod's limits set
  119.     DIM c, r, cMin, cMax, rMin, rMax, x, y, id
  120.     c = col: r = row 'get copies for recursive sub
  121.     IF c > 2 THEN cMin = c - 1 ELSE cMin = 1
  122.     IF c < arrD - 1 THEN cMax = c + 1 ELSE cMax = arrD
  123.     IF r > 2 THEN rMin = r - 1 ELSE rMin = 1
  124.     IF r < arrD - 1 THEN rMax = r + 1 ELSE rMax = arrD
  125.     FOR y = rMin TO rMax
  126.         FOR x = cMin TO cMax
  127.             IF b(x, y).reveal = 0 THEN
  128.                 id = b(x, y).id
  129.                 IF b(x, y).mine = 0 AND id = 0 THEN
  130.                     b(x, y).reveal = -1 'mark played
  131.                     showCell x, y
  132.                     sweepZeros x, y
  133.                 ELSE
  134.                     IF b(x, y).mine = 0 AND id >= 1 AND id <= 8 THEN
  135.                         b(x, y).reveal = -1
  136.                         showCell x, y
  137.                     END IF
  138.                 END IF
  139.             END IF
  140.         NEXT
  141.     NEXT
  142.  
  143. 'center the text around (x, y) point, needs a graphics screen!
  144. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  145.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  146.     fg = _DEFAULTCOLOR
  147.     'screen snapshot
  148.     cur& = _DEST
  149.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  150.     _DEST I&
  151.     COLOR K, _RGBA32(0, 0, 0, 0)
  152.     _PRINTSTRING (0, 0), txt$
  153.     mult = textHeight / 16
  154.     xlen = LEN(txt$) * 8 * mult
  155.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  156.     COLOR fg
  157.     _FREEIMAGE I&
  158.  
  159.  

2019-08-02 Update: _title change line number location and reflects mines set.
« Last Edit: August 02, 2019, 04:45:18 pm by bplus »

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Quick Minesweeper
« Reply #1 on: August 01, 2019, 10:32:19 pm »
Rigged! I played 5 times, and it never took more than 2 moves for me to blow my ascii up!

Pete :O
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Quick Minesweeper
« Reply #2 on: August 01, 2019, 10:36:23 pm »
Ha! It does have a shade more than std 15% mines. 14/81 = 17.28.. %

It took awhile!.PNG
* It took awhile!.PNG (Filesize: 20.04 KB, Dimensions: 542x567, Views: 308)
Typical!.PNG
* Typical!.PNG (Filesize: 18.9 KB, Dimensions: 544x569, Views: 304)
« Last Edit: August 01, 2019, 11:04:07 pm by bplus »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Quick Minesweeper
« Reply #3 on: August 02, 2019, 12:38:56 pm »
LOL awesome game!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Quick Minesweeper
« Reply #4 on: August 02, 2019, 12:44:47 pm »
Thanks, I am pretty sure Pete knows how to hack this game to play nicer :D

OK I will mine my own business now...

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Quick Minesweeper
« Reply #5 on: August 02, 2019, 04:43:30 pm »
Update: A tiny change to _title to reflect the amount of mines you are playing.

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Quick Minesweeper
« Reply #6 on: August 03, 2019, 08:22:34 pm »
Very cool!

In this kind of games I have not so much luck!
At first attempt I got a 1 in the middle of the green land ... so at the second click I got the mine :-))) LOL
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Quick Minesweeper
« Reply #7 on: August 03, 2019, 08:57:10 pm »
Thanks TempodiBasic!

Maybe this will change everyone's luck, design you own minefield: screen size, cells, cell sizes, and mines.
Here I am using your text editor to fill out a spec form.
Code: QB64: [Select]
  1. OPTION _EXPLICIT 'Bplus started 2019-08-01
  2. ' update 2019-08-02 _title change line number so can reflect changes to mines constant.
  3. ' 2019-08-03 Minesweeper Custom Field.bas creates a file: "Custom Field Specs.txt"
  4. ' that you edit with your text editor, if you select that option in the opening screen menu.
  5.  
  6. DEFINT A-Z
  7. DIM SHARED xmax, ymax, Xsq, Ysq, Xarrd, Yarrd, mines, Xmargin, Ymargin 'set all this in customField sub
  8. _TITLE "Minesweeper: Custom Field"
  9. customField
  10. _TITLE STR$(mines) + " Minesweeper: left click reveals, right marks red"
  11. SCREEN _NEWIMAGE(xmax, ymax, 32)
  12. _SCREENMOVE (1280 - xmax) / 2, (760 - ymax) / 2
  13. TYPE boardType
  14.     id AS INTEGER '0 to 8 neighbor mines
  15.     reveal AS INTEGER ' 1 for marked, 0 hidden, -1 for revealed
  16.     mine AS INTEGER '0 or -1
  17. REDIM SHARED b(0 TO Xarrd + 1, 0 TO Yarrd + 1) AS boardType 'oversize the board to make it easy to count mines
  18. DIM SHARED restart
  19. DIM gameOver, cc, cr, mbN, c, r, s$, sz!
  20. restart = 1
  21.     gameOver = 0
  22.     WHILE gameOver = 0
  23.         IF restart THEN initialize
  24.         mbN = 0
  25.         getCell cc, cr, mbN
  26.         'LOCATE 1, 1: PRINT cc, cr, mbN
  27.         IF mbN = 1 AND b(cc, cr).reveal = 0 THEN
  28.             IF b(cc, cr).mine THEN 'ka boom
  29.                 FOR r = 1 TO Yarrd 'show all mines
  30.                     FOR c = 1 TO Xarrd
  31.                         IF b(c, r).mine THEN b(c, r).reveal = -1: showCell c, r
  32.                     NEXT
  33.                 NEXT
  34.                 s$ = "KA - BOOOMMMM!"
  35.                 sz! = 1.2 * xmax / LEN(s$)
  36.                 cText xmax / 2, ymax / 2, sz!, &HFF000000, s$
  37.                 cText xmax / 2 - 4, ymax / 2 - 4, sz!, &HFFFF0000, s$
  38.                 cText xmax / 2 - 8, ymax / 2 - 8, sz!, &HFFFFFF00, s$
  39.                 gameOver = -1
  40.                 _DELAY 7
  41.             ELSE
  42.                 b(cc, cr).reveal = -1: showCell cc, cr
  43.                 IF b(cc, cr).id = 0 THEN sweepZeros cc, cr
  44.             END IF
  45.         ELSEIF mbN = 2 THEN
  46.             IF b(cc, cr).reveal = 1 THEN
  47.                 b(cc, cr).reveal = 0: showCell cc, cr
  48.             ELSE
  49.                 IF b(cc, cr).reveal = 0 THEN b(cc, cr).reveal = 1: showCell cc, cr
  50.             END IF
  51.         END IF
  52.         IF TFwin THEN
  53.             s$ = "Good Job!"
  54.             sz! = 1.2 * xmax / LEN(s$)
  55.             cText xmax / 2, ymax / 2, sz!, &HFF000000, s$
  56.             cText xmax / 2 - 1, ymax / 2 - 2, sz!, &HFF000055, s$
  57.             _DELAY 5
  58.             gameOver = -1
  59.         END IF
  60.         _LIMIT 60
  61.     WEND
  62.     restart = 1
  63.  
  64. 'set all this 'DIM SHARED xmax, ymax, Xsq, Ysq, XarrD, YarrD, mines, Xmargin, Ymargin
  65. SUB customField
  66.     DIM fName$, fe, fLine$, p, inCnt, beenHere, w$, allow$, choice$
  67.  
  68.     fName$ = "Custom Field Specs.txt"
  69.     IF _FILEEXISTS(fName$) THEN fe = -1 ELSE fe = 0
  70.     allow$ = "12" + CHR$(27)
  71.     PRINT
  72.     PRINT "     Minesweeper options:"
  73.     PRINT
  74.     PRINT "  1. Use mine field settings: 800 x 600 screen with 9 X 9 cells and 10 mines."
  75.     PRINT "  2. Customize your own field settings."
  76.     IF fe THEN PRINT "  3. Use the last customized mine field settings.": allow$ = allow$ + "3"
  77.     PRINT
  78.     PRINT "     or press esc to quit."
  79.     choice$ = getChar$(allow$)
  80.     SELECT CASE choice$
  81.         CASE "1": GOTO default
  82.         CASE "2": GOSUB editCustom
  83.         CASE "3": GOSUB loadCustom
  84.         CASE ELSE: SYSTEM
  85.     END SELECT
  86.     EXIT SUB
  87.  
  88.     editCustom:
  89.     OPEN fName$ FOR OUTPUT AS #1
  90.     PRINT #1, " "
  91.     PRINT #1, "     Custom Field Specs For Your Minesweeper Game"
  92.     PRINT #1, " "
  93.     PRINT #1, " Please fill out the right side of all Equal signs."
  94.     PRINT #1, " "
  95.     PRINT #1, "   X dimensions across the screen:"
  96.     PRINT #1, "                  Screen Width (pixels) = "
  97.     PRINT #1, "      Number of Horizontal Cells Across = "
  98.     PRINT #1, "          Cell Width (12 - 100? pixels) = "
  99.     PRINT #1, " "
  100.     PRINT #1, "   Y dimensions going down:"
  101.     PRINT #1, "                 Screen Height (pixels) = "
  102.     PRINT #1, "                   Number of Cells Down = "
  103.     PRINT #1, "          Cell Height (24 - 80? pixels) = "
  104.     PRINT #1, " "
  105.     PRINT #1, "The percent of mines (8 easy - 15 hard) = "
  106.     PRINT #1, " "
  107.     PRINT #1, "    To finish, Save the file and then close the editor."
  108.     CLOSE #1
  109.     ' I picked up this shortcut from Ken, normally I would call a text editor that I don't know if you have!
  110.     SHELL fName$
  111.     GOSUB loadCustom
  112.     RETURN
  113.  
  114.     loadCustom:
  115.     beenHere = beenHere + 1 'we'll give it 5 tries
  116.     IF beenHere > 5 THEN
  117.         PRINT "OK we tried 5 times, going with default settings..."
  118.         GOTO default 'exit from there
  119.     END IF
  120.     inCnt = 0
  121.     OPEN fName$ FOR INPUT AS #1
  122.     WHILE EOF(1) = 0 ' look to get 7 values from 7 = signs
  123.         LINE INPUT #1, fLine$
  124.         'PRINT fLine$
  125.         p = INSTR(fLine$, "=")
  126.         IF p > 0 THEN
  127.             inCnt = inCnt + 1
  128.             SELECT CASE inCnt
  129.                 CASE 1: xmax = VAL(rightOf$(fLine$, "="))
  130.                 CASE 2: Xarrd = VAL(rightOf$(fLine$, "="))
  131.                 CASE 3: Xsq = VAL(rightOf$(fLine$, "="))
  132.                 CASE 4: ymax = VAL(rightOf$(fLine$, "="))
  133.                 CASE 5: Yarrd = VAL(rightOf$(fLine$, "="))
  134.                 CASE 6: Ysq = VAL(rightOf$(fLine$, "="))
  135.                 CASE 7: mines = VAL(rightOf$(fLine$, "=")) * Xarrd * Yarrd / 100
  136.             END SELECT
  137.             IF inCnt = 7 THEN EXIT WHILE
  138.         END IF
  139.     WEND
  140.     CLOSE #1
  141.     IF inCnt = 7 THEN
  142.         IF Xsq >= 12 THEN
  143.             IF Ysq >= 24 THEN
  144.                 IF xmax >= Xarrd * Xsq THEN
  145.                     IF ymax >= Yarrd * Ysq THEN 'all good
  146.                         GOSUB calcMargins: EXIT SUB
  147.                     ELSE
  148.                         PRINT "Opps, Screen height is not big enough for Y cells * pixels down."
  149.                     END IF
  150.                 ELSE
  151.                     PRINT "Opps, Screen width is not big enough for X cells * pixels across."
  152.                 END IF
  153.             ELSE
  154.                 PRINT "Y Cell pixels down probably not enough."
  155.             END IF
  156.         ELSE
  157.             PRINT "X Cell pixels across probably not enough."
  158.         END IF
  159.     ELSE
  160.         PRINT "We did not get everything filled out by = signs."
  161.     END IF
  162.     PRINT: PRINT "Press any to continue.. "
  163.     SLEEP
  164.     SHELL fName$
  165.     GOTO loadCustom
  166.     RETURN
  167.  
  168.     calcMargins:
  169.     Xmargin = (xmax - Xarrd * Xsq) / 2: Ymargin = (ymax - Yarrd * Ysq) / 2
  170.     RETURN
  171.  
  172.     default:
  173.     xmax = 800: ymax = 600: Xarrd = 9: Yarrd = 9: Xsq = 60: Ysq = 60: mines = 10: GOSUB calcMargins
  174.  
  175. SUB initialize ()
  176.     DIM minesPlaced, rx, ry, x, y, nMines
  177.     restart = 0
  178.     REDIM b(0 TO Xarrd + 1, 0 TO Yarrd + 1) AS boardType
  179.     minesPlaced = 0
  180.     WHILE minesPlaced < mines
  181.         rx = INT(RND * Xarrd) + 1: ry = INT(RND * Yarrd) + 1
  182.         IF b(rx, ry).mine = 0 THEN
  183.             b(rx, ry).mine = -1: minesPlaced = minesPlaced + 1
  184.         END IF
  185.     WEND
  186.     'count mines amoung the neighbors
  187.     FOR y = 1 TO Yarrd
  188.         FOR x = 1 TO Xarrd
  189.             IF b(x, y).mine <> -1 THEN 'not already a mine
  190.                 nMines = b(x - 1, y - 1).mine + b(x - 1, y).mine + b(x - 1, y + 1).mine
  191.                 nMines = nMines + b(x, y - 1).mine + b(x, y + 1).mine
  192.                 nMines = nMines + b(x + 1, y - 1).mine + b(x + 1, y).mine + b(x + 1, y + 1).mine
  193.                 b(x, y).id = -nMines
  194.             ELSE
  195.                 b(x, y).id = 0
  196.             END IF
  197.             b(x, y).reveal = 0
  198.             showCell x, y
  199.         NEXT
  200.     NEXT
  201.  
  202. SUB showCell (c, r)
  203.     DIM x, y, clr AS _UNSIGNED LONG, sz
  204.     x = (c - 1) * Xsq + Xmargin: y = (r - 1) * Ysq + Ymargin
  205.     SELECT CASE b(c, r).reveal
  206.         CASE -1: IF b(c, r).mine THEN clr = &HFF883300 ELSE clr = &HFFFFFFFF 'revealed  white with number of mine neighbors
  207.         CASE 0: clr = &HFF008800 'hidden green
  208.         CASE 1: clr = &HFFFF0000 'marked red
  209.     END SELECT
  210.     LINE (x, y)-STEP(Xsq - 1, Ysq - 1), clr, BF
  211.     LINE (x, y)-STEP(Xsq - 1, Ysq - 1), &HFF000000, B
  212.     IF Xsq < Ysq THEN sz = .8 * Xsq ELSE sz = .8 * Ysq
  213.     IF b(c, r).reveal = -1 THEN
  214.         IF b(c, r).id > 0 THEN cText x + Xsq / 2, y + Ysq / 2, sz, &HFF000000, _TRIM$(STR$(b(c, r).id))
  215.         IF b(c, r).mine = -1 THEN cText x + Xsq / 2, y + Ysq / 2, sz, &HFFFFFFFF, "*"
  216.     END IF
  217.  
  218. FUNCTION TFwin
  219.     DIM c, x, y
  220.     FOR y = 1 TO Yarrd
  221.         FOR x = 1 TO Xarrd
  222.             IF b(x, y).reveal = -1 AND b(x, y).mine = 0 THEN c = c + 1
  223.         NEXT
  224.     NEXT
  225.     IF c = Xarrd * Yarrd - mines THEN TFwin = -1
  226.  
  227. SUB getCell (returnCol AS INTEGER, returnRow AS INTEGER, mbNum AS INTEGER)
  228.     DIM m, mx, my, mb1, mb2
  229.     mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  230.     IF mb1 THEN mbNum = 1
  231.     IF mb2 THEN mbNum = 2
  232.     IF mb1 OR mb2 THEN '                      get last place mouse button was down
  233.         WHILE mb1 OR mb2 '                    wait for mouse button release as a "click"
  234.             m = _MOUSEINPUT: mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  235.             mx = _MOUSEX: my = _MOUSEY
  236.         WEND
  237.         returnCol = INT((mx - Xmargin) / Xsq) + 1: returnRow = INT((my - Ymargin) / Ysq) + 1
  238.         IF returnCol < 1 OR returnCol > Xarrd OR returnRow < 1 OR returnRow > Yarrd THEN mbNum = 0
  239.     END IF
  240.  
  241. SUB sweepZeros (col, row) ' recursive sweep with Rod's limits set
  242.     DIM c, r, cMin, cMax, rMin, rMax, x, y, id
  243.     c = col: r = row 'get copies for recursive sub
  244.     IF c > 2 THEN cMin = c - 1 ELSE cMin = 1
  245.     IF c < Xarrd - 1 THEN cMax = c + 1 ELSE cMax = Xarrd
  246.     IF r > 2 THEN rMin = r - 1 ELSE rMin = 1
  247.     IF r < Yarrd - 1 THEN rMax = r + 1 ELSE rMax = Yarrd
  248.     FOR y = rMin TO rMax
  249.         FOR x = cMin TO cMax
  250.             IF b(x, y).reveal = 0 THEN
  251.                 id = b(x, y).id
  252.                 IF b(x, y).mine = 0 AND id = 0 THEN
  253.                     b(x, y).reveal = -1 'mark played
  254.                     showCell x, y
  255.                     sweepZeros x, y
  256.                 ELSE
  257.                     IF b(x, y).mine = 0 AND id >= 1 AND id <= 8 THEN
  258.                         b(x, y).reveal = -1
  259.                         showCell x, y
  260.                     END IF
  261.                 END IF
  262.             END IF
  263.         NEXT
  264.     NEXT
  265.  
  266. 'center the text around (x, y) point, needs a graphics screen!
  267. SUB cText (x, y, textHeight AS SINGLE, K AS _UNSIGNED LONG, txt$)
  268.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult!, xlen
  269.     fg = _DEFAULTCOLOR
  270.     'screen snapshot
  271.     cur& = _DEST
  272.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  273.     _DEST I&
  274.     COLOR K, _RGBA32(0, 0, 0, 0)
  275.     _PRINTSTRING (0, 0), txt$
  276.     mult! = textHeight / 16
  277.     xlen = LEN(txt$) * 8 * mult!
  278.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  279.     COLOR fg
  280.     _FREEIMAGE I&
  281.  
  282. FUNCTION rightOf$ (source$, of$)
  283.     IF INSTR(source$, of$) > 0 THEN rightOf$ = MID$(source$, INSTR(source$, of$) + LEN(of$))
  284.  
  285. FUNCTION getChar$ (fromStr$)
  286.     DIM OK AS INTEGER, k$
  287.     WHILE OK = 0
  288.         k$ = INKEY$
  289.         IF LEN(k$) THEN
  290.             IF INSTR(fromStr$, k$) <> 0 THEN OK = -1
  291.         END IF
  292.         _LIMIT 200
  293.     WEND
  294.     _KEYCLEAR
  295.     getChar$ = k$
  296.  
  297.  

EDIT: shorten 2nd _TITLE for smaller screens
Minesweeper Custom Field.PNG
* Minesweeper Custom Field.PNG (Filesize: 65.69 KB, Dimensions: 1264x655, Views: 287)
Good Job!.PNG
* Good Job!.PNG (Filesize: 76.55 KB, Dimensions: 1198x727, Views: 283)
« Last Edit: August 03, 2019, 10:12:23 pm by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Quick Minesweeper
« Reply #8 on: August 04, 2019, 01:18:03 pm »
and fine also customizable version.
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Quick Minesweeper
« Reply #9 on: August 04, 2019, 02:55:17 pm »
Thanks TempodiBasic,

I am putting together sound effects and maybe images for next round of customization's.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Quick Minesweeper
« Reply #10 on: August 04, 2019, 11:12:23 pm »
And here is Minesweeper you may customize and with sound effects added:
Code: QB64: [Select]
  1. OPTION _EXPLICIT 'Bplus started 2019-08-01
  2. ' update 2019-08-02 _title change line number so can reflect changes to mines constant.
  3. ' 2019-08-03 Minesweeper Custom Field.bas creates a file: "Custom Field Specs.txt"
  4. ' that you edit with your text editor, if you select that option in the opening screen menu.
  5.  
  6. ' 2019-08-04 add assets can use to the customize file, also if the file exits don't rewrite a blank one.
  7. ' Thanks to SoundBible for sounds dowmloaded under License Attribution 3.0
  8. ' http://soundbible.com
  9. ' https://creativecommons.org/licenses/by/3.0/us/
  10.  
  11. DEFINT A-Z
  12. DIM SHARED xmax, ymax, Xsq, Ysq, Xarrd, Yarrd, mines, Xmargin, Ymargin 'set all this in customField sub
  13. DIM SHARED ToggleSnd AS LONG, BombSnd AS LONG, ApplauseSnd AS LONG, ButtonSnd AS LONG, AhhSnd AS LONG, ShipBellSnd AS LONG
  14. DIM SHARED SwooshSnd AS LONG
  15. _TITLE "Minesweeper Custom wAssets"
  16. customField
  17. ToggleSnd = _SNDOPEN("Toggle.wav") '
  18. BombSnd = _SNDOPEN("BigBomb.wav") '
  19. ApplauseSnd = _SNDOPEN("Applause.wav") '
  20. ButtonSnd = _SNDOPEN("Button.wav") '
  21. ShipBellSnd = _SNDOPEN("Ships bell.wav") '
  22. SwooshSnd = _SNDOPEN("Swoosh.wav")
  23. DIM SHARED rndSnd(9) AS LONG
  24. rndSnd(0) = _SNDOPEN("Ahhh.wav") '
  25. rndSnd(1) = _SNDOPEN("BuzzFade.wav") '
  26. rndSnd(2) = _SNDOPEN("Carpet Ripping.wav") '
  27. rndSnd(3) = _SNDOPEN("DrumRoll.wav") '
  28. rndSnd(4) = _SNDOPEN("DyingNeon.wav") '
  29. rndSnd(5) = _SNDOPEN("ElectricMotor.wav") '
  30. rndSnd(6) = _SNDOPEN("Slime.wav")
  31. rndSnd(7) = _SNDOPEN("Gaffy.wav") '
  32. rndSnd(8) = _SNDOPEN("Monkey.wav") '
  33. rndSnd(9) = _SNDOPEN("Rooster.wav") '
  34. 'DIM i    'test load and sounds
  35. 'FOR i = 6 TO 6
  36. '    _SNDPLAY (rndSnd(i))
  37. '    PRINT i;
  38. '    IF rndSnd(i) = 0 THEN PRINT i; " not loaded." ELSE PRINT
  39. '    _DELAY 3
  40. 'NEXT
  41.  
  42. IF ButtonSnd = 0 THEN PRINT "No Button snd": END
  43. _TITLE STR$(mines) + " Minesweeper: left click cell to reveal, right click to mark mine (red)"
  44. SCREEN _NEWIMAGE(xmax, ymax, 32)
  45. _SCREENMOVE (1280 - xmax) / 2 + 60, (760 - ymax) / 2
  46. TYPE boardType
  47.     id AS INTEGER '0 to 8 neighbor mines
  48.     reveal AS INTEGER ' 1 for marked, 0 hidden, -1 for revealed
  49.     mine AS INTEGER '0 or -1
  50. REDIM SHARED b(0 TO Xarrd + 1, 0 TO Yarrd + 1) AS boardType 'oversize the board to make it easy to count mines
  51. DIM SHARED restart
  52. DIM gameOver, cc, cr, mbN, c, r, s$, sz!
  53. restart = 1
  54.     gameOver = 0
  55.     WHILE gameOver = 0
  56.         IF restart THEN initialize
  57.         mbN = 0
  58.         getCell cc, cr, mbN
  59.         'LOCATE 1, 1: PRINT cc, cr, mbN
  60.         IF mbN = 1 AND b(cc, cr).reveal = 0 THEN
  61.             IF b(cc, cr).mine THEN 'ka boom
  62.                 _SNDPLAY BombSnd
  63.                 FOR r = 1 TO Yarrd 'show all mines
  64.                     FOR c = 1 TO Xarrd
  65.                         IF b(c, r).mine THEN b(c, r).reveal = -1: showCell c, r
  66.                     NEXT
  67.                 NEXT
  68.                 s$ = "KA - BOOOMMMM!"
  69.                 sz! = 1.2 * xmax / LEN(s$)
  70.                 cText xmax / 2, ymax / 2, sz!, &HFF000000, s$
  71.                 cText xmax / 2 - 4, ymax / 2 - 4, sz!, &HFFFF0000, s$
  72.                 cText xmax / 2 - 8, ymax / 2 - 8, sz!, &HFFFFFF00, s$
  73.                 gameOver = -1
  74.                 _DELAY 7
  75.             ELSE
  76.                 IF b(cc, cr).reveal = 0 THEN
  77.                     IF RND < .75 THEN _SNDPLAY ButtonSnd ELSE _SNDPLAY rndSnd(INT(RND * 10))
  78.                     b(cc, cr).reveal = -1: showCell cc, cr
  79.                     IF b(cc, cr).id = 0 THEN sweepZeros cc, cr
  80.                 END IF
  81.             END IF
  82.         ELSEIF mbN = 2 THEN
  83.             _SNDPLAY ToggleSnd
  84.             IF b(cc, cr).reveal = 1 THEN
  85.                 b(cc, cr).reveal = 0: showCell cc, cr
  86.             ELSE
  87.                 IF b(cc, cr).reveal = 0 THEN b(cc, cr).reveal = 1: showCell cc, cr
  88.             END IF
  89.         END IF
  90.         IF TFwin THEN
  91.             _SNDPLAY ApplauseSnd
  92.             s$ = "Good Job!"
  93.             sz! = 1.2 * xmax / LEN(s$)
  94.             cText xmax / 2, ymax / 2, sz!, &HFF000000, s$
  95.             cText xmax / 2 - 1, ymax / 2 - 2, sz!, &HFF000055, s$
  96.             _DELAY 5
  97.             gameOver = -1
  98.         END IF
  99.         _LIMIT 60
  100.     WEND
  101.     restart = 1
  102.  
  103. 'set all this 'DIM SHARED xmax, ymax, Xsq, Ysq, XarrD, YarrD, mines, Xmargin, Ymargin
  104. SUB customField
  105.     DIM fName$, fe, fLine$, p, inCnt, beenHere, w$, allow$, choice$
  106.  
  107.     fName$ = "Custom Field Specs.txt"
  108.     IF _FILEEXISTS(fName$) THEN fe = -1 ELSE fe = 0
  109.     allow$ = "12" + CHR$(27)
  110.     PRINT
  111.     PRINT "     Minesweeper options:"
  112.     PRINT
  113.     PRINT "  1. Use mine field settings: 800 x 600 screen with 9 X 9 cells and 10 mines."
  114.     PRINT "  2. Customize your own field settings."
  115.     IF fe THEN PRINT "  3. Use the last customized mine field settings.": allow$ = allow$ + "3"
  116.     PRINT
  117.     PRINT "     or press esc to quit."
  118.     choice$ = getChar$(allow$)
  119.     SELECT CASE choice$
  120.         CASE "1": GOTO default
  121.         CASE "2": GOSUB editCustom
  122.         CASE "3": GOSUB loadCustom
  123.         CASE ELSE: SYSTEM
  124.     END SELECT
  125.     EXIT SUB
  126.  
  127.     editCustom:
  128.     IF fe = 0 THEN 'need to start the file, otherwise just edit what's there
  129.         OPEN fName$ FOR OUTPUT AS #1
  130.         PRINT #1, " "
  131.         PRINT #1, "     Custom Field Specs for your Minesweeper Game"
  132.         PRINT #1, " "
  133.         PRINT #1, " Please fill out the right side of all Equal signs."
  134.         PRINT #1, " "
  135.         PRINT #1, "   X dimensions across the screen:"
  136.         PRINT #1, "                  Screen Width (pixels) = "
  137.         PRINT #1, "      Number of Horizontal Cells Across = "
  138.         PRINT #1, "          Cell Width (12 - 100? pixels) = "
  139.         PRINT #1, " "
  140.         PRINT #1, "   Y dimensions going down:"
  141.         PRINT #1, "                 Screen Height (pixels) = "
  142.         PRINT #1, "                   Number of Cells Down = "
  143.         PRINT #1, "          Cell Height (24 - 80? pixels) = "
  144.         PRINT #1, " "
  145.         PRINT #1, "The percent of mines (8 easy - 15 hard) = "
  146.         PRINT #1, " "
  147.         PRINT #1, "    To finish, Save the file and then close the editor."
  148.         CLOSE #1
  149.     END IF
  150.     ' I picked up this shortcut from Ken, normally I would call a text editor that I don't know if you have!
  151.     SHELL fName$
  152.     GOSUB loadCustom
  153.     RETURN
  154.  
  155.     loadCustom:
  156.     beenHere = beenHere + 1 'we'll give it 5 tries
  157.     IF beenHere > 5 THEN
  158.         PRINT "OK we tried 5 times, going with default settings..."
  159.         GOTO default 'exit from there
  160.     END IF
  161.     inCnt = 0
  162.     OPEN fName$ FOR INPUT AS #1
  163.     WHILE EOF(1) = 0 ' look to get 7 values from 7 = signs
  164.         LINE INPUT #1, fLine$
  165.         'PRINT fLine$
  166.         p = INSTR(fLine$, "=")
  167.         IF p > 0 THEN
  168.             inCnt = inCnt + 1
  169.             SELECT CASE inCnt
  170.                 CASE 1: xmax = VAL(rightOf$(fLine$, "="))
  171.                 CASE 2: Xarrd = VAL(rightOf$(fLine$, "="))
  172.                 CASE 3: Xsq = VAL(rightOf$(fLine$, "="))
  173.                 CASE 4: ymax = VAL(rightOf$(fLine$, "="))
  174.                 CASE 5: Yarrd = VAL(rightOf$(fLine$, "="))
  175.                 CASE 6: Ysq = VAL(rightOf$(fLine$, "="))
  176.                 CASE 7: mines = VAL(rightOf$(fLine$, "=")) * Xarrd * Yarrd / 100
  177.             END SELECT
  178.             IF inCnt = 7 THEN EXIT WHILE
  179.         END IF
  180.     WEND
  181.     CLOSE #1
  182.  
  183.     'debug....................
  184.     'PRINT "xmax = "; xmax, "ymax = "; ymax, "Xarrd = "; Xarrd, "Yarrd = "; Yarrd
  185.     'PRINT "Xsq = "; Xsq, "Ysq = "; Ysq, "Mines = "; mines
  186.     'INPUT "OK... enter "; w$
  187.  
  188.     IF inCnt = 7 THEN
  189.         IF Xsq >= 12 THEN
  190.             IF Ysq >= 24 THEN
  191.                 IF xmax >= Xarrd * Xsq THEN
  192.                     IF ymax >= Yarrd * Ysq THEN 'all good
  193.                         GOSUB calcMargins: EXIT SUB
  194.                     ELSE
  195.                         PRINT "Opps, Screen height is not big enough for Y cells * pixels down. "
  196.                     END IF
  197.                 ELSE
  198.                     PRINT "Opps, Screen width is not big enough for X cells * pixels across. "
  199.                 END IF
  200.             ELSE
  201.                 PRINT "Y Cell pixels down probably not enough. "
  202.             END IF
  203.         ELSE
  204.             PRINT "X Cell pixels across probably not enough. "
  205.         END IF
  206.     ELSE
  207.         PRINT "We did not get everything filled out by = signs."
  208.     END IF
  209.     PRINT: PRINT "Press any to continue.. "
  210.     SLEEP
  211.     SHELL fName$
  212.     GOTO loadCustom
  213.     RETURN
  214.  
  215.     calcMargins:
  216.     Xmargin = (xmax - Xarrd * Xsq) / 2: Ymargin = (ymax - Yarrd * Ysq) / 2
  217.     RETURN
  218.  
  219.     default:
  220.     xmax = 800: ymax = 600: Xarrd = 9: Yarrd = 9: Xsq = 60: Ysq = 60: mines = 10: GOSUB calcMargins
  221.  
  222.  
  223. SUB initialize ()
  224.     DIM minesPlaced, rx, ry, x, y, nMines
  225.     restart = 0
  226.     _SNDPLAY ShipBellSnd
  227.     REDIM b(0 TO Xarrd + 1, 0 TO Yarrd + 1) AS boardType
  228.     minesPlaced = 0
  229.     WHILE minesPlaced < mines
  230.         rx = INT(RND * Xarrd) + 1: ry = INT(RND * Yarrd) + 1
  231.         IF b(rx, ry).mine = 0 THEN
  232.             b(rx, ry).mine = -1: minesPlaced = minesPlaced + 1
  233.         END IF
  234.     WEND
  235.     'count mines amoung the neighbors
  236.     FOR y = 1 TO Yarrd
  237.         FOR x = 1 TO Xarrd
  238.             IF b(x, y).mine <> -1 THEN 'not already a mine
  239.                 nMines = b(x - 1, y - 1).mine + b(x - 1, y).mine + b(x - 1, y + 1).mine
  240.                 nMines = nMines + b(x, y - 1).mine + b(x, y + 1).mine
  241.                 nMines = nMines + b(x + 1, y - 1).mine + b(x + 1, y).mine + b(x + 1, y + 1).mine
  242.                 b(x, y).id = -nMines
  243.             ELSE
  244.                 b(x, y).id = 0
  245.             END IF
  246.             b(x, y).reveal = 0
  247.             showCell x, y
  248.         NEXT
  249.     NEXT
  250.  
  251. SUB showCell (c, r)
  252.     DIM x, y, clr AS _UNSIGNED LONG, sz
  253.     x = (c - 1) * Xsq + Xmargin: y = (r - 1) * Ysq + Ymargin
  254.     SELECT CASE b(c, r).reveal
  255.         CASE -1: IF b(c, r).mine THEN clr = &HFF883300 ELSE clr = &HFFFFFFFF 'revealed  white with number of mine neighbors
  256.         CASE 0: clr = &HFF008800 'hidden green
  257.         CASE 1: clr = &HFFFF0000 'marked red
  258.     END SELECT
  259.     LINE (x, y)-STEP(Xsq - 1, Ysq - 1), clr, BF
  260.     LINE (x, y)-STEP(Xsq - 1, Ysq - 1), &HFF000000, B
  261.     IF Xsq < Ysq THEN sz = .8 * Xsq ELSE sz = .8 * Ysq
  262.     IF b(c, r).reveal = -1 THEN
  263.         IF b(c, r).id > 0 THEN cText x + Xsq / 2, y + Ysq / 2, sz, &HFF000000, _TRIM$(STR$(b(c, r).id))
  264.         IF b(c, r).mine = -1 THEN cText x + Xsq / 2, y + Ysq / 2, sz, &HFFFFFFFF, "*"
  265.     END IF
  266.  
  267. FUNCTION TFwin
  268.     DIM c, x, y
  269.     FOR y = 1 TO Yarrd
  270.         FOR x = 1 TO Xarrd
  271.             IF b(x, y).reveal = -1 AND b(x, y).mine = 0 THEN c = c + 1
  272.         NEXT
  273.     NEXT
  274.     IF c = Xarrd * Yarrd - mines THEN TFwin = -1
  275.  
  276. SUB getCell (returnCol AS INTEGER, returnRow AS INTEGER, mbNum AS INTEGER)
  277.     DIM m, mx, my, mb1, mb2
  278.     mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  279.     IF mb1 THEN mbNum = 1
  280.     IF mb2 THEN mbNum = 2
  281.     IF mb1 OR mb2 THEN '                      get last place mouse button was down
  282.         WHILE mb1 OR mb2 '                    wait for mouse button release as a "click"
  283.             m = _MOUSEINPUT: mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  284.             mx = _MOUSEX: my = _MOUSEY
  285.         WEND
  286.         returnCol = INT((mx - Xmargin) / Xsq) + 1: returnRow = INT((my - Ymargin) / Ysq) + 1
  287.         IF returnCol < 1 OR returnCol > Xarrd OR returnRow < 1 OR returnRow > Yarrd THEN mbNum = 0
  288.     END IF
  289.  
  290. SUB sweepZeros (col, row) ' recursive sweep with Rod's limits set
  291.     DIM c, r, cMin, cMax, rMin, rMax, x, y, id
  292.     _SNDPLAY SwooshSnd
  293.     c = col: r = row 'get copies for recursive sub
  294.     IF c > 2 THEN cMin = c - 1 ELSE cMin = 1
  295.     IF c < Xarrd - 1 THEN cMax = c + 1 ELSE cMax = Xarrd
  296.     IF r > 2 THEN rMin = r - 1 ELSE rMin = 1
  297.     IF r < Yarrd - 1 THEN rMax = r + 1 ELSE rMax = Yarrd
  298.     FOR y = rMin TO rMax
  299.         FOR x = cMin TO cMax
  300.             IF b(x, y).reveal = 0 THEN
  301.                 id = b(x, y).id
  302.                 IF b(x, y).mine = 0 AND id = 0 THEN
  303.                     b(x, y).reveal = -1 'mark played
  304.                     showCell x, y
  305.                     sweepZeros x, y
  306.                 ELSE
  307.                     IF b(x, y).mine = 0 AND id >= 1 AND id <= 8 THEN
  308.                         b(x, y).reveal = -1
  309.                         showCell x, y
  310.                     END IF
  311.                 END IF
  312.             END IF
  313.         NEXT
  314.     NEXT
  315.  
  316. 'center the text around (x, y) point, needs a graphics screen!
  317. SUB cText (x, y, textHeight AS SINGLE, K AS _UNSIGNED LONG, txt$)
  318.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult!, xlen
  319.     fg = _DEFAULTCOLOR
  320.     'screen snapshot
  321.     cur& = _DEST
  322.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  323.     _DEST I&
  324.     COLOR K, _RGBA32(0, 0, 0, 0)
  325.     _PRINTSTRING (0, 0), txt$
  326.     mult! = textHeight / 16
  327.     xlen = LEN(txt$) * 8 * mult!
  328.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  329.     COLOR fg
  330.     _FREEIMAGE I&
  331.  
  332. FUNCTION rightOf$ (source$, of$)
  333.     IF INSTR(source$, of$) > 0 THEN rightOf$ = MID$(source$, INSTR(source$, of$) + LEN(of$))
  334.  
  335. FUNCTION getChar$ (fromStr$)
  336.     DIM OK AS INTEGER, k$
  337.     WHILE OK = 0
  338.         k$ = INKEY$
  339.         IF LEN(k$) THEN
  340.             IF INSTR(fromStr$, k$) <> 0 THEN OK = -1
  341.         END IF
  342.         _LIMIT 200
  343.     WEND
  344.     _KEYCLEAR
  345.     getChar$ = k$
  346.  
  347.  

It's currently set to pretty easy game, just don't click top left cell for starters, the percentages are bad.
* Minesweeper wAssets.zip (Filesize: 3.9 MB, Downloads: 129)

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Quick Minesweeper
« Reply #11 on: August 07, 2019, 06:25:13 pm »
You like various challenges, bplus; maybe you'll like the idea for this one -- create a hexagonal minesweeper, just to be different.

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(640, 480, 32)
  2. DrawMap 50, 50, 24, 12, 10, -1
  3.  
  4.  
  5. SUB DrawMap (TopLeftX, TopLeftY, Hexsize, MapXLimit, MapYLimit, C)
  6.     F = _FONT
  7.     HexWidth = SQR(3) * Hexsize: HexHeight = 2 * Hexsize 'Height and Width of each individual hex
  8.     FOR X = 0 TO MapXLimit
  9.         FOR Y = 0 TO MapYLimit
  10.             CenterX = TopLeftX + X * HexWidth
  11.             CenterY = TopLeftY + Y * HexHeight * 0.75
  12.             IF Y MOD 2 THEN CenterX = CenterX + HexWidth / 2 'offset for odd/even rows
  13.             Point1X = CenterX - HexWidth / 2
  14.             Point2X = CenterX
  15.             Point3x = CenterX + HexWidth / 2
  16.             Point1y = CenterY - HexHeight / 2
  17.             Point2y = CenterY - HexHeight / 4
  18.             Point3y = CenterY + HexHeight / 4
  19.             Point4y = CenterY + HexHeight / 2
  20.             LINE (Point1X, Point2y)-(Point2X, Point1y), C 'NorthWest
  21.             LINE (Point2X, Point1y)-(Point3x, Point2y), C 'NorthEast
  22.             LINE (Point3x, Point2y)-(Point3x, Point3y), C 'East
  23.             LINE (Point3x, Point3y)-(Point2X, Point4y), C 'SouthEast
  24.             LINE (Point2X, Point4y)-(Point1X, Point3y), C 'SouthWest
  25.             LINE (Point1X, Point3y)-(Point1X, Point2y), C 'West
  26.  
  27.             'If we want the coordinates, we use the following, else just delete or remark out the next few lines:
  28.             _FONT 8
  29.             COLOR &HFFFF0000, 0
  30.             CenterText Point1X, Point1y, Point3x, Point4y, _TRIM$(STR$(X)) + "," + _TRIM$(STR$(Y))
  31.         NEXT
  32.     NEXT
  33.     _FONT F
  34.     COLOR DC, BG
  35.  
  36. SUB CenterText (x1, y1, x2, y2, text$)
  37.     text$ = _TRIM$(text$)
  38.     xmax = x2 - x1: ymax = y2 - y1
  39.     textlength = _PRINTWIDTH(text$)
  40.     xpos = (xmax - textlength) / 2
  41.     ypos = (ymax - _FONTHEIGHT) / 2
  42.     _PRINTSTRING (x1 + xpos, y1 + ypos), text$

Trickiest part here is remembering that diagonals are only a half step off.  View the example above and study the coordinate system carefully:

Y  coordinates change by 1 step each time we move in the grid.
X coordinates only change by .5 each step we move in the grid. 
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Quick Minesweeper
« Reply #12 on: August 07, 2019, 09:09:35 pm »
:) Thanks Steve, you got me thinking.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Quick Minesweeper
« Reply #13 on: August 07, 2019, 11:26:06 pm »
OK the quick version seems to be working OK:
Code: QB64: [Select]
  1. OPTION _EXPLICIT 'Bplus 2019-08-07 instigated by Steve McNeill
  2. '2019-08-08 fixed incomplete sweepZeros problem
  3.  
  4. DEFINT A-Z '      10 x 10 Hex grid, 12% mines
  5. CONST xmax = 510, ymax = 430, cellR = 25, arrD = 10, mines = 10
  6. DIM SHARED xspacing!, yspacing!
  7. xspacing! = 2 * cellR * COS(_D2R(30)): yspacing! = cellR * (1 + SIN(_D2R(30)))
  8.  
  9. _TITLE STR$(mines) + " Mine-sweeper Hexagon Style!: left click cell to reveal, right click to mark mine (red)"
  10. SCREEN _NEWIMAGE(xmax, ymax, 32)
  11. _SCREENMOVE 300, 10
  12. TYPE boardType
  13.     x AS SINGLE 'pixel location
  14.     y AS SINGLE 'pixel location
  15.     id AS INTEGER '0 to 8 neighbor mines
  16.     reveal AS INTEGER ' 1 for marked, 0 hidden, -1 for revealed
  17.     mine AS INTEGER '0 or -1
  18. REDIM SHARED b(0 TO arrD + 1, 0 TO arrD + 1) AS boardType 'oversize the board to make it easy to count mines
  19. DIM SHARED restart, dxdyOFF(6, 1), dxdyNoOff(6, 1)
  20. DIM gameOver, cc, cr, mbN, c, r, i, dx, dy
  21.  
  22. 'set the 2 sets of directions to neighbors a cell could have depending if the row is offset or not
  23. RESTORE NoOff
  24. FOR i = 0 TO 5
  25.     READ dx, dy
  26.     dxdyNoOff(i, 0) = dx: dxdyNoOff(i, 1) = dy
  27. RESTORE xOff
  28. FOR i = 0 TO 5
  29.     READ dx, dy
  30.     dxdyOFF(i, 0) = dx: dxdyOFF(i, 1) = dy
  31.  
  32. restart = 1
  33.     gameOver = 0
  34.     WHILE gameOver = 0
  35.         IF restart THEN initialize
  36.         mbN = 0
  37.         getCell cc, cr, mbN
  38.         IF mbN = 1 AND b(cc, cr).reveal = 0 THEN
  39.             IF b(cc, cr).mine THEN 'ka boom
  40.                 FOR r = 1 TO arrD 'show all mines
  41.                     FOR c = 1 TO arrD
  42.                         IF b(c, r).mine THEN b(c, r).reveal = -1: showCell c, r
  43.                     NEXT
  44.                 NEXT
  45.                 cText xmax / 2, ymax / 2, 72, &HFF000000, "KA - BOOOMMMM!"
  46.                 cText xmax / 2 - 4, ymax / 2 - 4, 64, &HFFFF0000, "KA - BOOOMMMM!"
  47.                 cText xmax / 2 - 8, ymax / 2 - 8, 56, &HFFFFFF00, "KA - BOOOMMMM!"
  48.                 gameOver = -1
  49.                 _DELAY 7
  50.             ELSE
  51.                 b(cc, cr).reveal = -1: showCell cc, cr
  52.                 IF b(cc, cr).id = 0 THEN sweepZeros cc, cr
  53.             END IF
  54.         ELSEIF mbN = 2 THEN
  55.             IF b(cc, cr).reveal = 1 THEN
  56.                 b(cc, cr).reveal = 0: showCell cc, cr
  57.             ELSE
  58.                 IF b(cc, cr).reveal = 0 THEN b(cc, cr).reveal = 1: showCell cc, cr
  59.             END IF
  60.         END IF
  61.         IF TFwin THEN
  62.             cText xmax / 2, ymax / 2, 80, &HFF001144, "Good Job!"
  63.             cText xmax / 2 - 1, ymax / 2 - 2, 80, &HFF000055, "Good Job!"
  64.             _DELAY 5
  65.             gameOver = -1
  66.         END IF
  67.         _LIMIT 60
  68.     WEND
  69.     restart = 1
  70.  
  71. NoOff:
  72. DATA 1,0,0,-1,0,1,-1,-1,-1,0,-1,1
  73.  
  74. xOff:
  75. DATA -1,0,0,-1,0,1,1,-1,1,0,1,1
  76.  
  77. SUB initialize ()
  78.     DIM minesPlaced, rx, ry, x, y, nMines, xoffset!
  79.     CLS
  80.     restart = 0
  81.     REDIM b(0 TO arrD + 1, 0 TO arrD + 1) AS boardType
  82.     minesPlaced = 0
  83.     WHILE minesPlaced < mines
  84.         rx = INT(RND * arrD) + 1: ry = INT(RND * arrD) + 1
  85.         IF b(rx, ry).mine = 0 THEN
  86.             b(rx, ry).mine = -1: minesPlaced = minesPlaced + 1
  87.         END IF
  88.     WEND
  89.     'count mines amoung the neighbors
  90.     FOR y = 1 TO arrD
  91.         IF y MOD 2 = 0 THEN xoffset! = .5 * xspacing! ELSE xoffset! = 0
  92.         FOR x = 1 TO arrD
  93.             IF b(x, y).mine <> -1 THEN 'not already a mine
  94.                 '2 sets of neighbors depending if x offset or not
  95.                 IF xoffset! > .1 THEN
  96.                     nMines = b(x - 1, y).mine + b(x, y - 1).mine + b(x, y + 1).mine
  97.                     nMines = nMines + b(x + 1, y - 1).mine + b(x + 1, y).mine + b(x + 1, y + 1).mine
  98.                 ELSE
  99.                     nMines = b(x + 1, y).mine + b(x, y - 1).mine + b(x, y + 1).mine
  100.                     nMines = nMines + b(x - 1, y - 1).mine + b(x - 1, y).mine + b(x - 1, y + 1).mine
  101.                 END IF
  102.                 b(x, y).id = -nMines
  103.             ELSE
  104.                 b(x, y).id = 0
  105.             END IF
  106.             b(x, y).x = x * xspacing! + xoffset! + 5
  107.             b(x, y).y = y * yspacing! + 5
  108.             b(x, y).reveal = 0
  109.             showCell x, y
  110.         NEXT
  111.     NEXT
  112.  
  113. SUB showCell (c, r)
  114.     DIM da, x!, y!, lastx!, lasty!, clr AS _UNSIGNED LONG
  115.     SELECT CASE b(c, r).reveal
  116.         CASE -1: IF b(c, r).mine THEN clr = &HFF883300 ELSE clr = &HFFFFFFFF 'revealed  white with number of mine neighbors
  117.         CASE 0: clr = &HFF008800 'hidden green
  118.         CASE 1: clr = &HFFFF0000 'marked red
  119.     END SELECT
  120.     lastx! = b(c, r).x + cellR * COS(_D2R(-30))
  121.     lasty! = b(c, r).y + cellR * SIN(_D2R(-30))
  122.     FOR da = 30 TO 330 STEP 60
  123.         x! = b(c, r).x + cellR * COS(_D2R(da))
  124.         y! = b(c, r).y + cellR * SIN(_D2R(da))
  125.         LINE (lastx!, lasty!)-(x!, y!), &HFFFF00FF
  126.         lastx! = x!: lasty! = y!
  127.     NEXT
  128.     PAINT (b(c, r).x, b(c, r).y), clr, &HFFFF00FF
  129.     IF b(c, r).reveal = -1 THEN
  130.         'cText b(c, r).x, b(c, r).y, 15, &HFF000000, _TRIM$(STR$(c)) + "," + _TRIM$(STR$(r))
  131.         IF b(c, r).id > 0 THEN cText b(c, r).x, b(c, r).y, 35, &HFF000000, _TRIM$(STR$(b(c, r).id))
  132.         IF b(c, r).mine = -1 THEN cText b(c, r).x, b(c, r).y, 35, &HFFFFFFFF, "*"
  133.     END IF
  134.  
  135. FUNCTION TFwin
  136.     DIM c, x, y
  137.     FOR y = 1 TO arrD
  138.         FOR x = 1 TO arrD
  139.             IF b(x, y).reveal = -1 AND b(x, y).mine = 0 THEN c = c + 1
  140.         NEXT
  141.     NEXT
  142.     IF c = arrD * arrD - mines THEN TFwin = -1
  143.  
  144. SUB getCell (returnCol AS INTEGER, returnRow AS INTEGER, mbNum AS INTEGER)
  145.     DIM m, mx, my, mb1, mb2, r, c
  146.     mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  147.     IF mb1 THEN mbNum = 1
  148.     IF mb2 THEN mbNum = 2
  149.     IF mb1 OR mb2 THEN '                      get last place mouse button was down
  150.         WHILE mb1 OR mb2 '                    wait for mouse button release as a "click"
  151.             m = _MOUSEINPUT: mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  152.             mx = _MOUSEX: my = _MOUSEY
  153.         WEND
  154.         FOR r = 1 TO arrD
  155.             FOR c = 1 TO arrD
  156.                 IF ((mx - b(c, r).x) ^ 2 + (my - b(c, r).y) ^ 2) ^ .5 < .5 * xspacing! THEN
  157.                     returnCol = c: returnRow = r: EXIT SUB
  158.                 END IF
  159.             NEXT
  160.         NEXT
  161.         mbNum = 0 'still here then clicked wrong
  162.     END IF
  163.  
  164. SUB sweepZeros (col, row)
  165.     DIM c, r, d, x, y, id
  166.     c = col: r = row 'get copies for recursive sub
  167.     FOR d = 0 TO 5
  168.         IF r MOD 2 = 0 THEN
  169.             x = dxdyOFF(d, 0) + c: y = dxdyOFF(d, 1) + r
  170.         ELSE
  171.             x = dxdyNoOff(d, 0) + c: y = dxdyNoOff(d, 1) + r
  172.         END IF
  173.         IF x >= 1 AND x <= arrD AND y >= 1 AND y <= arrD THEN
  174.             IF b(x, y).reveal = 0 THEN
  175.                 id = b(x, y).id
  176.                 IF b(x, y).mine = 0 AND id = 0 THEN
  177.                     b(x, y).reveal = -1 'mark played
  178.                     showCell x, y
  179.                     sweepZeros x, y
  180.                 ELSEIF b(x, y).mine = 0 AND id >= 1 THEN
  181.                     b(x, y).reveal = -1
  182.                     showCell x, y
  183.                 END IF
  184.             END IF
  185.         END IF
  186.     NEXT
  187.  
  188. 'center the text around (x, y) point, needs a graphics screen!
  189. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  190.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  191.     fg = _DEFAULTCOLOR
  192.     'screen snapshot
  193.     cur& = _DEST
  194.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  195.     _DEST I&
  196.     COLOR K, _RGBA32(0, 0, 0, 0)
  197.     _PRINTSTRING (0, 0), txt$
  198.     mult = textHeight / 16
  199.     xlen = LEN(txt$) * 8 * mult
  200.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  201.     COLOR fg
  202.     _FREEIMAGE I&
  203.  

hmm... the sweeper might be leaving holes

Update/Code EDIT: found the cause of the incomplete sweeps and fixed in the above code.
Hex Minsweeper.PNG
* Hex Minsweeper.PNG (Filesize: 22.14 KB, Dimensions: 513x451, Views: 157)
« Last Edit: August 08, 2019, 10:33:53 am by bplus »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Quick Minesweeper
« Reply #14 on: August 07, 2019, 11:51:54 pm »
Here's a little tweaking to the settings (and number sizes) so you can play around with a 30x30 grid, with 100 mines.  It looks a lot more like an actual minesweeper game to me now.  :D

Code: QB64: [Select]
  1. OPTION _EXPLICIT 'Bplus 2019-08-07 instigated by Steve McNeill
  2.  
  3. DEFINT A-Z '      30 x 30 Hex grid, 12% mines
  4. CONST xmax = 510, ymax = 430, cellR = 9, arrD = 30, mines = 100
  5. DIM SHARED xspacing!, yspacing!
  6. xspacing! = 2 * cellR * COS(_D2R(30)): yspacing! = cellR * (1 + SIN(_D2R(30)))
  7.  
  8. _TITLE STR$(mines) + " Mine-sweeper Hexagon Style!: left click cell to reveal, right click to mark mine (red)"
  9. SCREEN _NEWIMAGE(xmax, ymax, 32)
  10. _SCREENMOVE 300, 10
  11. TYPE boardType
  12.     x AS SINGLE 'pixel location
  13.     y AS SINGLE 'pixel location
  14.     id AS INTEGER '0 to 8 neighbor mines
  15.     reveal AS INTEGER ' 1 for marked, 0 hidden, -1 for revealed
  16.     mine AS INTEGER '0 or -1
  17. REDIM SHARED b(0 TO arrD + 1, 0 TO arrD + 1) AS boardType 'oversize the board to make it easy to count mines
  18. DIM SHARED restart, dxdyOFF(5, 1), dxdyNoOff(5, 1)
  19. DIM gameOver, cc, cr, mbN, c, r, i, dx, dy
  20.  
  21. 'set the 2 sets of directions to neighbors a cell could have depending if the row is offset or not
  22. RESTORE NoOff
  23. FOR i = 0 TO 5
  24.     READ dx, dy
  25.     dxdyNoOff(i, 0) = dx: dxdyNoOff(i, 1) = dy
  26. RESTORE xOff
  27. FOR i = 0 TO 5
  28.     READ dx, dy
  29.     dxdyOFF(i, 0) = dx: dxdyOFF(i, 1) = dy
  30.  
  31. restart = 1
  32.     gameOver = 0
  33.     WHILE gameOver = 0
  34.         IF restart THEN initialize
  35.         mbN = 0
  36.         getCell cc, cr, mbN
  37.         IF mbN = 1 AND b(cc, cr).reveal = 0 THEN
  38.             IF b(cc, cr).mine THEN 'ka boom
  39.                 FOR r = 1 TO arrD 'show all mines
  40.                     FOR c = 1 TO arrD
  41.                         IF b(c, r).mine THEN b(c, r).reveal = -1: showCell c, r
  42.                     NEXT
  43.                 NEXT
  44.                 cText xmax / 2, ymax / 2, 72, &HFF000000, "KA - BOOOMMMM!"
  45.                 cText xmax / 2 - 4, ymax / 2 - 4, 64, &HFFFF0000, "KA - BOOOMMMM!"
  46.                 cText xmax / 2 - 8, ymax / 2 - 8, 56, &HFFFFFF00, "KA - BOOOMMMM!"
  47.                 gameOver = -1
  48.                 _DELAY 7
  49.             ELSE
  50.                 b(cc, cr).reveal = -1: showCell cc, cr
  51.                 IF b(cc, cr).id = 0 THEN sweepZeros cc, cr
  52.             END IF
  53.         ELSEIF mbN = 2 THEN
  54.             IF b(cc, cr).reveal = 1 THEN
  55.                 b(cc, cr).reveal = 0: showCell cc, cr
  56.             ELSE
  57.                 IF b(cc, cr).reveal = 0 THEN b(cc, cr).reveal = 1: showCell cc, cr
  58.             END IF
  59.         END IF
  60.         IF TFwin THEN
  61.             cText xmax / 2, ymax / 2, 80, &HFF001144, "Good Job!"
  62.             cText xmax / 2 - 1, ymax / 2 - 2, 80, &HFF000055, "Good Job!"
  63.             _DELAY 15
  64.             gameOver = -1
  65.         END IF
  66.         _LIMIT 60
  67.     WEND
  68.     restart = 1
  69.  
  70. NoOff:
  71. DATA 1,0,0,-1,0,1,-1,-1,-1,0,-1,1
  72.  
  73. xOff:
  74. DATA -1,0,0,-1,0,1,1,-1,1,0,1,1
  75.  
  76. SUB initialize ()
  77.     DIM minesPlaced, rx, ry, x, y, nMines, xoffset!
  78.     CLS
  79.     restart = 0
  80.     REDIM b(0 TO arrD + 1, 0 TO arrD + 1) AS boardType
  81.     minesPlaced = 0
  82.     WHILE minesPlaced < mines
  83.         rx = INT(RND * arrD) + 1: ry = INT(RND * arrD) + 1
  84.         IF b(rx, ry).mine = 0 THEN
  85.             b(rx, ry).mine = -1: minesPlaced = minesPlaced + 1
  86.         END IF
  87.     WEND
  88.     'count mines amoung the neighbors
  89.     FOR y = 1 TO arrD
  90.         IF y MOD 2 = 0 THEN xoffset! = .5 * xspacing! ELSE xoffset! = 0
  91.         FOR x = 1 TO arrD
  92.             IF b(x, y).mine <> -1 THEN 'not already a mine
  93.                 '2 sets of neighbors depending if x offset or not
  94.                 IF xoffset! > .1 THEN
  95.                     nMines = b(x - 1, y).mine + b(x, y - 1).mine + b(x, y + 1).mine
  96.                     nMines = nMines + b(x + 1, y - 1).mine + b(x + 1, y).mine + b(x + 1, y + 1).mine
  97.                 ELSE
  98.                     nMines = b(x + 1, y).mine + b(x, y - 1).mine + b(x, y + 1).mine
  99.                     nMines = nMines + b(x - 1, y - 1).mine + b(x - 1, y).mine + b(x - 1, y + 1).mine
  100.                 END IF
  101.                 b(x, y).id = -nMines
  102.             ELSE
  103.                 b(x, y).id = 0
  104.             END IF
  105.             b(x, y).x = x * xspacing! + xoffset! + 5
  106.             b(x, y).y = y * yspacing! + 5
  107.             b(x, y).reveal = 0
  108.             showCell x, y
  109.         NEXT
  110.     NEXT
  111.  
  112. SUB showCell (c, r)
  113.     DIM da, x!, y!, lastx!, lasty!, clr AS _UNSIGNED LONG
  114.     SELECT CASE b(c, r).reveal
  115.         CASE -1: IF b(c, r).mine THEN clr = &HFF883300 ELSE clr = &HFFFFFFFF 'revealed  white with number of mine neighbors
  116.         CASE 0: clr = &HFF008800 'hidden green
  117.         CASE 1: clr = &HFFFF0000 'marked red
  118.     END SELECT
  119.     lastx! = b(c, r).x + cellR * COS(_D2R(-30))
  120.     lasty! = b(c, r).y + cellR * SIN(_D2R(-30))
  121.     FOR da = 30 TO 330 STEP 60
  122.         x! = b(c, r).x + cellR * COS(_D2R(da))
  123.         y! = b(c, r).y + cellR * SIN(_D2R(da))
  124.         LINE (lastx!, lasty!)-(x!, y!), &HFFFF00FF
  125.         lastx! = x!: lasty! = y!
  126.     NEXT
  127.     PAINT (b(c, r).x, b(c, r).y), clr, &HFFFF00FF
  128.     IF b(c, r).reveal = -1 THEN
  129.         'cText b(c, r).x, b(c, r).y, 15, &HFF000000, _TRIM$(STR$(c)) + "," + _TRIM$(STR$(r))
  130.         IF b(c, r).id > 0 THEN cText b(c, r).x, b(c, r).y, 35, &HFF000000, _TRIM$(STR$(b(c, r).id))
  131.         IF b(c, r).mine = -1 THEN cText b(c, r).x, b(c, r).y, 35, &HFFFFFFFF, "*"
  132.     END IF
  133.  
  134. FUNCTION TFwin
  135.     DIM c, x, y
  136.     FOR y = 1 TO arrD
  137.         FOR x = 1 TO arrD
  138.             IF b(x, y).reveal = -1 AND b(x, y).mine = 0 THEN c = c + 1
  139.         NEXT
  140.     NEXT
  141.     IF c = arrD * arrD - mines THEN TFwin = -1
  142.  
  143. SUB getCell (returnCol AS INTEGER, returnRow AS INTEGER, mbNum AS INTEGER)
  144.     DIM m, mx, my, mb1, mb2, r, c
  145.     mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  146.     IF mb1 THEN mbNum = 1
  147.     IF mb2 THEN mbNum = 2
  148.     IF mb1 OR mb2 THEN '                      get last place mouse button was down
  149.         WHILE mb1 OR mb2 '                    wait for mouse button release as a "click"
  150.             m = _MOUSEINPUT: mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  151.             mx = _MOUSEX: my = _MOUSEY
  152.         WEND
  153.         FOR r = 1 TO arrD
  154.             FOR c = 1 TO arrD
  155.                 IF ((mx - b(c, r).x) ^ 2 + (my - b(c, r).y) ^ 2) ^ .5 < .5 * xspacing! THEN
  156.                     returnCol = c: returnRow = r: EXIT SUB
  157.                 END IF
  158.             NEXT
  159.         NEXT
  160.         mbNum = 0 'still here then clicked wrong
  161.     END IF
  162.  
  163. SUB sweepZeros (col, row) ' recursive sweep with Rod's limits set
  164.     DIM c, r, d, x, y, id
  165.     c = col: r = row 'get copies for recursive sub
  166.     FOR d = 0 TO 5
  167.         IF r MOD 2 = 0 THEN
  168.             x = dxdyNoOff(d, 0) + c: y = dxdyNoOff(d, 1) + r
  169.         ELSE
  170.             x = dxdyOFF(d, 0) + c: y = dxdyOFF(d, 1) + r
  171.         END IF
  172.         IF x >= 1 AND x <= arrD AND y >= 1 AND y <= arrD THEN
  173.             IF b(x, y).reveal = 0 THEN
  174.                 id = b(x, y).id
  175.                 IF b(x, y).mine = 0 AND id = 0 THEN
  176.                     b(x, y).reveal = -1 'mark played
  177.                     showCell x, y
  178.                     sweepZeros x, y
  179.                 ELSE
  180.                     IF b(x, y).mine = 0 AND id >= 1 AND id <= 8 THEN
  181.                         b(x, y).reveal = -1
  182.                         showCell x, y
  183.                     END IF
  184.                 END IF
  185.             END IF
  186.         END IF
  187.     NEXT
  188.  
  189. 'center the text around (x, y) point, needs a graphics screen!
  190. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  191.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  192.     fg = _DEFAULTCOLOR
  193.     'screen snapshot
  194.     cur& = _DEST
  195.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  196.     _DEST I&
  197.     COLOR K, _RGBA32(0, 0, 0, 0)
  198.     _PRINTSTRING (0, 0), txt$
  199.     mult = textHeight / 16
  200.     xlen = LEN(txt$) * 8 * mult
  201.     _PUTIMAGE (x - .15 * xlen, y - .15 * textHeight)-STEP(.33 * xlen, .33 * textHeight), I&, cur&
  202.     COLOR fg
  203.     _FREEIMAGE I&
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!