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

C语言Hangman游戏异常:输入第3个字符后程序崩溃

Hangman游戏C代码终止问题排查与修复建议

问题描述

这是一个基础的Hangman(猜词)游戏C语言代码,运行时输入第3个字符后程序会突然终止。已在2个本地IDE及在线编译器测试,均出现该逻辑错误,请求排查问题并给出解决建议。

原代码

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

int chances = 5;         //可修改剩余次数
char sentence[20];      //单词缓冲区,修改长度时需同步调整indicator的长度
char indicator[20];     //显示猜词进度的占位符
char character;         //存储玩家输入的字符

int woncheck = 0;

void status();          //声明函数
void check();           //声明函数

void main() {

    printf("Wellcome to my hangman game");
    printf("Player 1 please enter your sentence [Max 20 character] ==> ");  
    gets(sentence);         //读取玩家1输入的单词
    
    while (strlen(sentence)>=20)    //检查输入长度是否超标
    {
        printf("Please enter max 20 character ==> ");
        gets(sentence);
    }

    for (int i = 0; i < strlen(sentence); i++) {  //初始化占位符,非空格字符用_代替
        if (sentence[i] != ' ') {
            indicator[i] = '_';
        } else {
            indicator[i] = ' ';
        }
    }

    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");   //清屏

    status(); //显示初始猜词进度

    for (int j = 0; j < chances ; j++) //循环次数等于剩余机会数
    {
        woncheck = 1;   //初始化胜利标记

        for (int k = 0; k < strlen(sentence); k++) {
            if (indicator[k] == '_') { //如果还有未猜中的字符,标记未胜利
                woncheck = 0;
                break;
            }
        }

        if (woncheck == 1) {
            printf("Player 1 won the game\n");
            break;
        }
    
        printf("Player 2 please enter 1 character ==> ");   //提示玩家2输入字符
        scanf(" %c",&character);
        printf("\n");
        chances--;      //剩余机会减1
        check();    //检查输入字符是否匹配
        status();   //更新显示当前进度
        
        if (chances == 0) {
            printf("Player 1 lost the game\n");
            break;
        }
    }
}

void status() {
    for (int  i = 0; i < strlen(sentence); i++)     //遍历单词长度显示占位符
    {
        printf("%c ",indicator[i]);     //打印占位符
    }

    printf("You have %d chances left. \n \n",chances);
}

void check() {
    for (int  i = 0; i < strlen(sentence); i++)
    {
        if (toupper(sentence[i]) == toupper(character))     //不区分大小写检查字符匹配
        {
            indicator[i] = character;
        }
        
    }
}

问题排查

  1. 循环逻辑冲突导致提前终止
    主循环使用for (int j = 0; j < chances ; j++)作为条件,但循环体内每次执行chances--,使得循环的终止条件动态缩小:
  • 初始chances=5,第一次循环后chances=4
  • 第二次循环后chances=3
  • 第三次循环后chances=2
  • 此时j递增到3,3 < 2不成立,循环直接终止,表现为输入3次后程序停止,并非崩溃。
  1. indicator数组未添加字符串终止符
    初始化indicator时仅设置了与sentence长度对应的字符,但未在末尾添加'\0'。虽然当前status函数用strlen(sentence)控制循环长度,但后续若有依赖字符串终止符的操作会引发未定义行为。

  2. gets函数不安全且已废弃
    gets不检查输入长度,若用户输入超过sentence的缓冲区大小(20字节),会导致缓冲区溢出,引发程序崩溃或其他未定义行为。

  3. 胜负判断逻辑颠倒
    原代码中,当玩家2猜对所有字符时,输出"Player 1 won the game",与实际游戏逻辑(玩家2猜中单词获胜)不符。

修复建议

1. 修正循环逻辑

使用独立变量记录剩余机会,避免修改循环条件中的变量,确保循环执行次数符合预期:

int remaining_chances = chances;
while (remaining_chances > 0) {
    // 原有循环体逻辑
}

2. 给indicator添加终止符

在初始化indicator的循环结束后,添加终止符:

int len = strlen(sentence);
for (int i = 0; i < len; i++) {
    // 初始化逻辑
}
indicator[len] = '\0';

3. 替换gets为fgets

fgets可指定最大读取长度,避免缓冲区溢出,同时移除读取到的换行符:

printf("Player 1 please enter your sentence [Max 20 characters] ==> ");  
fgets(sentence, sizeof(sentence), stdin);
sentence[strcspn(sentence, "\n")] = '\0'; // 移除换行符

4. 修正胜负判断逻辑

当玩家2猜中所有字符时,输出玩家2获胜;当机会耗尽未猜中时,输出玩家1获胜:

if (woncheck == 1) {
    printf("Player 2 won the game!\n");
    break;
}
// ...
if (remaining_chances == 0) {
    printf("Player 1 won the game! The word was: %s\n", sentence);
    break;
}

5. 优化机会扣除逻辑

只有当玩家猜错字符时才扣除机会,而非每次输入都扣除:

int found = check(); // 修改check函数返回是否找到匹配字符
if (!found) {
    remaining_chances--;
}

修复后的完整代码

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

int chances = 5;         
char sentence[20];      
char indicator[20];     
char character;         

void status(int remaining);          
int check();           

int main() {
    printf("Welcome to my hangman game!\n");
    printf("Player 1 please enter your sentence [Max 20 characters] ==> ");  
    fgets(sentence, sizeof(sentence), stdin);
    sentence[strcspn(sentence, "\n")] = '\0';
    
    while (strlen(sentence) >= 20) {
        printf("Please enter max 20 characters ==> ");
        fgets(sentence, sizeof(sentence), stdin);
        sentence[strcspn(sentence, "\n")] = '\0';
    }

    int len = strlen(sentence);
    for (int i = 0; i < len; i++) {
        if (sentence[i] != ' ') {
            indicator[i] = '_';
        } else {
            indicator[i] = ' ';
        }
    }
    indicator[len] = '\0';

    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");   

    int remaining_chances = chances;
    status(remaining_chances);

    while (remaining_chances > 0) {
        int woncheck = 1;
        for (int k = 0; k < len; k++) {
            if (indicator[k] == '_') {
                woncheck = 0;
                break;
            }
        }

        if (woncheck == 1) {
            printf("Player 2 won the game!\n");
            break;
        }
    
        printf("Player 2 please enter 1 character ==> ");
        scanf(" %c", &character);
        printf("\n");
        
        int found = check();
        if (!found) {
            remaining_chances--;
        }
        
        status(remaining_chances);
        
        if (remaining_chances == 0) {
            printf("Player 1 won the game! The word was: %s\n", sentence);
            break;
        }
    }
    return 0;
}

void status(int remaining) {
    int len = strlen(sentence);
    for (int i = 0; i < len; i++) {
        printf("%c ", indicator[i]);
    }
    printf("\nYou have %d chances left.\n\n", remaining);
}

int check() {
    int found = 0;
    int len = strlen(sentence);
    for (int i = 0; i < len; i++) {
        if (toupper(sentence[i]) == toupper(character)) {
            indicator[i] = character;
            found = 1;
        }
    }
    return found;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 23:17:03