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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:38:16