驴友花雕 发表于 2025-9-23 19:19:50

【花雕动手做】基于Kitronik可编程开发板之扫地雷游戏



Kitronik ARCADE 是一款由英国教育科技公司 Kitronik 精心打造的可编程游戏机开发板,专为编程教学与创客实践而设计。该设备原生支持微软的 MakeCode Arcade 平台,用户可通过图形化或 JavaScript 编程方式,轻松创建、下载并运行复古风格的街机游戏。

它集成了彩色 LCD 显示屏、方向控制键、功能按键、蜂鸣器和震动马达等交互组件,提供完整的游戏输入输出体验。无论是初学者进行编程启蒙,还是创客群体开发交互式作品,Kitronik ARCADE 都能作为理想的硬件载体,助力创意实现。

凭借其开源友好、易于上手、兼容性强等特点,该开发板广泛应用于中小学编程课程、创客工作坊、游戏开发教学以及个人项目原型设计,深受教育者与技术爱好者的喜爱。



驴友花雕 发表于 2025-9-23 19:22:50

【花雕动手做】基于Kitronik可编程开发板之扫地雷游戏

作为学习、练习与尝试,这里创建一个扫地雷的小游戏。
打开网页版:https://arcade.makecode.com/,设置项目名称:扫地雷

MicroPython实验代码

@namespace
class SpriteKind:
    Collison = SpriteKind.create()
    Tile = SpriteKind.create()
    secret = SpriteKind.create()

def on_overlap_tile(sprite, location):
    sprite.destroy()
scene.on_overlap_tile(SpriteKind.Tile,
    assets.tile("""
      tile16
      """),
    on_overlap_tile)

def flood_reveal(num: number, num2: number):
    global number_of_gophers_but_here
    if not (tiles.tile_is_wall(tiles.get_tile_location(num, num2))):
      if not (tiles.tile_at_location_equals(tiles.get_tile_location(num, num2),
            assets.tile("""
                tile
                """))):
            return
      else:
            tiles.place_on_tile(recursive_target, tiles.get_tile_location(num, num2))
            number_of_gophers_but_here = count_gophers_where_i_am(recursive_target)
            tiles.set_tile_at(tiles.get_tile_location(num, num2),
                tile_Numbers)
            if 0 < number_of_gophers_but_here:
                return
            else:
                flood_reveal(num - 1, num2 - 1)
                flood_reveal(num - 1, num2 - 0)
                flood_reveal(num - 0, num2 - 1)
                flood_reveal(num + 1, num2 - 0)
                flood_reveal(num + 1, num2 + 1)
                flood_reveal(num + 0, num2 + 1)
                flood_reveal(num - 1, num2 + 1)
                flood_reveal(num + 1, num2 - 1)
def game_over():
    currentTile.destroy()
    for value in sprites.all_of_kind(SpriteKind.Tile):
      value.destroy()
      pause(10)
    game.over(False)

def on_a_pressed():
    global temp_number
    if target.overlaps_with(currentTile):
      if tiles.tile_at_location_equals(tiles.location_of_sprite(currentTile),
            assets.tile("""
                tile2
                """)):
            game_over()
      temp_number = count_gophers_where_i_am(currentTile)
      if 0 < temp_number:
            tiles.set_tile_at(tiles.location_of_sprite(currentTile),
                tile_Numbers)
      else:
            flood_reveal(tiles.location_xy(tiles.location_of_sprite(currentTile), tiles.XY.COLUMN),
                tiles.location_xy(tiles.location_of_sprite(currentTile), tiles.XY.ROW))
      currentTile.destroy()
    if len(sprites.all_of_kind(SpriteKind.Tile)) <= number_of_gophers:
      game.over(True)
controller.A.on_event(ControllerButtonEvent.PRESSED, on_a_pressed)

def on_overlap_tile2(sprite2, location2):
    sprite2.destroy()
