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

Hangman游戏失败时无法打印目标词:首字符被改为'\000'问题排查

解决你的Hangman游戏失败时无法打印目标词的问题

嘿,我帮你找到了问题的核心——这是一个典型的栈内存越界写入导致的内存污染,正是它把目标词的首字符改成了'\0',让你没法正常打印出来。咱们一步步拆解问题,然后给出修复方案:

1. 越界写入的罪魁祸首

你定义了char letters[MAX_GUESS+1];,MAX_GUESS是6,所以这个数组总共能存7个字符(下标0到6)。但在循环里你写了:

letters[guesses] = temp_char;
letters[guesses+1] = '\0';

当guesses走到6(也就是第6次失败)的时候,guesses+1等于7,这时候你在给letters[7]赋值——这已经超出了数组的合法边界!

C语言的栈变量是连续排布的,letters数组越界写入的这个字节,刚好覆盖了相邻的word数组的第一个字符,把它改成了字符串结束符'\0'——这就是为什么失败时目标词打印不出来的原因。

2. 还有几个需要补的小坑

除了越界问题,代码里还有几个影响逻辑的小问题:

  • 未初始化的input数组:char input[MAX_STRING];没有初始化,一开始里面全是随机垃圾值,导致你第一次循环里的if (word[j] == input[j])判断完全不可靠,初始的下划线显示也不对。
  • 重复猜字母会误判失败:用户如果重复输入同一个字母,当前代码会重复计入失败次数,这显然不符合游戏逻辑。
  • 循环条件的边界错误:guesses <= MAX_GUESS会让用户多猜一次,因为guesses从0开始计数,到6的时候已经是第7次尝试,超过了设定的6次失败上限。

3. 修复后的完整代码

这里是把所有问题都修好的版本,逻辑更严谨,也不会再出现内存污染的问题:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define VOCABULARY_SIZE 8
#define MAX_STRING 32
#define MAX_GUESS 6

int random_number(int a, int b) {
    return a + rand() % (b - a + 1);
}

int main() {
    // 随机选择目标词
    srand((unsigned)time(NULL));
    const char VOCABULARY[VOCABULARY_SIZE][MAX_STRING] = {"vehicle", "building", "shirt", "pencil", "batman", "dromedary", "peach", "hangman"};
    char word[MAX_STRING];
    int i = random_number(0, VOCABULARY_SIZE - 1);
    strcpy(word, VOCABULARY[i]);
    
    int guesses = 0, length = strlen(word);
    char letters[MAX_GUESS + 1] = {0}; // 初始化字母数组为全0,确保字符串合法
    char input[MAX_STRING];
    // 初始化input为全下划线,和目标词长度匹配,末尾加结束符
    memset(input, '_', length);
    input[length] = '\0';
    char temp_char;
    char temp_input[MAX_STRING];

    do {
        printf("\nYour entered letters are: %s\n", letters);
        printf("Your letters found are: %s\n", input); // 直接打印input,不用循环判断,更简洁
        printf("%d-letter word. %d out of %d failures. Enter a letter: ", length, guesses, MAX_GUESS);
        scanf(" %c", &temp_char);
        
        // 先检查这个字母有没有猜过,避免重复计数
        if (strchr(letters, temp_char) == NULL) {
            int found_match = 0;
            // 遍历目标词,匹配到字母就更新input
            for (int j = 0; j < length; j++) {
                if (word[j] == temp_char) {
                    input[j] = word[j];
                    found_match = 1;
                }
            }
            // 只有没匹配到的时候,才把字母加入已猜列表,增加失败次数
            if (!found_match) {
                int current_len = strlen(letters);
                letters[current_len] = temp_char;
                letters[current_len + 1] = '\0';
                guesses++;
            }
        } else {
            printf("You already guessed '%c'! Try another one.\n", temp_char);
        }

        printf("\nWhat is the word to guess? ");
        scanf(" %s", temp_input);
    } while ((strcmp(input, word) != 0 && strcmp(temp_input, word) != 0) && guesses < MAX_GUESS); // 改成<,确保不超过最大失败次数

    // 游戏结束判定
    if (strcmp(input, word) == 0 || strcmp(temp_input, word) == 0) {
        printf("\nCongratulations, the word was %s!\n", word);
    } else {
        printf("\nBetter luck next time... The word was %s\n", word);
    }

    return 0;
}

修复要点总结

  • 彻底解决越界问题:现在用strlen(letters)获取已猜字母的长度,再添加新字母,完全避免了越界写入的风险,同时初始化letters为全0,确保字符串始终有效。
  • 初始化input数组:用memset把input初始化为下划线,初始显示正确,后续的strcmp判断也能正常工作。
  • 优化猜字母逻辑:增加了重复猜字母的检测,避免用户重复输入同一个字母却被误判为失败。
  • 修正循环边界:把guesses <= MAX_GUESS改成guesses < MAX_GUESS,确保用户最多只能失败6次,符合游戏设定。

这样修改后,不管玩家获胜还是失败,目标词都能正常打印,游戏逻辑也更流畅啦!

内容的提问来源于stack exchange,提问作者Ivan.2j

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:32:35