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

遍历Dictionary<int, int[]>得到非预期结果的C#技术问询

桌游主持辅助应用权重计算模块问题修复

问题描述

使用C#和Visual Studio开发桌游主持辅助应用时,权重计算模块出现异常:点击按钮后本应生成单一宝藏结果,实际却得到3-5组结果的累加值。按钮仅绑定一次点击事件,预期逻辑为掷出d100后,匹配第一个满足d100 ≤ 字典键值的条目并执行对应骰子滚动,但实际代码遍历了所有符合条件的键并累加结果。

相关代码

private void challenge1_Click(object sender, EventArgs e)
{
    Dictionary<int, int[]> weights = new Dictionary<int, int[]>() {
        { 30, new int[]{5,0,0,0,0}},
        { 60, new int[]{0,4,0,0,0}},
        { 70, new int[]{0,0,3,0,0}},
        { 95, new int[]{0,0,0,3,0}},
        { 100,new int[]{0,0,0,0,1}}
    };
    Random one = new Random();
    Random two = new Random();
    int d100 = RollDice(100, one);
    int[] results = IndividualTreasure(weights, d100);
    TreasureResults(results);
}

private int[] IndividualTreasure(Dictionary<int, int[]> weights, int d100)
{
    int cp = 0, sp = 0, gp = 0, ep = 0, pp = 0;
    Random num = new Random();
    foreach (KeyValuePair<int, int[]> entry in weights)
    {
        if (d100 <= entry.Key)
        {
            for (int i = 0; i < entry.Value.Length; i++)
            {
                if (entry.Value[i] > 0)
                {
                    switch (i)
                    {
                        case 0:
                            for (int j = 0; j < entry.Value[i]; j++)
                            {
                                int randNum = RollDice(6, num);
                                cp += randNum;
                            }
                            break;
                        case 1:
                            for (int j = 0; j < entry.Value[i]; j++)
                            {
                                int randNum = RollDice(6, num);
                                sp += randNum;
                            }
                            break;
                        case 2:
                            for (int j = 0; j < entry.Value[i]; j++)
                            {
                                int randNum = RollDice(6, num);
                                gp += randNum;
                            }
                            break;
                        case 3:
                            for (int j = 0; j < entry.Value[i]; j++)
                            {
                                int randNum = RollDice(6, num);
                                ep += randNum;
                            }
                            break;
                        case 4:
                            for (int j = 0; j < entry.Value[i]; j++)
                            {
                                int randNum = RollDice(6, num);
                                pp += randNum;
                            }
                            break;
                    }
                }
            }
        }
    }
    int[] result = new int[5] { cp, sp, gp, ep, pp };
    return result;
}

private void TreasureResults(int[] results)
{
    int cp = results[0];
    int sp = results[1];
    int gp = results[2];
    int ep = results[3];
    int pp = results[4];
    lbl_cp_amount.Text = cp.ToString();
    lbl_sp_amount.Text = sp.ToString();
    lbl_gp_amount.Text = gp.ToString();
    lbl_ep_amount.Text = ep.ToString();
    lbl_pp_amount.Text = pp.ToString();
}

问题根源

  1. 字典遍历逻辑错误:Dictionary默认不保证排序,当前代码会遍历所有满足d100 ≤ entry.Key的条目并累加结果。例如掷出d100=20时,30、60、70、95、100这些键都符合条件,导致所有对应宝藏类型的骰子结果被累加,出现多组结果。
  2. Random实例重复创建:短时间内多次创建Random实例(one、two、num)会因系统时钟种子相同,导致生成的随机数重复或不符合预期。

修复方案

修复后的代码

// 类级别全局Random实例,确保随机性正常
private Random _random = new Random();

private void challenge1_Click(object sender, EventArgs e)
{
    Dictionary<int, int[]> weights = new Dictionary<int, int[]>() {
        { 30, new int[]{5,0,0,0,0}},
        { 60, new int[]{0,4,0,0,0}},
        { 70, new int[]{0,0,3,0,0}},
        { 95, new int[]{0,0,0,3,0}},
        { 100,new int[]{0,0,0,0,1}}
    };
    int d100 = RollDice(100, _random);
    int[] results = IndividualTreasure(weights, d100);
    TreasureResults(results);
}

private int[] IndividualTreasure(Dictionary<int, int[]> weights, int d100)
{
    int cp = 0, sp = 0, gp = 0, ep = 0, pp = 0;
    // 将字典按键升序排序,确保从最低阈值开始匹配
    var sortedWeights = weights.OrderBy(kv => kv.Key);
    
    foreach (KeyValuePair<int, int[]> entry in sortedWeights)
    {
        if (d100 <= entry.Key)
        {
            for (int i = 0; i < entry.Value.Length; i++)
            {
                if (entry.Value[i] > 0)
                {
                    switch (i)
                    {
                        case 0:
                            for (int j = 0; j < entry.Value[i]; j++)
                                cp += RollDice(6, _random);
                            break;
                        case 1:
                            for (int j = 0; j < entry.Value[i]; j++)
                                sp += RollDice(6, _random);
                            break;
                        case 2:
                            for (int j = 0; j < entry.Value[i]; j++)
                                gp += RollDice(6, _random);
                            break;
                        case 3:
                            for (int j = 0; j < entry.Value[i]; j++)
                                ep += RollDice(6, _random);
                            break;
                        case 4:
                            for (int j = 0; j < entry.Value[i]; j++)
                                pp += RollDice(6, _random);
                            break;
                    }
                }
            }
            // 找到匹配条目后立即退出循环,避免处理后续条目
            break;
        }
    }
    
    return new int[5] { cp, sp, gp, ep, pp };
}

private void TreasureResults(int[] results)
{
    lbl_cp_amount.Text = results[0].ToString();
    lbl_sp_amount.Text = results[1].ToString();
    lbl_gp_amount.Text = results[2].ToString();
    lbl_ep_amount.Text = results[3].ToString();
    lbl_pp_amount.Text = results[4].ToString();
}

关键修复点

  • 全局Random实例:避免短时间内重复创建Random导致的随机数重复问题,统一使用类级别实例生成所有随机数。
  • 排序+终止循环:将字典按键升序排序后,找到第一个满足条件的条目就执行break终止遍历,确保只生成一组宝藏结果,符合预期逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 09:20:21