Kitronik ARCADE 是一款由英国教育科技公司 Kitronik 精心打造的可编程游戏机开发板,专为编程教学与创客实践而设计。该设备原生支持微软的 MakeCode Arcade 平台,用户可通过图形化或 JavaScript 编程方式,轻松创建、下载并运行复古风格的街机游戏。
它集成了彩色 LCD 显示屏、方向控制键、功能按键、蜂鸣器和震动马达等交互组件,提供完整的游戏输入输出体验。无论是初学者进行编程启蒙,还是创客群体开发交互式作品,Kitronik ARCADE 都能作为理想的硬件载体,助力创意实现。
凭借其开源友好、易于上手、兼容性强等特点,该开发板广泛应用于中小学编程课程、创客工作坊、游戏开发教学以及个人项目原型设计,深受教育者与技术爱好者的喜爱。

作为学习、练习与尝试,这里创建一个扫地雷的小游戏。
打开网页版: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[number_of_gophers_but_here])
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[temp_number])
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[tiles.Location] = []
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[Image] = []
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)
这是一个使用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扫雷游戏的核心机制,包括地雷生成、数字计算、递归揭示和胜负判定等关键功能。
图形编程参考实验程序

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

实验场景记录




评论