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

C语言实现MasterMind游戏:白棋计数函数BUG修复求助

MasterMind游戏白棋计算函数问题修复

问题描述

正在用C语言开发MasterMind游戏,大部分功能已完成,但计算白棋(颜色正确但位置错误)的calculaBrancas函数存在问题:当随机生成的棋盘包含重复颜色,且玩家猜中其中一个错误位置时,函数无法正确计数。

现有完整代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define STRING_MAXIMO 10

void gerarTabuleiro(int nivel, char (*tabuleiro)[STRING_MAXIMO])
{
    char coresNivel1[6][STRING_MAXIMO] = {"vermelho", "verde", "azul", "amarelo", "rosa", "ciano"};
    char coresNivel2[7][STRING_MAXIMO] = {"vermelho", "verde", "azul", "amarelo", "rosa", "ciano", "castanho"};
    char coresNivel3[8][STRING_MAXIMO] = {"vermelho", "verde", "azul", "amarelo", "rosa", "ciano", "castanho", "roxo"};
    int index;

    srand(time(NULL));

    if(nivel == 1){
        for(index = 0; index != nivel + 3; index++)
            strcpy(tabuleiro[index], coresNivel1[rand() % 6]);
    }
    else if(nivel == 2){
        for(index = 0; index != nivel + 3; index++)
            strcpy(tabuleiro[index], coresNivel2[rand() % 7]);
    }
    else if(nivel == 3){
        for(index = 0; index != nivel + 3; index++)
            strcpy(tabuleiro[index], coresNivel3[rand() % 8]);
    }
}

int calculaPretas(int nivel, char (*tabuleiro)[STRING_MAXIMO], char (*palpite)[STRING_MAXIMO])
{
    int index;
    int nDp = 0;

    for(index = 0; index != nivel + 3; index++){
        if(strcmp(palpite[index], tabuleiro[index]) == 0)
            nDp++;
    }
    return nDp;
}

int calculaBrancas(int nivel, char (*tabuleiro)[STRING_MAXIMO], char (*palpite)[STRING_MAXIMO])
{
    int indexT, indexP;
    int nDp = 0;
    int contabilizado[nivel+3];

    for(int index = 0; index != nivel + 3; index++)
        contabilizado[index] = 0;

    for(indexP = 0; indexP != nivel + 3; indexP++){
        for(indexT = 0; indexT != nivel + 3; indexT++){
            if((strcmp(palpite[indexP], tabuleiro[indexT]) == 0) && indexP != indexT && !contabilizado[indexP]){
                nDp++;
                contabilizado[indexP] = 1;         
            }
        }
    }
    return nDp;
}

int main(int argc, char *argv)
{
    int nivel;
    int index;

    printf("#############################################################################################################\n");
    printf("# O objectivo do Mastermind é descobrir uma combinação de cores determinada aleatoriamente pelo computador. #\n");
    printf("# Para tal e necessario que escolha o nivel de jogo adequado                                                #\n");
    printf("# Nivel 1 -> 4 casas e 6 cores possiveis                                                                    #\n");
    printf("# Nivel 2 -> 5 casas e 7 cores possiveis                                                                    #\n");
    printf("# Nivel 3 -> 6 casas e 8 cores possiveis                                                                    #\n");
    printf("# Escolha o nivel pretendido                                                                                #\n");
    scanf("%i", &nivel); 
    printf("# Nivel %i selecionado                                                                                       #\n", nivel);
    printf("#############################################################################################################\n\n\n");

    char tabuleiro[nivel + 3][STRING_MAXIMO];
    char palpite[nivel + 3][STRING_MAXIMO];

    gerarTabuleiro(nivel, tabuleiro);

    /*Teste*/
    printf("| ");
    for(index = 0; index != nivel + 3; index++){
        printf("%s | ", tabuleiro[index]);
    }
    printf("\n\n");
    /*Fim de teste*/

    int novoPalpite;
    int tentativas = 0;
    int numeroDeBrancas = 0, numeroDePretas = 0;

    do{
        printf("# Insira o seu palpite #\n");
        for(index = 0; index != nivel + 3; index++){
            printf("# Casa %i\t", index + 1);
            scanf("%s", palpite[index]);
        }
        tentativas++;

        numeroDePretas = calculaPretas(nivel, tabuleiro, palpite);
        numeroDeBrancas = calculaBrancas(nivel, tabuleiro, palpite);
        printf("###########################################\n");
        printf("# Numero de peças pretas: %i               #\n", numeroDePretas);
        printf("#Numero de peças brancas: %i               #\n", numeroDeBrancas);
        printf("###########################################\n");

        if(numeroDePretas == nivel + 3){
            printf("###########################################\n");
            printf("# Necessitou de %i tentativas para ganhar  #\n", tentativas);
            printf("#                  TABULEIRO              #\n# ");
            for(index = 0; index != nivel + 3; index++)
                printf("%s # ", tabuleiro[index]);
            printf("\n###########################################\n");
            break;
        }

        printf("# Deseja introduzir um novo palpite #\n");
        printf("# 1. Novo palpite #\n");
        printf("# 2. Desistir #\n");
        scanf("%i", &novoPalpite);

        if(novoPalpite == 2){
            printf("# Desistiu do jogo #\n");
            printf("# Tabuleiro #\n ");
            printf("| ");
            for(index = 0; index != nivel + 3; index++)
                printf("%s | ", tabuleiro[index]);
            printf("\n\n");
        }

    }while(novoPalpite == 1);

    return 0;
}

