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

C语言中switch语句能否使用数组?CS50拼字游戏代码优化咨询

拼字游戏计分的高效实现方案

我正在完成CS50的编程作业,需要实现一款拼字游戏:两名玩家分别输入单词,每个字母对应不同分值(例如A得1分,Z得10分)。我原本计划通过switch语句结合字符数组来存储对应不同分值的字母,但发现无法在case分支中使用数组,于是编写了如下代码。请问是否存在更高效的实现方式,还是应当回归使用switch语句?

#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    // 获取玩家输入并存储为字符串
    string p1 = get_string("Player 1: ");
    string p2 = get_string("Player 2: ");
    // 初始化玩家得分
    int score1 = 0;
    int score2 = 0;
    char one[20] = {'a','A','e','E','i','I','l','L','n','N','o','O','r','R','s','S','t','T','u','U'};
    char two[4] = {'d','D','g','G'};
    char three[8] = {'b','B','c','C','m','M','p','P'};
    char four[10] = {'f','F','h','H','v','V','w','W','y','Y'};
    char five[2] = {'k','K'};
    char eight[4] = {'j','J','x','X'};
    char ten[4] = {'q','Q','z','Z'};
    int str = strlen(p1);
    for (int N = 0; N < str; N++)
    {
        if (p1[N] == one[0] || p1[N] == one[1] || p1[N] == one[2] || p1[N] == one[3] || p1[N] == one[4] || p1[N] == one[5] || p1[N] == one[6] || p1[N] == one[7] || p1[N] == one[8] || p1[N] == one[9] || p1[N] == one[10] || p1[N] == one[11] || p1[N] == one[12] || p1[N] == one[13] || p1[N] == one[14] || p1[N] == one[15] || p1[N] == one[16] || p1[N] == one[17] || p1[N] == one[18] || p1[N] == one[19])
        {
            score1++;
        } else if (p1[N] == two[0] || p1[N] == two[1] || p1[N] == two[2] || p1[N] == two[3])
        {
            score1 += 2;
        } else if (p1[N] == three[0] || p1[N] == three[1] || p1[N] == three[2] || p1[N] == three[3] || p1[N] == three[4] || p1[N] == three[5] || p1[N] == three[6] || p1[N] == three[7])
        { 
            score1 += 3;
        }
    }
}

更高效的实现:字符分值数组映射

你当前的代码依赖大量条件判断和数组遍历,不仅冗余,效率也低。利用ASCII码的连续性,用数组直接映射每个字母的分值是最优解,能在O(1)时间内获取任意字符的分值,代码简洁易维护。

实现思路

  1. 用tolower()(或toupper())统一字符大小写,避免重复判断大小写字母
  2. 创建一个长度为26的数组,索引对应a-z的偏移量(c - 'a'),数组值为对应字母的分值
  3. 遍历玩家输入的单词,逐个字符转换后累加对应分值

优化后的完整代码

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main(void)
{
    // 获取玩家输入
    string p1 = get_string("Player 1: ");
    string p2 = get_string("Player 2: ");
    
    // 字母分值表:索引0对应a,1对应b,以此类推
    int letter_scores[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10};
    
    // 计算玩家1得分
    int score1 = 0;
    int len1 = strlen(p1);
    for (int i = 0; i < len1; i++)
    {
        char c = tolower(p1[i]);
        if (c >= 'a' && c <= 'z') // 仅处理有效字母
        {
            score1 += letter_scores[c - 'a'];
        }
    }
    
    // 计算玩家2得分
    int score2 = 0;
    int len2 = strlen(p2);
    for (int i = 0; i < len2; i++)
    {
        char c = tolower(p2[i]);
        if (c >= 'a' && c <= 'z')
        {
            score2 += letter_scores[c - 'a'];
        }
    }
    
    // 输出结果
    if (score1 > score2)
    {
        printf("Player 1 wins!\n");
    }
    else if (score2 > score1)
    {
        printf("Player 2 wins!\n");
    }
    else
    {
        printf("Tie!\n");
    }
    
    return 0;
}

方案优势

  • 效率高:直接通过数组索引访问分值,无需遍历或多条件判断
  • 代码简洁:避免了冗长的if-else链,逻辑清晰
  • 易维护:调整分值只需修改数组,无需改动判断逻辑

关于switch语句的选择

如果一定要用switch,也可以实现,但代码会非常冗长。例如:

char c = tolower(p1[i]);
switch(c)
{
    case 'a': case 'e': case 'i': case 'l': case 'n': case 'o': case 'r': case 's': case 't': case 'u':
        score1 += 1;
        break;
    case 'd': case 'g':
        score1 += 2;
        break;
    case 'b': case 'c': case 'm': case 'p':
        score1 += 3;
        break;
    // 剩余分值的case分支...
}

这种方式可行,但代码量远大于数组映射方案,维护成本更高,因此更推荐数组映射的实现方式。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 08:41:01