如何在Rust中用命名常量初始化const类型匹配二维数组
Rust编译期初始化宝可梦属性匹配表的方案
你可以通过const函数结合命名常量/枚举的方式,实现无魔法数字的编译期数组初始化,完全满足你的需求:
方案一:使用枚举(更符合Rust风格)
先定义带固定内存布局的枚举,变体对应数组索引,再用const函数初始化数组:
// 用#[repr(usize)]确保枚举变体从0开始按顺序对应usize值 #[repr(usize)] #[derive(Debug, Clone, Copy)] enum PokemonType { Normal, Grass, Fire, Water, Electric, Fighting, Flying, Rock, } const fn init_matchup_table() -> [[f32; 8]; 8] { // 先初始化全1的基础数组 let mut table = [[1.0; 8]; 8]; // 设置属性克制关系(攻击方 -> 防御方 = 倍数) table[PokemonType::Fire as usize][PokemonType::Grass as usize] = 2.0; table[PokemonType::Grass as usize][PokemonType::Water as usize] = 2.0; table[PokemonType::Water as usize][PokemonType::Fire as usize] = 2.0; table[PokemonType::Electric as usize][PokemonType::Water as usize] = 2.0; table[PokemonType::Electric as usize][PokemonType::Flying as usize] = 2.0; table[PokemonType::Fighting as usize][PokemonType::Normal as usize] = 2.0; table[PokemonType::Fighting as usize][PokemonType::Rock as usize] = 2.0; table[PokemonType::Flying as usize][PokemonType::Grass as usize] = 2.0; table[PokemonType::Rock as usize][PokemonType::Fire as usize] = 2.0; table[PokemonType::Rock as usize][PokemonType::Flying as usize] = 2.0; // 设置属性弱效关系 table[PokemonType::Grass as usize][PokemonType::Fire as usize] = 0.5; table[PokemonType::Water as usize][PokemonType::Grass as usize] = 0.5; table[PokemonType::Fire as usize][PokemonType::Water as usize] = 0.5; table[PokemonType::Water as usize][PokemonType::Electric as usize] = 0.5; table[PokemonType::Flying as usize][PokemonType::Electric as usize] = 0.5; table[PokemonType::Normal as usize][PokemonType::Fighting as usize] = 0.5; table[PokemonType::Rock as usize][PokemonType::Fighting as usize] = 0.5; table[PokemonType::Grass as usize][PokemonType::Flying as usize] = 0.5; table[PokemonType::Fire as usize][PokemonType::Rock as usize] = 0.5; table[PokemonType::Flying as usize][PokemonType::Rock as usize] = 0.5; table } // 编译期初始化的常量数组,存于只读内存 const MATCHUP_TABLE: [[f32; 8]; 8] = init_matchup_table();
方案二:使用命名常量(贴近你的原始写法)
如果更习惯用独立的命名常量,只需将常量类型改为usize,再用const函数初始化:
const NORMAL: usize = 0; const GRASS: usize = 1; const FIRE: usize = 2; const WATER: usize = 3; const ELECTRIC: usize = 4; const FIGHTING: usize = 5; const FLYING: usize = 6; const ROCK: usize = 7; const fn create_matchup_table() -> [[f32; 8]; 8] { let mut table = [[1.0; 8]; 8]; // 克制关系 table[FIRE][GRASS] = 2.0; table[GRASS][WATER] = 2.0; table[WATER][FIRE] = 2.0; table[ELECTRIC][WATER] = 2.0; table[ELECTRIC][FLYING] = 2.0; table[FIGHTING][NORMAL] = 2.0; table[FIGHTING][ROCK] = 2.0; table[FLYING][GRASS] = 2.0; table[ROCK][FIRE] = 2.0; table[ROCK][FLYING] = 2.0; // 弱效关系 table[GRASS][FIRE] = 0.5; table[WATER][GRASS] = 0.5; table[FIRE][WATER] = 0.5; table[WATER][ELECTRIC] = 0.5; table[FLYING][ELECTRIC] = 0.5; table[NORMAL][FIGHTING] = 0.5; table[ROCK][FIGHTING] = 0.5; table[GRASS][FLYING] = 0.5; table[FIRE][ROCK] = 0.5; table[FLYING][ROCK] = 0.5; table } const MATCHUP_TABLE: [[f32; 8]; 8] = create_matchup_table();
核心原理
Rust的const fn支持编译期执行逻辑,包括数组元素的修改。我们先初始化全1的数组,再通过命名常量/枚举变体的索引精准修改属性关系,既避免了魔法数字的可读性问题,又保证数组在编译期完成初始化,最终存放在只读内存中,完全符合你的要求。
内容的提问来源于stack exchange,提问作者user973223
相关产品推荐
相关产品推荐

