You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android Room数据库中存储多关卡游戏数据?

最佳存储方案:规范化关系型数据库设计

针对你的马里奥关卡数据存储需求,拆分出两张关联表是Room数据库的最优解,完全解决数组不支持的问题,同时兼顾性能和扩展性:

表结构设计

1. 世界表(worlds)

存储世界的基础标识信息,结构极简:

字段名类型说明
world_idINT主键,对应世界编号(1-10)
world_nameTEXT可选,比如“世界1”这类名称

2. 关卡表(levels)

每个关卡作为单独的一行存储,通过world_id关联到对应的世界:

字段名类型说明
level_idINT自增主键(或用复合主键)
world_idINT外键,关联worlds表的world_id
level_numberINT关卡编号(1-23,每个世界内唯一)
enemy_countINT敌人数量
coin_countINT金币数量
checkpoint_countINT检查点数量

为什么这是最优解?

  1. 适配Room规则:所有字段都是基本数据类型,完全避开Room不支持数组的限制,不需要额外的序列化/反序列化操作。
  2. 扩展性极强:如果后续要给关卡加新属性(比如是否有BOSS、通关时间限制),直接给levels表加列即可,不用重构整个表结构。
  3. 查询灵活高效:可以单独查询某世界的所有关卡、某特定关卡的具体数据,不用像原方案那样读取整行数据再解析数组,查询效率大幅提升。
  4. 性能完全不用担心:10个世界×23个关卡=230条数据,单条数据仅3个整数,总内存占用不到1KB,Room处理这种量级的数据毫无压力,比存在内存里更稳妥(持久化存储,APP重启数据不丢失)。

代码示例(Kotlin)

World实体类

@Entity(tableName = "worlds")
data class World(
    @PrimaryKey val worldId: Int,
    val worldName: String? = null // 可选字段,不需要可以删掉
)

Level实体类

@Entity(
    tableName = "levels",
    foreignKeys = [ForeignKey(
        entity = World::class,
        parentColumns = ["worldId"],
        childColumns = ["worldId"],
        onDelete = ForeignKey.CASCADE
    )],
    indices = [Index(value = ["worldId", "levelNumber"], unique = true)] // 确保同一世界的关卡编号不重复
)
data class Level(
    @PrimaryKey(autoGenerate = true) val levelId: Long = 0,
    val worldId: Int,
    val levelNumber: Int,
    val enemyCount: Int,
    val coinCount: Int,
    val checkpointCount: Int
)

DAO接口

@Dao
interface GameDao {
    // 查询指定世界的所有关卡,按关卡号排序
    @Query("SELECT * FROM levels WHERE worldId = :worldId ORDER BY levelNumber ASC")
    suspend fun getLevelsByWorld(worldId: Int): List<Level>

    // 查询指定世界的指定关卡
    @Query("SELECT * FROM levels WHERE worldId = :worldId AND levelNumber = :levelNumber")
    suspend fun getLevel(worldId: Int, levelNumber: Int): Level?

    // 批量插入世界数据
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertWorlds(worlds: List<World>)

    // 批量插入关卡数据
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertLevels(levels: List<Level>)
}

额外优化:静态数据预填充

如果这些关卡数据是固定不变的静态数据,可以用Room的预填充数据库功能:

  1. 提前在本地生成包含所有数据的SQLite数据库文件
  2. 将文件放在assets/databases/目录下
  3. 在Room数据库类中配置createFromAsset(),App启动时Room会自动加载预填充数据,无需手动插入

内容的提问来源于stack exchange,提问作者Soil Milk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 02:17:32