поворот указателя на массив внутри самого массива - PullRequest
0 голосов
/ 06 марта 2012

Я пишу гибкий алмазно-квадратный генератор местности на C ++.Моя сетка тайлов для значений высоты моего ландшафта определяется как гигантский массив целых.Теперь у меня есть весь алгоритм алмазного квадрата, который управляет этой сеткой как отдельной функцией, stdroutine.Я не могу объявить сетку как глобальную переменную, потому что мне нужно, чтобы пользователь мог определить ее размер (в пределах разумного, хотя проверка размера еще не реализована).Я не хочу просто вставлять содержимое stdroutine в main, потому что я хочу иметь возможность вызывать его несколько раз подряд без особых хлопот (что в конечном итоге потребуется для запуска некоторых предустановленных подпрограмм).Итак, я попытался дать stdroutine указатель на мой массив, в надежде, что он сможет выяснить, где находится массив, если я скажу его.stdroutine фактически вызывает другую функцию, mean, которая также нуждается в работе сетки.Вот мой код (непристойно неправильный, ну да ладно, я не знаю ничего лучше):

main.cpp:

#include <stdio.h>
#include <stdlib.h>
#include "mt.h"
#include "diamondsquare.h"

int main () {
    unsigned  long seed = 0, x = 0, y = 0, initial = 0, range = 0;
    int smooth = 0, fail = 1, index1 = 0, index2 = 0;
    char flagchar1 = 'n';
    printf("Welcome to my diamond-square generator! This isn't full-feature yet, so I'm just gonna have you input the variables one by one. ");
    do {
        printf("Please input the seed (this is a positive integer):\n");
        fail = scanf("%lu", &seed);
        while (fail == 0) {
            printf("Try again, smartass.\n");
            fail = scanf("%lu", &seed);
        }
        fail = 1;
        printf("Now input the x, or horizontal, size of your grid:\n");
        fail = scanf("%lu", &x);
        while (fail == 0) {
            printf("An integer. Not a string. An integer. You can do that, can't you?\n");
            fail = scanf("%lu", &x);
        }
        fail = 1;
        printf("Now input the y, or vertical, size of your grid:\n");
        fail = scanf("%lu", &y);
        while (fail == 0) {
            printf("What was that supposed to be? An integer, please.\n");
            fail = scanf("%lu", &y);
        }
        fail = 1;
        printf("Now input about how high you'd like the grid to be (this goes from a scale of 1 to 256):\n");
        fail = scanf("%lu", &initial);
        while (initial == 0 || initial > 256 || fail == 0) {
            printf("ahahahahaha how HIGH do you have to be just to HAVE that hieght........\n");
            fail = scanf("%lu", &initial);
        }
        fail = 1;
        printf("Now input the range of the heights on your grid (this must be equal to or less than 256):\n");
        scanf("%lu", &range);
        while (range >= 256 || fail == 0) {
            printf("What did I say about being equal to or less than 256? Give me something reasonable to work with here.\n");
            fail = scanf("%lu", &range);
        }
        fail = 1;
        printf("Just one more variable to go! Now, I need you to input the smoothness of your grid. Smaller numbers make spikier grids. You can make this negative, but beware!\n");
        fail = scanf("%d", &smooth);
        while (fail == 0) {
            printf("That... was not a number.\n");
            fail = scanf("%d", &smooth);
        }
        fail = 1;
        printf("\nOkay. Are these the values you want? Type Y/n.\n   Seed:       %lu\n   Width:      %lu\n   Length:     %lu\n   Height:     %lu\n   Range:      %lu\n   Smoothness: %d\n", seed, x, y, initial, range, smooth);
        // Ignore remaining characters on current line.
        int ch;
        while( (ch = getchar()) != EOF && ch != '\n')
            ;
        // fetch first character on next line
        flagchar1 = getchar();
    } while (flagchar1 != 'y' && flagchar1 != 'Y' && flagchar1 != '\n');
    printf("Welp, time to get started!\n\n");
    printf("Twisting primes...\n");                  // Initializes the Mersenne twister.
    mt_init(seed);
    printf("Scrawling preliminary etchings...\n");   // Presets as many values on the grid as is called for.
    printf("Creating depth matrix...\n");            // Declares grid.
    int grid [x] [y];
    printf("Nullifying grid constants...\n");        // Sets all values in grid to 0.
    for (index1 = 0; index1 < x; index1++) {
        for (index2 = 0; index2 < y; index2++) {
            grid [index1] [index2] = 0;
        }
    }
    printf("Filling rhombus circumcenters...\n");     // Actually runs the diamond-square algorithm.
    stdroutine(initial, range, smooth, x, y, &grid);
    printf("Inserting strategic aberrations...");     // Runs any postgenerational script a tag needs (currently only needed for "glacier" tag).
    printf("Applying planetary fabrics...\n");        // Sets the materials of all tiles6.
    printf("Scraping irregularities into suface..."); // Simulates erosion.
    printf("Discharging liquids...\n");               // Inserts liquids.
    printf("Populating biosphere...\n");              // Inserts plants, animals.
    printf("Constructing civilized edifices...\n");   // Inserts structures.
}

diamond-square.h:

int mean (bool sqd, unsigned long mx, unsigned long my, unsigned long x, unsigned long y, int** grid [x] [y]) {
    int x1 = mx, x2 = mx, x3 = mx, x4 = mx, y1 = my, y2 = my, y3 = my, y4 = my;
    int avg;
    if (sqd == false) {
        do {
            y1++;
        } while (**grid [x1] [y1]);
        do {
            x2++;
        } while (**grid [x2] [y2]);
        do {
            y3--;
        } while (**grid [x3] [y3]);
        do {
            x4--;
        } while (**grid [x4] [y4]);
        avg = (**grid [x1] [y1] + **grid [x2] [y2] + **grid [x3] [y3] + **grid [x4] [y4]) / 4;
        return avg;
    }
    else if (sqd == true) {
        do {
            x1--;
            y1++;
        } while (**grid [x1] [y1]);
        do {
            x2++;
            y2++;
        } while (**grid [x2] [y2]);
        do {
            x3++;
            y3--;
        } while (**grid [x3] [y3]);
        do {
            x4--;
            y4--;
        } while (**grid [x4] [y4]);
        avg = (**grid [x1] [y1] + **grid [x2] [y2] + **grid [x3] [y3] + **grid [x4] [y4]) / 4;
        return avg;
    }
    else
        return 0;
}

void stdroutine (unsigned long i, unsigned long r, int h, unsigned long x, unsigned long y, int* grid [x] [y]) { // LADIES AND GENTLEMEN... THE DIAMOND-SQUARE ALGORITHM.
    *grid [0] [0] = i + ((mt_random() % r) - (r/2)); // Set
    *grid [x] [0] = i + ((mt_random() % r) - (r/2)); // the
    *grid [0] [y] = i + ((mt_random() % r) - (r/2)); // four
    *grid [x] [y] = i + ((mt_random() % r) - (r/2)); // corners.
    int sect = 2;                                    // This is the subdivision and iteration count of our diamond-square algorithm.
    while (x / sect != x || y / sect != y) {
        for (int n = 1; n < sect; n++) // The square algorithm: it finds a point in the middle of every square, and sets it to the mean of the four corners of the square, plus a little offset. In theory, anyway.
            for (int m = 1; m < sect; m++)
                if (*grid [x * (m/sect)] [y * (n/sect)] == 0) // If it's already been given a value, just leave it.
                    *grid [x * (m/sect)] [y * (n/sect)] = mean(true, (x * (m/sect)), (y * (n/sect)), x, y) + ((mt_random() % (r - h)) - ((r - h)/2)); // Randomize the location's height.
        for (int n = 0; n == sect; n++)     // The diamond algorithm: it finds a point in the middle of every diamond, and it sets it to the mean of the four corners of the diamond, plus a little offset. In theory, anyway.
            for (int m = 0; m == sect; m++) {
                if (n % 2 == 0)
                    if (m % 2 == 1)
                        if (*grid [x * (m/sect)] [y * (n/sect)] == 0) // Same deal here. We don't want to overwrite existing stuff.
                            *grid [x * (m/sect)] [y * (n/sect)] = mean (false, (x * (m/sect)), y * (n/sect), x, y, &grid) + ((mt_random() % (r - h)) - ((r - h)/2)); // Randomize the location's height.
                if (n % 2 == 1)
                    if (m % 2 == 0)
                        if (*grid [x * (m/sect)] [y * (n/sect)] == 0) // Again, we only want to change positions that haven't been changed yet.
                    *grid [x * (m/sect)] [y * (n/sect)] = mean (false, (x * (m/sect)), (y * (n/sect)), x, y, &grid) + ((mt_random() % (r - h)) - ((r - h)/2)); // Randomize the location's height.
            }
        sect++; // Increment sect for the next iteration. I am perfectly aware that this could have been done as a for loop.
    }
}

(mt.h просто содержит две подпрограммы, mt_init и mt_random, которые соответственно инициализируют и запускают PRNG твистера Мерсенна.)

