This article is an experiment to create a Simple MineSweeper as shown in Figure 1, using an ESP32 microcontroller board with a 1.8″ REDTAB st7735 display. The display resolution is 128×160, the same hardware as Simple Tetris [Part 1, Part 2 and part 3] mentioned earlier, still using MicroPython as the main. The explanation starts step by step from screen generation, randomization, counting, motion control, scrolling the options frame turn off visibility, establishing a relationship between identifying where the bomb is likely to be, picking open and counting points at the end of the game.
Simple MineSweeper is one of the first games we’ve been imitating to study ideas and develop programming techniques since the DOS era and the GUI-based Windows operating system DOS, which was written and worked on the DOS operating system at the time, change the mode to graphics mode to contact with mouse and draw pixels by yourself (It’s the same thing as writing on the ESP32 microcontroller board, but it doesn’t have an operating system to use) So let’s get started.
Start building
The written content has two main parts: the first part is the development of the back-end system of the game, which is the data structure for storing the location of the bombs, counting how many bombs there are around, drawing the screen to see the results of the work in the area of randomization and counting the number of bombs around it. And finish with moving by pressing the left, right, top and bottom switches to use for selecting the position of the grid.
Data structure
The design of the game on a 128×160 display with the font size 16×16 forced us to use an 8×6 grid as the game grid and create a variable for storing table data named table as follows
table = [
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]
]
The data stored in the table contains numbers that have the following meanings:
- 0 means an empty space or there’s no bombs around.
- 1-8 means the surrounding area with 1, 2, 3, 4, 5, 6, 7 or 8 bombs according to the specified value.
- 9 means the location of the bomb
Random the bomb
From the table for collecting the location of the bomb by specifying that if there’s a bomb, let that field store a value of 9 and for ease of display testing. We set the bomb to be displayed as a red square and put a * symbol as shown in Figures 2 and 3.
The randomization algorithm is as follows.
- Set the number of successfully random bombs to 0.
- Random x and y values. If no bombs are found in the table in row y, column x, then that cell will store 9 and increase the number of successful bombs.
- Return to 1 until the required number of bombs is obtained.
Code
table = [
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]
]
counter = 0
while (counter < 10):
x = random.randint(1,maxCol)-1
y = random.randint(1,maxRow)-1
if (table[y][x] == 0):
# print("Bomb no.{} at ({},{}).".format(counter+1,x,y))
table[y][x] = 9
counter+=1
Counting the bombs around the cell
When the number of bombs in the table is reached as specified. The next step is to count how many bombs are around that position. As an example of the counting result in Figure 4 (displays the location of the bomb as a solid red square).
From Figure 4, if set to row 0, column 0 shows that there is no bomb around itself, so it reports a blank. (The number of bombs is 0) but in row 5, column 0, 2 bombs were found: 1 from the above row and 1 from the bottom. In the example of row 5, column 5 found 3 bombs from the left, top and below etc.
The bomb counting algorithm is carried out by dividing the cases of counting as follows:
- The first row
- The first column in the first row, Let’s look at it from the right, bottom, and bottom right.
- The last column in the first row, Let’s look at it from the left, bottom left, and below.
- The other columns in the first row, look from the left, right, bottom left, bottom, and bottom right.
- The last row
- The first column in the last row, Let’s look at it from the top, top right, and right side.
- is the last column in the last row, Let’s look at it from the left, top left, and above.
- are the other columns in the last row, Let’s look at it from the left, top left, top, top right, and right.
- other rows
- is the first column, Let’s look at it from the top, top right, right, bottom right, and bottom.
- is the last column, Let’s look at it from the left, top left, top, bottom, and bottom left.
- Other columns are viewed from the left, top left, top, top right, right, bottom right, bottom and bottom left.
Code
## เติมตัวเลข
for row in range(maxRow):
for col in range(maxCol):
sum = 0
if (table[row][col] != 9):
if (row == 0): # first row
if col == 0: # first col
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
elif col == maxCol-1: # last col
if (table[row][col-1]==9): # left
sum += 1
if (table[row+1][col-1]==9): # bottpm left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
else: # other cols
if (table[row][col-1]==9): # left
sum += 1
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col-1]==9): # bottom left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
elif (row == maxRow-1): # last row
if col == 0: # คอลัมน์แรก
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col+1]==9): # right
sum += 1
elif col == maxCol-1: # last col
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row][col-1]==9): # left
sum += 1
else: # คอลัมน์อื่น ๆ
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col-1]==9): # left
sum += 1
if (table[row][col+1]==9): # right
sum += 1
else:
if col == 0: # คอลัมน์แรก
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
elif col == maxCol-1: # last col
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row][col-1]==9): # left
sum += 1
if (table[row+1][col-1]==9): # bottom left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
else: # คอลัมน์อื่น ๆ
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col-1]==9): # left
sum += 1
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col-1]==9): # bottom left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
table[row][col] = sum
Screen drawing to test
Drawing data from the table on the display as shown in Figure 5 is as follows.
w = 20
h = 20
for row in range(6):
y = row*h+4+2
for col in range(8):
x = col*w+2
if table[row][col]:
if (table[row][col]== 9):
scr.fill_rect(x,y,w-4,h-4, bgColor)
scr.text(font,"*",x,y,tft.YELLOW,bgColor)
else:
scr.fill_rect(x,y,w-4,h-4, tft.BLUE)
scr.text(font,"{}".format(table[row][col]),x,y,tft.WHITE,tft.BLUE)
else:
scr.fill_rect(x,y,w-4,h-4, tft.BLUE)
Movement
The movement is performed by pressing the left, right, top, or bottom switches to move the position of the rectangle as shown in Figure 6. The principle of operation is based on memorizing the last position of the current box with the variables posX and posY, as well as writing a draw/delete function. rectangular frame as follows:
def cursor(marked=True):
w = 20
h = 20
if marked:
scr.rect(posX*w,posY*h+4,w,h,tft.WHITE)
else:
scr.rect(posX*w,posY*h+4,w,h,tft.BLACK)
The code part of the four direction switch response is written as follows:
#######################################################
##### Input : move to the left
#######################################################
if keL.value() == 0:
#updated = True
if (posX > 0):
cursor(False)
posX -= 1
cursor()
#######################################################
##### Input : move to the right
#######################################################
if keR.value() == 0:
#updated = True
if (posX < maxCol-1):
cursor(False)
posX += 1
cursor()
#######################################################
##### Input : move to the top
#######################################################
if keU.value() == 0:
#updated = True
if (posY > 0):
cursor(False)
posY -= 1
cursor()
#######################################################
##### Input : move to bottom
#######################################################
if keD.value() == 0:
#updated = True
if (posY < maxRow-1):
cursor(False)
posY += 1
cursor()
Example code 1
Code
#################################################################
# mineSweep Part 1
# JarutEx 2021-11-12
# 128x160
#################################################################
import gc
import os
import sys
import time
import machine as mc
from machine import Pin,SPI, Timer
import math
import st7735 as tft
import vga1_16x16 as font
import random
#################################################################
###### setting ##################################################
#################################################################
gc.enable()
gc.collect()
mc.freq(240000000)
spi = SPI(2, baudrate=26000000,
sck=Pin(14), mosi=Pin(12),
polarity=0, phase=0)
#### Key
keL = Pin(39, Pin.IN, Pin.PULL_UP)
keU = Pin(34, Pin.IN, Pin.PULL_UP)
keD = Pin(35, Pin.IN, Pin.PULL_UP)
keR = Pin(32, Pin.IN, Pin.PULL_UP)
swM1 = Pin(33, Pin.IN, Pin.PULL_UP)
swM2 = Pin(25, Pin.IN, Pin.PULL_UP)
swA = Pin(26, Pin.IN, Pin.PULL_UP)
swB = Pin(27, Pin.IN, Pin.PULL_UP)
spk = Pin(19,Pin.OUT)
spk.on()
time.sleep(0.1)
spk.off()
# dc, rst, cs
scr = tft.ST7735(spi, 128, 160, dc=Pin(15, Pin.OUT), reset=Pin(13,Pin.OUT), cs=Pin(2, Pin.OUT), rotation=3)
scr.initr()
Tmr = Timer(0)
Render = Timer(1)
bgColor = tft.color565(0x96,0x24,0x24)
updated = False
gameOver = False
maxRow = const(6)
maxCol = const(8)
table = [
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]
]
posX = 0
posY = 0
#################################################################
###### sub modules ##############################################
#################################################################
def splash():
scr.fill(bgColor)
scr.text(font,"mine", 20, 42, tft.YELLOW, bgColor)
for i in range(200):
color = tft.color565(55+i,55+i,55+i)
scr.text(font,"Sweep", 56, 60, color, bgColor)
time.sleep_ms(10)
time.sleep_ms(2000)
def randomTable():
global table
table = [
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]
]
counter = 0
while (counter < 10):
x = random.randint(1,maxCol)-1
y = random.randint(1,maxRow)-1
if (table[y][x] == 0):
# print("Bomb no.{} at ({},{}).".format(counter+1,x,y))
table[y][x] = 9
counter+=1
## เติมตัวเลข
for row in range(maxRow):
for col in range(maxCol):
sum = 0
if (table[row][col] != 9):
if (row == 0): # first row
if col == 0: # first col
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
elif col == maxCol-1: # last col
if (table[row][col-1]==9): # left
sum += 1
if (table[row+1][col-1]==9): # bottom left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
else: # คอลัมน์อื่น ๆ
if (table[row][col-1]==9): # left
sum += 1
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col-1]==9): # bottom left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
elif (row == maxRow-1): # last row
if col == 0: # คอลัมน์แรก
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col+1]==9): # right
sum += 1
elif col == maxCol-1: # last col
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row][col-1]==9): # left
sum += 1
else: # คอลัมน์อื่น ๆ
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col-1]==9): # left
sum += 1
if (table[row][col+1]==9): # right
sum += 1
else:
if col == 0: # first col
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
elif col == maxCol-1: # last col
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row][col-1]==9): # left
sum += 1
if (table[row+1][col-1]==9): # bottom left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
else: # คอลัมน์อื่น ๆ
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col-1]==9): # left
sum += 1
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col-1]==9): # bottom left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
table[row][col] = sum
def cbInput(x):
global updated, posX, posY
#######################################################
##### Input
#######################################################
if (swM2.value() == 0):
randomTable()
updated = True
#######################################################
##### Input : move to the left
#######################################################
if keL.value() == 0:
#updated = True
if (posX > 0):
cursor(False)
posX -= 1
cursor()
#######################################################
##### Input : move to the right
#######################################################
if keR.value() == 0:
#updated = True
if (posX < maxCol-1):
cursor(False)
posX += 1
cursor()
#######################################################
##### Input : move to top
#######################################################
if keU.value() == 0:
#updated = True
if (posY > 0):
cursor(False)
posY -= 1
cursor()
#######################################################
##### Input : move to bottom
#######################################################
if keD.value() == 0:
#updated = True
if (posY < maxRow-1):
cursor(False)
posY += 1
cursor()
def cbRender(x):
global updated
#######################################################
##### screen updated
#######################################################
if (updated):
draw()
updated = False
def draw():
w = 20
h = 20
for row in range(6):
y = row*h+4+2
for col in range(8):
x = col*w+2
if table[row][col]:
if (table[row][col]== 9):
scr.fill_rect(x,y,w-4,h-4, bgColor)
scr.text(font,"*",x,y,tft.YELLOW,bgColor)
else:
scr.fill_rect(x,y,w-4,h-4, tft.BLUE)
scr.text(font,"{}".format(table[row][col]),x,y,tft.WHITE,tft.BLUE)
else:
scr.fill_rect(x,y,w-4,h-4, tft.BLUE)
def cursor(marked=True):
w = 20
h = 20
if marked:
scr.rect(posX*w,posY*h+4,w,h,tft.WHITE)
else:
scr.rect(posX*w,posY*h+4,w,h,tft.BLACK)
#################################################################
###### main program #############################################
#################################################################
#splash()
randomTable()
scr.fill(tft.BLACK)
draw()
cursor()
Tmr.init( period=200, mode=Timer.PERIODIC, callback=cbInput)
Render.init( period=100, mode=Timer.PERIODIC, callback=cbRender)
while swM1.value():
pass
scr.fill(0)
Tmr.deinit()
Render.deinit()
spi.deinit()
Adjustment
From the program code in the first part, it is called the function of the backend which allows program developers to see the data in the location. But if the players saw this information, there would be no challenge. Therefore, there must be a screen for closing the player not to see, as shown in Figure 6.
Data Structure 2
To create a challenge and give the player an idea of predicting the location of the bomb, a variable for holding the state of each cell has been created as a variable named plate, which has the following values:
- 0 means it hasn’t been opened yet.
- 1 means it has been opened
- 2 means the location that the player determines to be the location of the bomb.
The data structure of the plate is as follows: when randomizing the location of the bomb, the plate will be set to 0 in all fields.
plate = [
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]
]
Bomb marking
This example game design stipulates that if a location is where the player thinks it’s a bomb, press swB to change that cell’s state to the expected bomb location along with showing the mark ! As shown in Figure 7.
From Figure 7 added the count of the bomb mark is stored in the markCounter variable and if the player presses the same position, it means canceling the position as the program code as follows:
#######################################################
##### Input : maybe bomb
#######################################################
if swB.value() == 0:
if (plate[posY][posX] == 0):
if (markCounter < maxBomb): # less than the number of bomb
plate[posY][posX] = 2
markCounter += 1
updated = True
elif (plate[posY][posX] == 2):
plate[posY][posX] = 0
markCounter -= 1
updated = True
Opening
Turning on changes the plate’s state to 1 and checks the value of the table variable at that position, and if it’s 9, it explodes, it’s game over. If not, it will display the value of the number of bombs as shown in Figures 1 and 8.
From Figure 8, the code for the SWA response is as follows:
#######################################################
##### Input : choose
#######################################################
if swA.value() == 0:
if (plate[posY][posX] == 0):
if (table[posY][posX] == 9):
gameOver = True
plate[posY][posX] = 1
updated = True
The display has been changed, if any plate is 0, it shows solid, if 1 it shows the value from the table, and if 2 it shows ! As shown in Figure 7, the program code is as follows.
w = 20
h = 20
for row in range(6):
y = row*h+4+2
for col in range(8):
x = col*w+2
if plate[row][col]:
if (plate[row][col] == 1):
if (table[row][col]== 9):
scr.fill_rect(x,y,w-4,h-4, bgColor)
scr.text(font,"*",x,y,tft.YELLOW,bgColor)
else:
scr.fill_rect(x,y,w-4,h-4, tft.BLUE)
if (table[row][col] > 0):
scr.text(font,"{}".format(table[row][col]),x,y,tft.WHITE,tft.BLUE)
else:
scr.fill_rect(x,y,w-4,h-4, tft.GRAY)
scr.text(font,"!",x,y,tft.BLACK,tft.GRAY)
else:
scr.fill_rect(x,y,w-4,h-4, tft.GRAY)
Counting the scores.
The score is counted based on the number of bomb guesses the player has and displays the result to end the game as in the example in Figure 9. The concept is as follows in the program code, that is, if any of the plate’s fields have a value of 2 and match a table that holds a value of 9, which is the value of that position. Mark that it was a bomb with the locationon of the bomb. The score will be increased by 1 point.
score = 0
for i in range(maxRow):
for j in range(maxCol):
if ((plate[i][j] == 2) and (table[i][j] == 9)):
score += 1
Example Code
Code
#################################################################
# mineSweep Part2
# JarutEx 2021-11-12
# 128x160
#################################################################
import gc
import os
import sys
import time
import machine as mc
from machine import Pin,SPI, Timer
import math
import st7735 as tft
import vga1_16x16 as font
import random
#################################################################
###### setting ##################################################
#################################################################
gc.enable()
gc.collect()
mc.freq(240000000)
spi = SPI(2, baudrate=26000000,
sck=Pin(14), mosi=Pin(12),
polarity=0, phase=0)
#### Key
keL = Pin(39, Pin.IN, Pin.PULL_UP)
keU = Pin(34, Pin.IN, Pin.PULL_UP)
keD = Pin(35, Pin.IN, Pin.PULL_UP)
keR = Pin(32, Pin.IN, Pin.PULL_UP)
swM1 = Pin(33, Pin.IN, Pin.PULL_UP)
swM2 = Pin(25, Pin.IN, Pin.PULL_UP)
swA = Pin(26, Pin.IN, Pin.PULL_UP)
swB = Pin(27, Pin.IN, Pin.PULL_UP)
spk = Pin(19,Pin.OUT)
spk.on()
time.sleep(0.1)
spk.off()
# dc, rst, cs
scr = tft.ST7735(spi, 128, 160, dc=Pin(15, Pin.OUT), reset=Pin(13,Pin.OUT), cs=Pin(2, Pin.OUT), rotation=3)
scr.initr()
Tmr = Timer(0)
Render = Timer(1)
bgColor = tft.color565(0x96,0x24,0x24)
updated = False
gameOver = False
maxRow = const(6)
maxCol = const(8)
maxBomb = const(7)
table = [
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]
]
plate = [
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]
]
posX = 0
posY = 0
markCounter = 0
#################################################################
###### sub modules ##############################################
#################################################################
def splash():
scr.fill(bgColor)
scr.text(font,"mine", 20, 42, tft.YELLOW, bgColor)
for i in range(200):
color = tft.color565(55+i,55+i,55+i)
scr.text(font,"Sweep", 56, 60, color, bgColor)
time.sleep_ms(10)
time.sleep_ms(2000)
def randomTable():
global table,plate,markCounter
table = [
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]
]
plate = [
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]
]
counter = 0
markCounter=0
while (counter < maxBomb):
x = random.randint(1,maxCol)-1
y = random.randint(1,maxRow)-1
if (table[y][x] == 0):
# print("Bomb no.{} at ({},{}).".format(counter+1,x,y))
table[y][x] = 9
counter+=1
## fill the number
for row in range(maxRow):
for col in range(maxCol):
sum = 0
if (table[row][col] != 9):
if (row == 0): # first row
if col == 0: # first col
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
elif col == maxCol-1: # last col
if (table[row][col-1]==9): # left
sum += 1
if (table[row+1][col-1]==9): # bottom left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
else: # คอลัมน์อื่น ๆ
if (table[row][col-1]==9): # left
sum += 1
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col-1]==9): # bottom left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
elif (row == maxRow-1): # last row
if col == 0: # คอลัมน์แรก
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col+1]==9): # right
sum += 1
elif col == maxCol-1: # last col
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row][col-1]==9): # left
sum += 1
else: # other cols
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col-1]==9): # left
sum += 1
if (table[row][col+1]==9): # right
sum += 1
else:
if col == 0: # first col
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
elif col == maxCol-1: # last col
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row][col-1]==9): # left
sum += 1
if (table[row+1][col-1]==9): # bottom left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
else: # คอลัมน์อื่น ๆ
if (table[row-1][col-1]==9): # top left
sum += 1
if (table[row-1][col]==9): # top
sum += 1
if (table[row-1][col+1]==9): # top right
sum += 1
if (table[row][col-1]==9): # left
sum += 1
if (table[row][col+1]==9): # right
sum += 1
if (table[row+1][col-1]==9): # bottom left
sum += 1
if (table[row+1][col]==9): # bottom
sum += 1
if (table[row+1][col+1]==9): # bottom right
sum += 1
table[row][col] = sum
def cbInput(x):
global updated, posX, posY, table, plate, gameOver, markCounter
#######################################################
##### Input
#######################################################
if (swM2.value() == 0):
randomTable()
updated = True
#######################################################
##### Input : move to the left
#######################################################
if keL.value() == 0:
#updated = True
if (posX > 0):
cursor(False)
posX -= 1
cursor()
#######################################################
##### Input : move to the right
#######################################################
if keR.value() == 0:
#updated = True
if (posX < maxCol-1):
cursor(False)
posX += 1
cursor()
#######################################################
##### Input : move to top
#######################################################
if keU.value() == 0:
#updated = True
if (posY > 0):
cursor(False)
posY -= 1
cursor()
#######################################################
##### Input : move to bottom
#######################################################
if keD.value() == 0:
#updated = True
if (posY < maxRow-1):
cursor(False)
posY += 1
cursor()
#######################################################
##### Input : choose
#######################################################
if swA.value() == 0:
if (plate[posY][posX] == 0):
if (table[posY][posX] == 9):
gameOver = True
plate[posY][posX] = 1
updated = True
#######################################################
##### Input : maybe bomb
#######################################################
if swB.value() == 0:
if (plate[posY][posX] == 0):
if (markCounter < maxBomb): # less than the bomb number
plate[posY][posX] = 2
markCounter += 1
updated = True
elif (plate[posY][posX] == 2):
plate[posY][posX] = 0
markCounter -= 1
updated = True
def cbRender(x):
global updated
#######################################################
##### screen update
#######################################################
if (updated):
draw()
updated = False
def draw():
w = 20
h = 20
for row in range(6):
y = row*h+4+2
for col in range(8):
x = col*w+2
if plate[row][col]:
if (plate[row][col] == 1):
if (table[row][col]== 9):
scr.fill_rect(x,y,w-4,h-4, bgColor)
scr.text(font,"*",x,y,tft.YELLOW,bgColor)
else:
scr.fill_rect(x,y,w-4,h-4, tft.BLUE)
if (table[row][col] > 0):
scr.text(font,"{}".format(table[row][col]),x,y,tft.WHITE,tft.BLUE)
else:
scr.fill_rect(x,y,w-4,h-4, tft.GRAY)
scr.text(font,"!",x,y,tft.BLACK,tft.GRAY)
else:
scr.fill_rect(x,y,w-4,h-4, tft.GRAY)
def cursor(marked=True):
w = 20
h = 20
if marked:
scr.rect(posX*w,posY*h+4,w,h,tft.WHITE)
else:
scr.rect(posX*w,posY*h+4,w,h,tft.BLACK)
#################################################################
###### main program #############################################
#################################################################
#splash()
randomTable()
scr.fill(tft.BLACK)
draw()
cursor()
Tmr.init( period=150, mode=Timer.PERIODIC, callback=cbInput)
Render.init( period=33, mode=Timer.PERIODIC, callback=cbRender)
while (swM1.value() and (gameOver==False)):
pass
Tmr.deinit()
Render.deinit()
if (gameOver):
draw()
score = 0
for i in range(maxRow):
for j in range(maxCol):
if ((plate[i][j] == 2) and (table[i][j] == 9)):
score += 1
scr.fill(tft.BLACK)
scr.text(font,"Score={}".format(score),8,8,tft.WHITE,tft.BLACK)
spi.deinit()
Conclusion
From this article, you will find that Simple MineSweeper still needs to improve one important task. If the player selects and hits an empty area or keeps the value 0, the game must open all adjacent empty areas to be visible and collect statistics for playing. As for the main work of this example, it will make it easy for those who lead to further studies to improve. Finally, we hope that the example of this article was helpful and gave some ideas to those who are interested in developing simple and easy-to-make games on their own. Have fun programming.
(C) 2020-2022, By Jarut Busarathid and Danai Jedsadathitikul
Updated 2022-01-20