【问题标题】:Array element disappears数组元素消失
【发布时间】:2015-12-27 02:45:07
【问题描述】:

我正在尝试用 x 标记他们的位置来跟踪玩家的位置。当玩家输入一个字符串时,我相应地增加坐标。但是,当玩家位于距离边界一格的位置,然后尝试移动到地图边缘时,玩家就会消失。

例子:

.....  
...x.  
.....  
.....  
.....

玩家位于'x'

如果玩家输入字符串“right”并且我移动player_loc,则数组简单地返回:

.....  
.....  
.....  
.....  
.....

我试图通过增加数组的大小来添加一种缓冲区。没有运气。我已经坚持了将近一个星期了。任何帮助,将不胜感激。我为混乱的代码道歉。我在这方面完全是新手,我真的只是在黑暗中摸索所有这些东西。我在这里的论坛上对此进行了研究,但没有找到解决方案。如果您知道我可能(可能)错过的某些事情,请随时指出我的方向。

#include <stdio.h>
#include <string.h>
char map[6][6];
char player_loc = 'x';
int row;
int col;

void init_map()
{
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {

        map[i][j] = '.';

        }
    }
}

void print_map()
{
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {

                printf("%c", map[i][j]);

            }
        printf("\n");
        }
}

int get_player_loc()
{
    for (int j = 0; j < 5; j++) {
        for (int k = 0; k < 5; k++) {
            if(map[j][k] == player_loc)
            {
                row = k;
                col = j;
            }
        }
    }
    return row;
    return col;
}

void init_player_loc()
{
    int check = 1;
    for (int g = 0; g < 5; g++) {
        for (int h = 0; h < 5; h++) {
            if (map[g][h] == 'x') {
                check = 0;
            }

        }   
    }
    if(check == 1) {
        map[0][0] = player_loc;
    } else {
        get_player_loc();
    }

}

void move_left()
{
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            if (map[i][j] == player_loc) {
                map[i][j-1] = player_loc;
                map[i][j] = '.';
            }
        }
    }

}

void move_right()
{
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            if (map[i][j] == player_loc) {
                map[i][j+1] = player_loc;
                map[i][j] = '.';
            }
        }
    }
}




int main(int argc, char* argv[])
{
    char input[15];
    printf("You enter a room...you can go left, right, or straight. Which way do you go?\n");

    int done = 0;

    init_map();
    map[3][3] = player_loc;
    //init_player_loc();
    print_map();

    while (!done)  {
        scanf("%s", input);

            if (strcmp("left", input) == 0) {
                move_left();
                printf("You go left...\n");
                print_map();
                get_player_loc();
                printf("%d %d\n", row, col);
                done = 1;
            } 
            else if (strcmp("right", input) == 0) {
                move_right();
                printf("You go right...\n");
                print_map();
                get_player_loc();
                printf("%d %d\n", row, col);
                done = 1;
            }
            else if (strcmp("straight", input) == 0) {
                printf("You go straight...");
                done = 1;
            }
            else {
                printf("Sorry, can't do that.\n");
            }
        }
}

【问题讨论】:

  • 你在哪里增加索引?
  • 抱歉,没有意识到我粘贴了旧文件。解决了这个问题。在 if 语句中,我正在打印坐标以尝试调试它。实际上不是“游戏”的一部分。
  • get_player_loc() 中,您不能让return row; return col; } 返回行和列;它返回单个值,即rowreturn col; 语句不可访问,编译器应对此发出警告。但是,如果您正在设置全局变量,则不需要返回任何一个值; get_player_loc() 应该是 void get_player_loc(void) 最后没有返回。或者你可以从if 中返回,如果你到达最后会出现错误;这将显示一个问题(没有玩家)。

标签: c arrays elements


【解决方案1】:

如果找到播放器位置,则必须中断循环,例如

void move_right()
{
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            if (map[i][j] == player_loc) {
                map[i][j+1] = player_loc;
                map[i][j] = '.';
                return;
            }
        }
    }
}

在您的代码中,您将玩家向右移动,下一个循环将在新位置找到玩家并再次向右移动,直到永远。

此外,在您的代码中,您没有处理二维矩阵的边界:j+1 仅在 j&lt;5 时有效。 那么更好的代码应该是

void move_right()
{
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if (map[i][j] == player_loc) {
                map[i][j+1] = player_loc;
                map[i][j] = '.';
                return;
            }
        }
    }
}

【讨论】:

  • @Jiminion 如果他以这种方式实现他可以。实际代码没有规定玩家在到达左边界或右边界时继续前进i+1i-1
【解决方案2】:

问题在于您的move_right 函数会拾取玩家并将他们完全移出地图。假设您的播放器位于[0, 2] 并单步执行代码。

for (int j = 0; j < 5; j++) {
    if (map[i][j] == player_loc) {
        map[i][j+1] = player_loc;
        map[i][j] = '.';
    }
}
  • [0, 0]这里没有玩家,继续前进
  • [0, 1]这里没有玩家,继续前进
  • [0, 2]找到玩家了!将它们右移至[0, 3]
  • [0, 3]找到玩家了!将它们右移至[0, 4]
  • [0, 4]找到玩家了!将它们右移至[0, 5]

在 5 点,循环结束。由于您添加了缓冲区,您的数组是 6x6,因此玩家被隐藏在机翼中而不会导致程序崩溃。您应该做几件事:

  • 找到并移动播放器后,breakreturn 这样它们只会移动一次。
  • 将您的阵列设为 5x5(或全部打印 6x6),以便您可以查看所有内容。
  • 做一些边界检查,这样玩家就不能从j = 5向右移动。
  • 注意move_up 中的相同错误,当您增加i 时会发生这种错误。

【讨论】:

  • 我想真正让我感到困惑的是左侧功能有效但右侧无效。现在它是有道理的。我正在通过数组解析“向前”,所以一旦我将播放器向左移动,该函数就会越过播放器。向右移动时,玩家仍处于 for 循环的“路径”中。脑洞大开。我在 move_right 函数中添加了一个中断,现在它可以完美运行了。非常感谢你的帮助! @Kristján
  • 乐于助人!当您在迭代列表的同时修改列表时,这是一个需要注意的常见问题。祝你好运!
【解决方案3】:

您的循环允许检查位置两次,一次是在 i,j,另一次是在 i,(j+1)(或其他一些变体)。这可能不是你想要的。找到播放器后,您应该进行更新,然后跳出循环。

此外,理论上,代码原样允许通过数组边界进行索引。也不是想要的。您可以考虑边界检查。我不知道当玩家向右移动并且右侧有一堵墙时会发生什么。他不动吗?环绕? LR 拐角可能会导致 seg 错误,就像现在一样。

【讨论】:

    【解决方案4】:

    您似乎在get_player_loc 函数中转置了行和列索引,并且有两个返回语句(编译器应该警告您有关无法访问的代码),调用代码都不需要或使用这两个语句。

    一开始,初始化rowcol 变量。 (取自您的 main 的值。)

    int row = 3;
    int col = 3;
    

    更改get_player_loc 函数,使其仅更新全局变量rowcol。如果没有找到播放器,它会将rowcol 设置为0,按照原始设置。

    void get_player_loc(void)
    {
        for (int j = 0; j < 5; j++) {
            for (int k = 0; k < 5; k++) {
                if(map[j][k] == player_loc)
                {
                    // The meaning of row and col is set by how they are used
                    // to index the array in the move and print functions.  Keep
                    // the same order and meaning here.
                    row = j;
                    col = k;
                    return;
                }
            }
        }
        // Set row and col to 0 if the location is not found.
        row = 0;
        col = 0;
        map[0][0] = player_loc;
    }
    

    当它们到达边缘时你仍然会遇到问题,因为数组的索引超出了移动函数的范围,但这是一个不同的问题。

    【讨论】:

    • 我编辑了 get_player_loc 函数,现在出现错误。 'return' 没有值,在函数中返回非 void [默认启用]
    • 请注意,该函数现在定义为void get_player_loc(void)。您可能已将第一个 void 保留为 int。很高兴您找到了问题的正确答案和解决方案。
    猜你喜欢
    • 2017-09-13
    • 2018-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-12
    • 2023-03-15
    • 2022-11-15
    • 2017-11-22
    相关资源
    最近更新 更多