首页 > 解决方案 > 在c中初始化一个扫雷艇

问题描述

我目前正在使用 CSFML 库在 C 中重写一个扫雷程序。

我在第一次单击后管理初始化时遇到了一些问题,更准确地说是在我应该将单击周围的图块设置为空的部分。

我找不到办法让这些瓷砖清空而不冒移除一些炸弹的风险。这是我现在的初始化代码块:

int current = 0;

    temp.bombs = BOMB_EASY;
    temp.difficulty = EASY;
    temp.mapEasy = malloc(sizeof(sTILE *) * (Y_EASY + 1));

    for (int i = 0; i < Y_EASY + 1 ; i++)
    {
        temp.mapEasy[i] = malloc(sizeof(sTILE) * (X_EASY + 1));
    }

    for (int i = 0; i < X_EASY + 1; i++)
    {
        temp.mapEasy[Y_EASY][i].type = 0;
    }

    while (current < BOMB_EASY)
    {
        for (int i = 0; i < Y_EASY; i++)
        {
            for (int j = 0; j < X_EASY; j++)
            {
                int isBomb = rand() % 10;
                if (isBomb == 0 && current < BOMB_EASY && temp.mapEasy[i][j].type != 9)
                {
                    temp.mapEasy[i][j].type = 9;
                    current++;
                }
                else if (temp.mapEasy[i][j].type != 9)
                {
                    temp.mapEasy[i][j].type = 0;
                }
            }
        }
    }

    for (int i = 0; i < Y_EASY; i++)
    {
        for (int j = 0; j < X_EASY; j++)
        {
            if (temp.mapEasy[i][j].type == 0)
            {
                temp.mapEasy[i][j].type = HowManyBombs(temp.mapEasy, i, j, Y_EASY, X_EASY);
            }
            temp.mapEasy[i][j].isRevealed = sfFalse;
            temp.mapEasy[i][j].isFlagged = sfFalse;
        }
    }
}

我知道我的问题可能看起来很愚蠢,并且可能已经有人回答了,但我找不到答案,所以感谢那些会回答我的人。

标签: cinitializationminesweeper

解决方案


  1. 创建一个空矩阵
  2. 在随机位置用n 个地雷填充它。生成 (x, y) 坐标后,检查它们是否已被使用。
  3. 如果坐标已经被获​​取,您应该将地雷放置在下一个可用位置。

    例如,通过将 x 增加 1,检查是否空闲,如果没有,则再次增加 x。到达行尾时,改为增加 y 并从 x=0 重新开始。

    如果您只是生成一个新的随机数,理论上您的算法可能会永远卡住。在实践中它可能会起作用,但我希望这样的算法生成网格的速度比只选择下一个空闲点的算法慢1) 。


1) rand() 调用开销是该算法中最可能的瓶颈。但是,如果您选择下一个位置而不是再次调用 rand(),CPU 可能能够推测性地将数组(部分)加载到预取数据缓存中。当您每次选择它时内存位置实际上是随机的时,这是不可能的。


推荐阅读