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)时间内获取任意字符的分值,代码简洁易维护。
实现思路
- 用
tolower()(或toupper())统一字符大小写,避免重复判断大小写字母 - 创建一个长度为26的数组,索引对应a-z的偏移量(
c - 'a'),数组值为对应字母的分值 - 遍历玩家输入的单词,逐个字符转换后累加对应分值
优化后的完整代码
#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
相关产品推荐
相关产品推荐

