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

Codewars骰子游戏Greed的C语言代码出现不稳定行为求助

Greed骰子游戏C语言代码问题

问题规则

Greed是一款使用5枚六面骰子的游戏,单次掷骰子得分规则如下(输入为包含5个骰子点数的数组):

  • 三个1(⚀)=1000分
  • 三个6(⚅)=600分
  • 三个5(⚄)=500分
  • 三个4(⚃)=400分
  • 三个3(⚂)=300分
  • 三个2(⚁)=200分
  • 单个1(⚀)=100分
  • 单个5(⚄)=50分

单个骰子只能被计数一次,例如某个5只能计入三元组(得500分)或单个(得50分),不能同时计入。

示例计分:

掷骰结果得分说明
5 1 3 4 1250: 50(单个5) + 2 * 100(两个1)
1 1 1 3 11100: 1000(三个1) + 100(剩余一个1)
2 4 4 5 4450: 400(三个4) + 50(单个5)

注意:不可修改输入数组,否则无法通过所有测试。

我的代码

int score(const int dice[5]) {
    int score = 0;
    int digits[6] = { 0 };
    for (int i = 0; i < 5; i++) {
        digits[dice[i]]++;
    }
    // Rules
    // 100 points for each 1 except when there is more than 2
    if (digits[1] < 3) {
        score += digits[1] * 100;    
    } else {
        score += (digits[1] % 3) * 100;
    }
    // 50 points for each 5
    if (digits[5] < 3) {
        score += digits[5] * 50;    
    } else {
        score += (digits[5] % 3) * 50;
    }
    // 1000 points for 3 1s
    for (int i = 1; i <= 6; i++) {
        int repeats = digits[i];
        if (repeats >= 3) {
            switch (i) {
              case 1:
                score += 1000;
                break;
              case 2:
                score += 200;
                break;
              case 3:
                score += 300;
                break;
              case 4:
                score += 400;
                break;
              case 5:
                score += 500;
                break;
              case 6:
                score += 600;
                break;
              default:
                break;
            }
        }
    }
    return score;
}

问题现象

本地运行所有测试用例均正常,但在Codewars平台上测试时而通过时而失败,怀疑存在机器/编译器相关的问题,恳请帮忙找出问题所在。


问题根源

代码中存在数组越界访问的未定义行为:

  • 定义的digits数组长度为6,索引范围是0~5,但骰子点数范围是1~6。当骰子出现点数6时,digits[6]会访问数组边界外的内存,这会导致不可预测的结果——有时刚好内存数据不影响计算,有时会破坏其他变量值,最终表现为测试时而通过时而失败。

修复方案

有两种可行的修复方式:

方式1:扩大数组长度

将digits数组长度改为7,让索引1~6都能被合法访问:

int score(const int dice[5]) {
    int score = 0;
    int digits[7] = { 0 }; // 长度改为7,索引0~6
    for (int i = 0; i < 5; i++) {
        digits[dice[i]]++;
    }
    // 后续逻辑保持不变
    if (digits[1] < 3) {
        score += digits[1] * 100;    
    } else {
        score += (digits[1] % 3) * 100;
    }
    if (digits[5] < 3) {
        score += digits[5] * 50;    
    } else {
        score += (digits[5] % 3) * 50;
    }
    for (int i = 1; i <= 6; i++) {
        int repeats = digits[i];
        if (repeats >= 3) {
            switch (i) {
              case 1:
                score += 1000;
                break;
              case 2:
                score += 200;
                break;
              case 3:
                score += 300;
                break;
              case 4:
                score += 400;
                break;
              case 5:
                score += 500;
                break;
              case 6:
                score += 600;
                break;
              default:
                break;
            }
        }
    }
    return score;
}

方式2:偏移骰子点数到合法索引

将骰子点数减1,映射到0~5的数组索引:

int score(const int dice[5]) {
    int score = 0;
    int digits[6] = { 0 };
    for (int i = 0; i < 5; i++) {
        digits[dice[i] - 1]++; // 点数减1,映射到0~5索引
    }
    // 调整后续逻辑的索引对应关系
    int count1 = digits[0]; // digits[0]对应点数1的数量
    if (count1 < 3) {
        score += count1 * 100;    
    } else {
        score += (count1 % 3) * 100;
    }
    int count5 = digits[4]; // digits[4]对应点数5的数量
    if (count5 < 3) {
        score += count5 * 50;    
    } else {
        score += (count5 % 3) * 50;
    }
    for (int i = 0; i < 6; i++) {
        int repeats = digits[i];
        if (repeats >= 3) {
            switch (i+1) { // 索引加1还原为骰子点数
              case 1:
                score += 1000;
                break;
              case 2:
                score += 200;
                break;
              case 3:
                score += 300;
                break;
              case 4:
                score += 400;
                break;
              case 5:
                score += 500;
                break;
              case 6:
                score += 600;
                break;
              default:
                break;
            }
        }
    }
    return score;
}

两种方式都能解决数组越界问题,确保在任何环境下都能稳定运行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 05:54:59