scene.on_overlap_tile(SpriteKind.Tile,
    assets.tile("""
      tile17
      """),
    on_overlap_tile2)

def on_overlap_tile3(sprite3, location3):
    sprite3.destroy()
scene.on_overlap_tile(SpriteKind.Tile,
    assets.tile("""
      tile19
      """),
    on_overlap_tile3)

def on_overlap_tile4(sprite4, location4):
    sprite4.destroy()
scene.on_overlap_tile(SpriteKind.Tile,
    assets.tile("""
      tile18
      """),
    on_overlap_tile4)

def on_b_pressed():
    if not (sprites.read_data_boolean(currentTile, "revealed")):
      if currentTile.image.equals(unseenTileImage):
            currentTile.set_image(seenTileImage)
      else:
            currentTile.set_image(unseenTileImage)
controller.B.on_event(ControllerButtonEvent.PRESSED, on_b_pressed)

def on_overlap_tile5(sprite5, location5):
    sprite5.destroy()
scene.on_overlap_tile(SpriteKind.Tile,
    assets.tile("""
      tile14
      """),
    on_overlap_tile5)

def on_overlap_tile6(sprite6, location6):
    sprite6.destroy()
scene.on_overlap_tile(SpriteKind.Tile,
    assets.tile("""
      tile15
      """),
    on_overlap_tile6)

def on_overlap_tile7(sprite7, location7):
    sprite7.destroy()
scene.on_overlap_tile(SpriteKind.Tile,
    assets.tile("""
      tile12
      """),
    on_overlap_tile7)

def make_cover_tiles():
    global tile
    for value2 in tiles.get_tiles_by_type(assets.tile("""
      tile
      """)):
      tile = sprites.create(img("""
                9 1 1 1 1 1 1 d
                1 b b b b b b c
                1 b b b b b b c
                1 b b b b b b c
                1 b b b b b b c
                1 b b b b b b c
                1 b b b b b b c
                d c c c c c c f
                """),
            SpriteKind.Tile)
      tile.set_flag(SpriteFlag.INVISIBLE, False)
      tiles.place_on_tile(tile, value2)
      sprites.set_data_boolean(tile, "revealed", False)
def count_gophers_where_i_am(mySprite: Sprite):
    global currentTileLocation, number_of_gophers_next_to_me
    currentTileLocation = tiles.location_of_sprite(mySprite)
    number_of_gophers_next_to_me = 0
    if tiles.tile_is(tiles.location_in_direction(tiles.location_in_direction(currentTileLocation, CollisionDirection.LEFT),
            CollisionDirection.TOP),
      assets.tile("""
            tile2
            """)):
      number_of_gophers_next_to_me += 1
    if tiles.tile_is(tiles.location_in_direction(currentTileLocation, CollisionDirection.TOP),
      assets.tile("""
            tile2
            """)):
      number_of_gophers_next_to_me += 1
    if tiles.tile_is(tiles.location_in_direction(tiles.location_in_direction(currentTileLocation, CollisionDirection.TOP),
            CollisionDirection.RIGHT),
      assets.tile("""
            tile2
            """)):
      number_of_gophers_next_to_me += 1
    if tiles.tile_is(tiles.location_in_direction(currentTileLocation, CollisionDirection.LEFT),
      assets.tile("""
            tile2
            """)):
      number_of_gophers_next_to_me += 1
    if tiles.tile_is(tiles.location_in_direction(currentTileLocation, CollisionDirection.RIGHT),
      assets.tile("""
            tile2
            """)):
      number_of_gophers_next_to_me += 1
    if tiles.tile_is(tiles.location_in_direction(tiles.location_in_direction(currentTileLocation, CollisionDirection.BOTTOM),
            CollisionDirection.LEFT),
      assets.tile("""
            tile2
            """)):
      number_of_gophers_next_to_me += 1
    if tiles.tile_is(tiles.location_in_direction(currentTileLocation, CollisionDirection.BOTTOM),
      assets.tile("""
            tile2
            """)):
      number_of_gophers_next_to_me += 1
    if tiles.tile_is(tiles.location_in_direction(tiles.location_in_direction(currentTileLocation, CollisionDirection.BOTTOM),
            CollisionDirection.RIGHT),
      assets.tile("""
            tile2
            """)):
      number_of_gophers_next_to_me += 1
    return number_of_gophers_next_to_me

