2025-5-1 18:59:19 [显示全部楼层]
375浏览
查看: 375|回复: 0

基于掌控板的——2048——小游戏

[复制链接]
本帖最后由 mmm530531 于 2025-5-1 19:06 编辑

一、项目简介
2048 是一款广受欢迎的数字合并游戏,通过不断合并相同数字来获得更大的数字。本次项目使用掌控板来实现这一经典游戏,结合掌控板的硬件特性,为游戏带来独特的交互体验。
二、硬件准备
1. 掌控板:作为游戏运行的核心硬件,它集成了丰富的传感器和接口,方便实现游戏的各种功能。
2. USB 数据线:用于连接掌控板和电脑,以便烧录代码。  

三、软件准备
1. mpython:选择一款适合的编程环境,用于编写和烧录游戏代码。  



四、代码实现
1. 游戏初始化:  
from mpython import *
import random

# 初始化 OLED 对象
oled = OLED()

# 初始化游戏板
board = [[0] * 4 for _ in range(4)]

# 定义颜色映射
color_map = {
    2: (255, 255, 255),
    4: (255, 255, 0),
    8: (255, 165, 0),
    16: (255, 0, 0),
    32: (0, 255, 0),
    64: (0, 0, 255),
    128: (255, 255, 128),
    256: (255, 128, 255),
    512: (128, 255, 255),
    1024: (255, 128, 0),
    2048: (0, 255, 255)
}

# 初始化分数和最高分
score = 0
high_score = 0

2. 添加新数字:在空白位置随机添加数字 2 或 4。
     def add_new_tile():
    """在空白位置添加新的数字 2 或 4"""
    empty_cells = []
    for i in range(4):
        for j in range(4):
            if board[j] == 0:
                empty_cells.append((i, j))
    if empty_cells:
        row, col = random.choice(empty_cells)
        board[row][col] = 2 if random.random() < 0.9 else 4
     3. 绘制游戏板:在 OLED 屏幕上绘制游戏板和数字,并显示当前得分和最高得分。
def draw_board():
    """在 OLED 上绘制游戏板"""
    oled.fill(0)
    draw_grid()
    # 绘制游戏区数字
    for i in range(4):
        for j in range(4):
            if board[j] != 0:
                num_str = str(board[j])
                x = j * 24 + (24 - font_width * len(num_str)) // 2
                y = i * 16 + (16 - font_width) // 2
                color = color_map.get(board[j], (255, 255, 255))
                # 假设使用 RGB565 颜色编码转换
                r, g, b = color
                rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)
                oled.text(num_str, x, y, rgb565)
    # 绘制右侧得分区域
    oled.text("Score:", 100, 10)
    oled.text("%d" % score, 100, 20)
    oled.text("High Score:", 100, 35)
    oled.text("%d" % high_score, 100, 45)
    oled.show()
     4. 移动和合并数字:根据不同方向移动游戏板上的数字,并合并相同数字。      
     def merge_left():
    """向左合并数字"""
    global score
    for row in board:
        new_row = [num for num in row if num != 0]
        i = 0
        while i < len(new_row) - 1:
            if new_row == new_row[i + 1]:
                # 更新分数
                score += new_row * 2
                new_row *= 2
                del new_row[i + 1]
            i += 1
        new_row.extend([0] * (4 - len(new_row)))
        for j in range(4):
            row[j] = new_row[j]


def rotate_board():
    """顺时针旋转游戏板"""
    global board
    board = list(map(list, zip(*board[::-1])))


def move(direction):
    """根据方向移动和合并数字"""
    if direction == 'left':
        merge_left()
    elif direction == 'up':
        rotate_board()
        merge_left()
        rotate_board()
        rotate_board()
        rotate_board()
    elif direction == 'right':
        rotate_board()
        rotate_board()
        merge_left()
        rotate_board()
        rotate_board()
    elif direction == 'down':
        rotate_board()
        rotate_board()
        rotate_board()
        merge_left()
        rotate_board()
     5. 检查游戏是否结束:判断游戏是否结束,当没有空白位置且相邻数字不能合并时,游戏结束。  
def is_game_over():
    """检查游戏是否结束"""
    for i in range(4):
        for j in range(4):
            if board[j] == 0:
                return False
            if i > 0 and board[j] == board[i - 1][j]:
                return False
            if j > 0 and board[j] == board[j - 1]:
                return False
    return True
     6. 重置游戏:当游戏结束后,按下特定按键可重置游戏。  
def reset_game():
    """重置游戏状态"""
    global board, score
    board = [[0] * 4 for _ in range(4)]
    score = 0
    add_new_tile()
    add_new_tile()
    draw_board()
     7. 游戏主循环:监听按键和加速度计事件,实现游戏的交互和逻辑。  
# 初始化游戏
add_new_tile()
add_new_tile()
draw_board()

while True:
    if button_a.value() == 0:
        move('left')
        add_new_tile()
        draw_board()
    elif button_b.value() == 0:
        move('right')
        add_new_tile()
        draw_board()
    elif accelerometer.get_x() > 0.5:
        move('down')
        add_new_tile()
        draw_board()
    elif accelerometer.get_x() < -0.5:
        move('up')
        add_new_tile()
        draw_board()
    if is_game_over():
        # 检查是否打破最高分
        if score > high_score:
            high_score = score
        oled.fill(0)
        oled.text("Game Over!", 5, 5)
        oled.text("Final Score:", 5, 20)
        oled.text(str(score), 5 + len("Final Score:") * font_width, 20)
        oled.text("High Score:", 5, 35)
        oled.text(str(high_score), 5 + len("High Score:") * font_width, 35)
        oled.show()
        # 等待按键按下以重置游戏
        while True:
            if button_a.value() == 0 or button_b.value() == 0:
                reset_game()
                break


五、制作过程中的问题与解决
在制作过程中,遇到了一些问题。比如在 OLED 显示时,出现了 TypeError 和 NameError 等错误。 1. TypeError: can not convert tuple to int:这是因为在 OLED 显示颜色时,传入了元组形式的颜色值,而 oled.text 函数可能只接受单个整数值。通过将颜色元组转换为 RGB565 颜色编码的单个整数值解决了该问题。 2. NameError:在游戏结束界面部分,由于未正确定义或引用变量(如 font_width)导致报错。通过将 font_width 定义为全局变量,确保了在需要使用的地方都能正确访问。

六、总结
通过这次在掌控板上制作 2048 小游戏,深入了解了掌控板的编程和硬件特性。在解决各种问题的过程中,也提高了自己的编程能力和调试技巧。希望我的分享能对大家有所帮助,也期待大家在这个基础上进行更多的创新和改进。 希望以上内容对你有所帮助,祝你在 dfrobot 创客社区的分享顺利!

基于掌控板的——2048——小游戏图1基于掌控板的——2048——小游戏图2
ThuMay-202505019879..jpg

mpython_2048.py

4.75 KB, 下载次数: 63

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
关于楼主
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail