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

C语言模式游戏开发:用数组校验玩家输入字符重复实现问题

C语言模式类游戏输入重复校验方案

需求

开发模式类游戏时需要实现输入字符去重逻辑:玩家1(uno)、玩家2(dos)的所有历史输入字符不允许重复,若输入已使用过的字符,要提示用户重新输入未使用的字符,预期运行效果如下:

Round 1:
Player 1 Inputs : -> A
Player 2 Inputs : -> B
Valid

Round 2:
 Player 1 Inputs : -> L
 Player 2 Inputs  : -> V
Valid
Round 3:
Player 1 Inputs : -> A (Invalid Already been used)
enter char again

现有基础代码

#include <stdio.h>
#include <string.h>
#define SWITCH(_g0,_g1) \
(_g0 << 8) | (_g1 << 0)
#define CASE(_g0,_g1) \
case SWITCH(_g0,_g1)

int getval(const char *prompt)
{
    char *cp;
    char buf[100];
    int val;
    while (1) {
        printf("%s: ",prompt);
        fflush(stdout);
        cp = fgets(buf,sizeof(buf),stdin);
        // handle end of file
        if (cp == NULL) {
            val = -1;
            break;
        }
        // get the first char on the line
        val = buf[0];
        if (val != '\n')
            break;
    }
    return val;
}

int main ()
{
    int i = 0;
    int roundCount = 1;
    int pos = 0;
    int over = 0;
    int f = 1;
    char G[9];
    char uno,dos;
    printf("Game Start!\n");

    do {
        printf("Round %d!\n", roundCount++);
        printf("Input selection upon prompt.\n");

        printf("Player 1: ");
        scanf(" %c", &uno );
        printf("Player 2: ");
        scanf(" %c", &dos);

        //printf("DEBUG: %2.2X %2.2X\n",G[0],G[1]);

        switch (SWITCH(uno,dos)) {
            CASE('L','V'):
            CASE('V','S'):
            CASE('S','P'):
            CASE('P','R'):
            CASE('R','L'):
            CASE('R','S'):
            CASE('P','V'):
            CASE('S','L'):
            CASE('V','R'):
            CASE('L','P'):
                f++;
                pos--;
                printf("Uno Wins!   Pos[%d]\n\n", pos);
                break;
            CASE('R','P'):
            CASE('L','R'):
            CASE('R','V'):
            CASE('P','S'):
            CASE('P','L'):
            CASE('S','R'):
            CASE('S','V'):
            CASE('L','S'):
            CASE('V','P'):
            CASE('V','L'):
                f++;
                pos++;
                printf("Dos Wins    Pos[%d]!\n\n", pos);
                break;
            CASE('R','R'):
            CASE('P','P'):
            CASE('S','S'):
            CASE('L','L'):
            CASE('V','V'):
                f++;
                pos = pos;
                break;
        }
        if (pos == -3 || pos == 3) {
            printf("Game over\n");
            break;
        }
        if (f == 5 && pos != -3 && pos != 3) {
            switch (SWITCH(uno,dos)) {
                CASE('L','V'):
                CASE('V','S'):
                CASE('S','P'):
                CASE('P','R'):
                CASE('R','L'):
                CASE('R','S'):
                CASE('P','V'):
                CASE('S','L'):
                CASE('V','R'):
                CASE('L','P'):
                    printf("Uno:Wins!\n");
                    break;
                CASE('R','P'):
                CASE('L','R'):
                CASE('R','V'):
                CASE('P','S'):
                CASE('P','L'):
                CASE('S','R'):
                CASE('S','V'):
                CASE('L','S'):
                CASE('V','P'):
                CASE('V','L'):
                    printf("Dos Win!\n");
                    break;
            }
        }
    } while (f < 5);
    return 0;
}

(注:已修复原有代码中函数名定义错误、括号不匹配的基础语法问题)

原有尝试的问题

你之前写的单次for循环校验逻辑存在两个核心问题:

  1. 仅遍历校验一次,如果用户第二次输入的字符仍然重复,不会触发二次校验,会直接放行
  2. 未绑定已使用字符的实际数量,遍历整个数组长度会读到未初始化的无效元素,导致逻辑错误

修改后完整实现代码