问题分析

原calculaBrancas函数存在两个核心问题:

  1. 未排除黑棋位置:已经被判定为黑棋(颜色和位置均正确)的棋子,不应该参与白棋的计数逻辑,但原函数没有处理这一点,会导致重复计数。
  2. 仅标记猜测项:只标记了猜测的棋子是否已被计数,但没有标记棋盘上的棋子,当棋盘存在重复颜色时,同一个棋盘棋子可能被多个猜测棋子匹配,导致白棋数量虚高。

修复方案

修改calculaBrancas函数,新增棋盘标记数组,先排除黑棋位置,再双向标记已匹配的猜测和棋盘棋子:

int calculaBrancas(int nivel, char (*tabuleiro)[STRING_MAXIMO], char (*palpite)[STRING_MAXIMO])
{
    int indexT, indexP;
    int nDp = 0;
    int tamanho = nivel + 3;
    // 标记棋盘位置是否已被匹配(用于白棋计算)
    int tabuleiroUsado[tamanho];
    // 标记猜测位置是否已被匹配(用于白棋计算)
    int palpiteUsado[tamanho];

    // 初始化标记数组
    for(int index = 0; index < tamanho; index++){
        tabuleiroUsado[index] = 0;
        palpiteUsado[index] = 0;
    }

    // 第一步:标记所有黑棋的位置,这些位置不参与白棋计算
    for(int index = 0; index < tamanho; index++){
        if(strcmp(palpite[index], tabuleiro[index]) == 0){
            tabuleiroUsado[index] = 1;
            palpiteUsado[index] = 1;
        }
    }

    // 第二步:匹配颜色正确但位置错误的棋子,双向标记避免重复计数
    for(indexP = 0; indexP < tamanho; indexP++){
        if(palpiteUsado[indexP]) continue; // 跳过已标记为黑棋或已匹配白棋的猜测项
        for(indexT = 0; indexT < tamanho; indexT++){
            if(tabuleiroUsado[indexT]) continue; // 跳过已标记的棋盘项
            if(strcmp(palpite[indexP], tabuleiro[indexT]) == 0){
                nDp++;
                palpiteUsado[indexP] = 1;
                tabuleiroUsado[indexT] = 1;
                break; // 找到匹配后跳出内层循环,避免同一猜测项匹配多个棋盘项
            }
        }
    }
    return nDp;
}

修改说明

  • 新增两个标记数组tabuleiroUsado和palpiteUsado,分别记录棋盘和猜测的棋子是否已被用于黑棋或白棋计数。
  • 先遍历一次,标记所有黑棋的位置,这些位置直接跳过后续白棋计算。
  • 遍历猜测和棋盘时,仅处理未被标记的项,匹配成功后同时标记双方位置,确保每个棋子只被计数一次。

验证示例

  1. 测试用例1:

    • 棋盘:["vermelho", "vermelho"]
    • 玩家猜测:["vermelho", "azul"]
    • 预期结果:黑棋1,白棋0
    • 修复后函数返回白棋0,符合预期。
  2. 测试用例2:

    • 棋盘:["vermelho", "verde", "vermelho"]
    • 玩家猜测:["verde", "vermelho", "azul"]
    • 预期结果:黑棋0,白棋2
    • 修复后函数返回白棋2,符合预期。
  3. 测试用例3:

    • 棋盘:["vermelho", "vermelho"]
    • 玩家猜测:["azul", "vermelho"]
    • 预期结果:黑棋1,白棋0
    • 修复后函数返回白棋0,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 20:05:31