Как сделать так, чтобы мои указатели на грид играли хорошовсе функции, которые их вызывают?В настоящий момент я получаю четыре ошибки из Xcode 4.3, три в diamond-square.h, «Нет подходящей функции для вызова« mean »» и одна в main.cpp, «Нет соответствующей функции для вызова« stdroutine »».

РЕДАКТИРОВАТЬ: Хм, проще, чем я думал.У меня все еще есть проблема, см. Комментарии.Соответствующий код (main.cpp такой же, но я опускаю амперсанд перед сеткой при вызове stdroutine):

int mean (bool sqd, unsigned long mx, unsigned long my, unsigned long x, unsigned long y, const int grid [] [y]) {
    int x1 = mx, x2 = mx, x3 = mx, x4 = mx, y1 = my, y2 = my, y3 = my, y4 = my;
    int avg;
    if (sqd) {
        do {
            x1--;
            y1++;
        } while (grid [x1] [y1]);
        do {
            x2++;
            y2++;
        } while (grid [x2] [y2]);
        do {
            x3++;
            y3--;
        } while (grid [x3] [y3]);
        do {
            x4--;
            y4--;
        } while (grid [x4] [y4]);
        avg = (grid [x1] [y1] + grid [x2] [y2] + grid [x3] [y3] + grid [x4] [y4]) / 4;
        return avg;
    }
    else {
        do {
            y1++;
        } while (grid [x1] [y1]);
        do {
            x2++;
        } while (grid [x2] [y2]);
        do {
            y3--;
        } while (grid [x3] [y3]);
        do {
            x4--;
        } while (grid [x4] [y4]);
        avg = (grid [x1] [y1] + grid [x2] [y2] + grid [x3] [y3] + grid [x4] [y4]) / 4;
        return avg;
    }
}

void stdroutine (unsigned long i, unsigned long r, int h, unsigned long x, unsigned long y, int grid [] [y]) { // LADIES AND GENTLEMEN... THE DIAMOND-SQUARE ALGORITHM.
    grid [0] [0] = i + ((mt_random() % r) - (r/2));     // Set
    grid [x-1] [0] = i + ((mt_random() % r) - (r/2));   // the
    grid [0] [y-1] = i + ((mt_random() % r) - (r/2));   // four
    grid [x-1] [y-1] = i + ((mt_random() % r) - (r/2)); // corners.
    int sect = 2;                                        // This is the subdivision and iteration count of our diamond-square algorithm.
    while (x / sect != x || y / sect != y) {
        for (int n = 1; n < sect; n++) // The square algorithm: it finds a point in the middle of every square, and sets it to the mean of the four corners of the square, plus a little offset. In theory, anyway.
            for (int m = 1; m < sect; m++)
                if (grid [x * (m/sect)] [y * (n/sect)] == 0) // If it's already been given a value, just leave it.
                    grid [x * (m/sect)] [y * (n/sect)] = mean(true, (x * (m/sect)), (y * (n/sect)), x, y, grid) + ((mt_random() % (r - h)) - ((r - h)/2)); // Randomize the location's height.
        for (int n = 0; n == sect; n++)     // The diamond algorithm: it finds a point in the middle of every diamond, and it sets it to the mean of the four corners of the diamond, plus a little offset. In theory, anyway.
            for (int m = 0; m == sect; m++) {
                if (n % 2 == 0)
                    if (m % 2 == 1)
                        if (grid [x * (m/sect)] [y * (n/sect)] == 0) // Same deal here. We don't want to overwrite existing stuff.
                            grid [x * (m/sect)] [y * (n/sect)] = mean (false, (x * (m/sect)), y * (n/sect), x, y, grid) + ((mt_random() % (r - h)) - ((r - h)/2)); // Randomize the location's height.
                if (n % 2 == 1)
                    if (m % 2 == 0)
                        if (grid [x * (m/sect)] [y * (n/sect)] == 0) // Again, we only want to change positions that haven't been changed yet.
                    grid [x * (m/sect)] [y * (n/sect)] = mean (false, (x * (m/sect)), (y * (n/sect)), x, y, grid) + ((mt_random() % (r - h)) - ((r - h)/2)); // Randomize the location's height.
            }
        sect++; // Increment sect for the next iteration. I am perfectly aware that this could have been done as a for loop.
    }
    return;
}

1 Ответ

0 голосов
/ 08 марта 2012

Я немного больше думал и экспериментировал.Я не думаю, что допустимо C или C ++ объявлять параметр как int grid [] [y], если только y не является константой, известной во время компиляции.Вы можете иметь параметр как int grid[], а затем индексировать его как grid [y * ncolumns +x].Вам нужно передать указатель на методы как &grid[0][0].

Вы также можете сделать это, используя шаблон метода, который принимает размеры массива в качестве параметров шаблона.

...