def on_on_overlap(sprite8, otherSprite):
    global currentTile
    currentTile = otherSprite
sprites.on_overlap(SpriteKind.Collison, SpriteKind.Tile, on_on_overlap)

def on_overlap_tile8(sprite9, location8):
    sprite9.destroy()
scene.on_overlap_tile(SpriteKind.Tile,
    assets.tile("""
      tile0
      """),
    on_overlap_tile8)

def on_overlap_tile9(sprite10, location9):
    sprite10.destroy()
scene.on_overlap_tile(SpriteKind.Tile,
    assets.tile("""
      tile13
      """),
    on_overlap_tile9)

def place_gophers():
    global allOpenTiles, random_tile_index
    allOpenTiles = tiles.get_tiles_by_type(assets.tile("""
      tile
      """))
    index = 0
    while index <= number_of_gophers - 1:
      random_tile_index = randint(0, len(allOpenTiles) - 1)
      tiles.set_tile_at(allOpenTiles.remove_at(random_tile_index),
            assets.tile("""
                tile2
                """))
      index += 1
random_tile_index = 0
allOpenTiles: List = []
number_of_gophers_next_to_me = 0
currentTileLocation: tiles.Location = None
tile: Sprite = None
temp_number = 0
currentTile: Sprite = None
number_of_gophers_but_here = 0
tile_Numbers: List = []
number_of_gophers = 0
seenTileImage: Image = None
unseenTileImage: Image = None
target: Sprite = None
recursive_target: Sprite = None
num_flags_placed = 0
tiles.set_small_tilemap(tilemap("""
    level1
    """))
recursive_target = sprites.create(img("""
    3
    """), SpriteKind.secret)
recursive_target.set_flag(SpriteFlag.INVISIBLE, True)
cursor = sprites.create(img("""
      . . f . . . . .
      . f 1 f . . . .
      . f 1 f f f . .
      . f 1 b 1 b f .
      . f 1 b 1 b 1 f
      f 1 1 1 1 1 1 f
      f 1 1 1 1 1 1 f
      . f f f f f f .
      """),
    SpriteKind.player)
cursor.z = 10000000000
target = sprites.create(img("""
    2
    """), SpriteKind.Collison)
target.set_flag(SpriteFlag.INVISIBLE, True)
controller.move_sprite(cursor, 50, 50)
unseenTileImage = img("""
    9 1 1 1 1 1 1 d
    1 b b b b b b c
    1 b b b b b b c
    1 b b b b b b c
    1 b b b b b b c
    1 b b b b b b c
    1 b b b b b b c
    d c c c c c c f
    """)
seenTileImage = img("""
    9 1 1 1 1 1 1 d
    1 b b b b 2 2 c
    1 b e e e e b 2
    1 b f e f e 2 c
    1 e e e e e b c
    1 b e e e e 2 c
    1 b b b b b b c
    d c c c c c c f
    """)
number_of_gophers = 30
tile_Numbers = [assets.tile("""
      tile12
      """),
    assets.tile("""
      tile0
      """),
    assets.tile("""
      tile13
      """),
    assets.tile("""
      tile14
      """),
    assets.tile("""
      tile15
      """),
    assets.tile("""
      tile16
      """),
    assets.tile("""
      tile17
      """),
    assets.tile("""
      tile18
      """),
    assets.tile("""
      tile19
      """)]
make_cover_tiles()
place_gophers()

