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

C语言潜艇对战游戏循环迭代异常问题排查求助

潜艇击沉游戏循环逻辑输出异常问题修复

问题描述

开发一款类似战舰的变体游戏,目标是在5轮内击沉一艘潜艇。游戏采用10×10坐标系,用户输入坐标后程序需反馈击中、未击中(附带瞄准方位提示)或输入坐标非法。各功能单独运行正常,但加入循环(处理非法输入重输及5轮次数限制)后,程序出现输出异常。

原代码

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

const char* southNorth(int row, int uRow);
const char* eastWest(int col, int uCol);

int main(void)
{
    int col, row;
    char k;

    int uCol = 3;
    int uRow = 8;

    
    printf("The submarine is hiding at the ocean floor.\n");
    printf("You have five depth charges. Try to sing the submarine!\n");
    printf("\n");

    for (int i = 1; i <=5; i++)
    {
        while (1)
        {
            printf("Where to try next (col row)? ");
            scanf("%c %d", &k, &row);

            if ( isupper(k))
            {
                col = k - ('A'-1);
            }
            else if (islower(k))
            {
                col = k - ('a'-1);
            }
            if (col >= 1 && col <= 10 && row >= 1 && row <= 10)
            {
                break;
            }
             printf("Sorry, illegal input!\n");
             printf("\n");
        }
        
        if (southNorth(row, uRow) == NULL && eastWest(col, uCol) == NULL)
        {
            printf("Well done, you sank the submarine in %d tries!\n", i);
            return 0;
        }
        else if (southNorth(row, uRow) == NULL && eastWest(col, uCol) != NULL)
        {
            printf("Miss. Sonar indicates that the submarine is located %s of your current position.\n",  eastWest(col, uCol));
            continue;
        }
        else if (southNorth(row, uRow) != NULL && eastWest(col, uCol) == NULL)
        {
            printf("Miss. Sonar indicates that the submarine is located %s of your current position.\n", southNorth(row, uRow));
            continue;
        }
        else
        {
            printf("Miss. Sonar indicates that the submarine is located %s%s of your current position.\n", southNorth(row, uRow), eastWest(col, uCol));
            continue;
        }
    }
    
    return 0;
}

const char* southNorth(int row, int uRow) 
{
    char *nS;
    if (row < uRow)
    {
        nS = "south";
    }
    else if (row > uRow)
    {
        nS = "north";
    }
    else
    {
        nS = NULL;
    }
    return nS;
}

const char* eastWest(int col, int uCol) 
{
    char *eW;
    if (col < uCol)
    {
        eW = "west";
    }
    else if (col > uCol)
    {
        eW = "east";
    }
    else
    {
        eW = NULL;
    }
    return eW;
}

问题分析

  1. 输入缓冲区残留换行符:scanf("%c %d", &k, &row)会读取用户输入的字符和数字,但回车产生的换行符会留在缓冲区,下一次调用scanf时会直接读取该换行符作为k的值,触发非法输入提示,导致输出异常。
  2. col变量未初始化:当输入的字符不是大小写字母时,col未被赋值,此时判断col >=1 && col <=10会使用内存中的垃圾值,导致非法输入逻辑误判。
  3. 方位提示格式错误:同时显示南北和东西方位时,两个字符串直接拼接(如southeast),缺少空格分隔,影响可读性。
  4. 拼写错误:Try to sing the submarine!应为Try to sink the submarine!。

修复方案及代码

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

const char* southNorth(int row, int uRow);
const char* eastWest(int col, int uCol);

int main(void)
{
    int col = 0, row; // 初始化col为0
    char k;

    int uCol = 3;
    int uRow = 8;

    printf("The submarine is hiding at the ocean floor.\n");
    printf("You have five depth charges. Try to sink the submarine!\n"); // 修正拼写错误
    printf("\n");

    for (int i = 1; i <=5; i++)
    {
        while (1)
        {
            printf("Where to try next (col row)? ");
            scanf(" %c %d", &k, &row); // %c前添加空格,跳过空白字符(包括换行)

            col = 0; // 每次输入前重置col
            if (isupper(k))
            {
                col = k - ('A'-1);
            }
            else if (islower(k))
            {
                col = k - ('a'-1);
            }
            // 明确判断col是否有效,且row在范围内
            if (col >= 1 && col <= 10 && row >= 1 && row <= 10)
            {
                break;
            }
            printf("Sorry, illegal input!\n");
            printf("\n");
        }
        
        if (southNorth(row, uRow) == NULL && eastWest(col, uCol) == NULL)
        {
            printf("Well done, you sank the submarine in %d tries!\n", i);
            return 0;
        }
        else if (southNorth(row, uRow) == NULL && eastWest(col, uCol) != NULL)
        {
            printf("Miss. Sonar indicates that the submarine is located %s of your current position.\n",  eastWest(col, uCol));
        }
        else if (southNorth(row, uRow) != NULL && eastWest(col, uCol) == NULL)
        {
            printf("Miss. Sonar indicates that the submarine is located %s of your current position.\n", southNorth(row, uRow));
        }
        else
        {
            // 两个方位之间添加空格
            printf("Miss. Sonar indicates that the submarine is located %s %s of your current position.\n", southNorth(row, uRow), eastWest(col, uCol));
        }
    }
    // 5轮未击沉的提示
    printf("Game over! The submarine got away.\n");
    return 0;
}

const char* southNorth(int row, int uRow) 
{
    if (row < uRow)
    {
        return "south";
    }
    else if (row > uRow)
    {
        return "north";
    }
    else
    {
        return NULL;
    }
}

const char* eastWest(int col, int uCol) 
{
    if (col < uCol)
    {
        return "west";
    }
    else if (col > uCol)
    {
        return "east";
    }
    else
    {
        return NULL;
    }
}

修复说明

  • 在scanf(" %c %d", &k, &row)的%c前添加空格,自动跳过输入缓冲区中的空白字符(包括换行、空格等),解决残留换行符导致的异常。
  • 初始化col变量,并在每次输入循环前重置为0,避免垃圾值影响非法输入判断。
  • 修改方位提示的输出格式,在南北和方位字符串之间添加空格,提升可读性。
  • 修正原文中的拼写错误,并添加5轮未击沉的结束提示,完善游戏逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 19:10:49