#include <stdio.h>
#include <string.h>
#define SWITCH(_g0,_g1) \
(_g0 << 8) | (_g1 << 0)
#define CASE(_g0,_g1) \
case SWITCH(_g0,_g1)

// 校验字符是否已被使用
int is_used(char c, char *used_arr, int used_len) {
    for(int i=0; i<used_len; i++) {
        if(used_arr[i] == c) return 1;
    }
    return 0;
}

int getval(const char *prompt)
{
    char *cp;
    char buf[100];
    int val;
    while (1) {
        printf("%s: ",prompt);
        fflush(stdout);
        cp = fgets(buf,sizeof(buf),stdin);
        // handle end of file
        if (cp == NULL) {
            val = -1;
            break;
        }
        // get the first char on the line
        val = buf[0];
        if (val != '\n')
            break;
    }
    return val;
}

int main ()
{
    int i = 0;
    int roundCount = 1;
    int pos = 0;
    int over = 0;
    int f = 1;
    char G[9];
    char uno,dos;
    // 新增:存储已使用的字符,最多5轮共10个字符,预留足够空间
    char used_chars[20];
    int used_cnt = 0;
    printf("Game Start!\n");

    do {
        printf("Round %d!\n", roundCount++);
        printf("Input selection upon prompt.\n");

        // 玩家1输入加重复校验
        while(1) {
            printf("Player 1: ");
            scanf(" %c", &uno);
            if(is_used(uno, used_chars, used_cnt)) {
                printf("(Invalid Already been used)\nenter char again\n");
            } else {
                break;
            }
        }
        used_chars[used_cnt++] = uno;

        // 玩家2输入加重复校验
        while(1) {
            printf("Player 2: ");
            scanf(" %c", &dos);
            if(is_used(dos, used_chars, used_cnt)) {
                printf("(Invalid Already been used)\nenter char again\n");
            } else {
                break;
            }
        }
        used_chars[used_cnt++] = dos;
        printf("Valid\n\n");

        //printf("DEBUG: %2.2X %2.2X\n",G[0],G[1]);

        switch (SWITCH(uno,dos)) {
            CASE('L','V'):
            CASE('V','S'):
            CASE('S','P'):
            CASE('P','R'):
            CASE('R','L'):
            CASE('R','S'):
            CASE('P','V'):
            CASE('S','L'):
            CASE('V','R'):
            CASE('L','P'):
                f++;
                pos--;
                printf("Uno Wins!   Pos[%d]\n\n", pos);
                break;
            CASE('R','P'):
            CASE('L','R'):
            CASE('R','V'):
            CASE('P','S'):
            CASE('P','L'):
            CASE('S','R'):
            CASE('S','V'):
            CASE('L','S'):
            CASE('V','P'):
            CASE('V','L'):
                f++;
                pos++;
                printf("Dos Wins    Pos[%d]!\n\n", pos);
                break;
            CASE('R','R'):
            CASE('P','P'):
            CASE('S','S'):
            CASE('L','L'):
            CASE('V','V'):
                f++;
                pos = pos;
                break;
        }
        if (pos == -3 || pos == 3) {
            printf("Game over\n");
            break;
        }
        if (f == 5 && pos != -3 && pos != 3) {
            switch (SWITCH(uno,dos)) {
                CASE('L','V'):
                CASE('V','S'):
                CASE('S','P'):
                CASE('P','R'):
                CASE('R','L'):
                CASE('R','S'):
                CASE('P','V'):
                CASE('S','L'):
                CASE('V','R'):
                CASE('L','P'):
                    printf("Uno:Wins!\n");
                    break;
                CASE('R','P'):
                CASE('L','R'):
                CASE('R','V'):
                CASE('P','S'):
                CASE('P','L'):
                CASE('S','R'):
                CASE('S','V'):
                CASE('L','S'):
                CASE('V','P'):
                CASE('V','L'):
                    printf("Dos Win!\n");
                    break;
            }
        }
    } while (f < 5);
    return 0;
}

逻辑说明

  • 新增used_chars数组存储两个玩家所有历史输入的字符,used_cnt记录已存储的字符数量
  • 输入阶段用死循环做校验,只有输入未使用的字符才会跳出循环,存入数组后进入后续逻辑
  • 单独封装is_used校验函数,代码可复用性更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 09:27:02