1

互いに衝突しないように、グリッド内に数字を配置する必要があります。この数字の配置はランダムにする必要があり、水平または垂直にすることができます。番号は基本的に船の位置を示します。したがって、船のポイントは一緒にある必要があり、ランダムである必要があり、衝突するべきではありません。

私はそれを試しました:

int main()
{
    srand(time(NULL));
    int Grid[64];
    int battleShips;
    bool battleShipFilled;

    for(int i = 0; i < 64; i++)
        Grid[i]=0;

    for(int i = 1; i <= 5; i++)
    {
        battleShips = 1;
        while(battleShips != 5)
        {
            int horizontal = rand()%2;
            if(horizontal == 0)
            {
                battleShipFilled = false;
                while(!battleShipFilled)
                {
                    int row = rand()%8;
                    int column = rand()%8;

                    while(Grid[(row)*8+(column)] == 1)
                    {
                        row = rand()%8;
                        column = rand()%8;
                    }

                    int j = 0;
                    if(i == 1) j= (i+1);
                    else j= i;

                    for(int k = -j/2; k <= j/2; k++)
                    {
                        int numberOfCorrectLocation = 0;
                        while(numberOfCorrectLocation != j)
                        {
                            if(row+k> 0 && row+k<8)
                            {
                                if(Grid[(row+k)*8+(column)] == 1) break;
                                numberOfCorrectLocation++;
                            }
                        }
                        if(numberOfCorrectLocation !=i) break;
                    }

                    for(int k = -j/2; k <= j/2; k++)
                        Grid[(row+k)*8+(column)] = 1;
                    battleShipFilled = true;    
                }
                battleShips++;
            }
            else
            {
                battleShipFilled = false;
                while(!battleShipFilled)
                {
                    int row = rand()%8;
                    int column = rand()%8;

                    while(Grid[(row)*8+(column)] == 1)
                    {
                        row = rand()%8;
                        column = rand()%8;
                    }

                    int j = 0;
                    if(i == 1) j= (i+1);
                    else j= i;

                    for(int k = -j/2; k <= j/2; k++)
                    {
                        int numberOfCorrectLocation = 0;
                        while(numberOfCorrectLocation != i)
                        {
                            if(row+k> 0 && row+k<8)
                            {
                                if(Grid[(row)*8+(column+k)] == 1) break;
                                numberOfCorrectLocation++;
                            }
                        }
                        if(numberOfCorrectLocation !=i) break;
                    }

                    for(int k = -j/2; k <= j/2; k++)
                        Grid[(row)*8+(column+k)] = 1;
                    battleShipFilled = true;    
                }
                battleShips++;
            }
        }
    }
}

しかし、私が書いたコードは、8x8 グリッドでランダムに数字を生成することができません。

これを解決する方法についてのガイダンスが必要です。何か良い方法があれば教えて...

どのように見えるか:

ここに画像の説明を入力

私のコードが行っていること: 基本的に、グリッド上にそれぞれ異なるサイズの 5 つの船を配置しています。それぞれ、横置きにするか縦置きにするかをランダムにチェックします。その後、周囲が埋まっているかどうかを確認します。そうでない場合は、そこに配置します。または、プロセスを繰り返します。

重要なポイント: while、for ループだけを使用する必要があります。

4

4 に答える 4

1

いくつかの OOP を使用して、ソリューションを実際にクリーンアップし、より柔軟にする方法の非常に簡単でおそらくバグのある例:

enum Orientation {
    Horizontal,
    Vertical
};

struct Ship {
    Ship(unsigned l = 1, bool o = Horizontal) : length(l), orientation(o) {}
    unsigned char length;
    bool orientation;
};

class Grid {
public:
    Grid(const unsigned w = 8, const unsigned h = 8) : _w(w), _h(h) {
        grid.resize(w * h);
        foreach (Ship * sp, grid) {
            sp = nullptr;
        }
    }

    bool addShip(Ship * s, unsigned x, unsigned y) {
        if ((x <= _w) && (y <= _h)) { // if in valid range
            if (s->orientation == Horizontal) {
                if ((x + s->length) <= _w) { // if not too big
                    int p = 0; //check if occupied
                    for (int c1 = 0; c1 < s->length; ++c1) if (grid[y * _w + x + p++]) return false;
                    p = 0; // occupy if not
                    for (int c1 = 0; c1 < s->length; ++c1)  grid[y * _w + x + p++] = s;
                    return true;
                } else return false;
            } else {
                if ((y + s->length) <= _h) {
                    int p = 0; // check
                    for (int c1 = 0; c1 < s->length; ++c1) {
                        if (grid[y * _w + x + p]) return false;
                        p += _w;
                    }
                    p = 0; // occupy
                    for (int c1 = 0; c1 < s->length; ++c1) {
                        grid[y * _w + x + p] = s;
                        p += _w;
                    }
                    return true;
                } else return false;
            }
        } else return false;
    }

    void drawGrid() {
        for (int y = 0; y < _h; ++y) {
            for (int x = 0; x < _w; ++x) {
                if (grid.at(y * w + x)) cout << "|S";
                else cout << "|_";
            }
            cout << "|" << endl;
        }
        cout << endl;
    }

    void hitXY(unsigned x, unsigned y) {
        if ((x <= _w) && (y <= _h)) {
            if (grid[y * _w + x]) cout << "You sunk my battleship" << endl;
            else cout << "Nothing..." << endl;
        }
    }

private:
    QVector<Ship *> grid;
    unsigned _w, _h;
};

基本的な考え方は、任意のサイズのグリッドを作成し、任意の座標で任意の長さの船を「積載」できるようにすることです。サイズが大きすぎないかどうか、タイルがまだ占有されていないかどうかを確認する必要があります。もう 1 つは方向です。水平方向の場合は増分が +1、垂直方向の増分が + 幅の場合です。

これにより、メソッドを使用してグリッドにランダム データをすばやく入力する柔軟性が得られます。

int main() {
    Grid g(20, 20);
    g.drawGrid();
    unsigned shipCount = 20;

    while (shipCount) {
        Ship * s = new Ship(qrand() % 8 + 2, qrand() %2);
        if (g.addShip(s, qrand() % 20, qrand() % 20)) --shipCount;
        else delete s;
    }
    cout << endl;
    g.drawGrid();

    for (int i = 0; i < 20; ++i) g.hitXY(qrand() % 20, qrand() % 20);
}

当然のことながら、それをさらに拡張して、ヒットした船を沈めたり、グリッドから消したり、船を動かしたり、向きを反転させたりすることができます。斜め方向も使用できます。OOP ベースのソリューションを改良することで、多くの柔軟性と可能性を活用できます。

現在、0x0 のグリッドと長さ 0 のシップを作成できるため、生産コードにいくつかの制限を課すことは明らかです。とにかく、これは簡単な例です。私は Qt を使用しているため、Qt コンテナーを使用していますが、std コンテナーとまったく同じです。

于 2013-08-20T22:25:21.437 に答える