def on_on_update():
    target.set_position(Math.floor(cursor.left) + 3, Math.floor(cursor.top) + 1)
game.on_update(on_on_update)


驴友花雕 发表于 2025-9-23 19:26:44

【花雕动手做】基于Kitronik可编程开发板之扫地雷游戏

这是一个使用MakeCode Arcade开发的扫雷游戏代码。

游戏核心机制

1. 初始化设置
python
# 创建自定义精灵类型

class SpriteKind:

    Collison = SpriteKind.create()# 碰撞检测

    Tile = SpriteKind.create()      # 地砖覆盖层

    secret = SpriteKind.create()    # 秘密精灵(用于递归计算)

2. 游戏组件
地图:使用tilemap创建游戏网格
光标:玩家控制的可移动光标
目标标记:用于检测当前选中的格子
地砖覆盖:覆盖在每个格子上的可点击层

3. 核心函数解析
地雷放置函数 place_gophers()

python
def place_gophers():

    global allOpenTiles, random_tile_index

    allOpenTiles = tiles.get_tiles_by_type(assets.tile("tile"))# 获取所有可放置位置

    # 随机放置指定数量的地雷

    for i in range(number_of_gophers):

      random_tile_index = randint(0, len(allOpenTiles) - 1)

      tiles.set_tile_at(allOpenTiles.remove_at(random_tile_index), assets.tile("tile2"))
地雷计数函数 count_gophers_where_i_am()

python
def count_gophers_where_i_me(mySprite: Sprite):

    # 检查当前格子周围8个方向的地雷数量

    number_of_gophers_next_to_me = 0

    # 检查左上、上、右上、左、右、左下、下、右下8个位置

    return number_of_gophers_next_to_me
洪水揭示算法 flood_reveal()

python
def flood_reveal(num: number, num2: number):

    # 递归揭示空白区域(类似标准扫雷的连片空白揭示)

    if 当前格子不是墙且未被揭示:

      if 周围地雷数 > 0:

            显示数字

            return

      else:

            # 递归检查周围8个方向

            flood_reveal(num-1, num2-1)# 左上

            flood_reveal(num-1, num2)    # 上

            flood_reveal(num, num2-1)    # 左

            # ... 其他方向

4. 玩家控制
A键按下 - 揭示格子

python
def on_a_pressed():

    if 点击到地雷: game_over()# 游戏结束

    if 周围有地雷: 显示数字

    else: flood_reveal()# 递归揭示空白区域
B键按下 - 标记/取消标记

python
def on_b_pressed():

    # 切换地砖图像(标记/取消标记)

    if currentTile.image.equals(unseenTileImage):

      currentTile.set_image(seenTileImage)

    else:

      currentTile.set_image(unseenTileImage)

5. 游戏结束条件
失败:点击到地雷格子(tile2)
胜利:所有非地雷格子都被揭示(剩余地砖数 ≤ 地雷数)

6. 视觉表现
未揭示格子:灰色覆盖层
已揭示格子:显示数字或空白
数字显示:使用不同的tile图像表示1-8的数字

游戏特点
经典扫雷玩法:数字表示周围地雷数量
递归揭示:空白区域自动连片揭示
标记功能:可标记疑似地雷位置
逐步揭示:动画效果展示游戏过程

这个实现完整地复现了经典Windows扫雷游戏的核心机制,包括地雷生成、数字计算、递归揭示和胜负判定等关键功能。

驴友花雕 发表于 2025-9-23 19:31:36

【花雕动手做】基于Kitronik可编程开发板之扫地雷游戏

图形编程参考实验程序



通过模拟器,调试与模拟运行



实验场景记录









驴友花雕 发表于 2025-9-23 19:37:47

【花雕动手做】基于Kitronik可编程开发板之扫地雷游戏


页: [1]
查看完整版本: 【花雕动手做】基于Kitronik可编程开发板之扫地雷游戏