私は、C++で柔軟なダイヤモンドスクエアテレインジェネレータを作成しています。私の地形の高さのためのタイルのグリッドは、intの巨大な配列として定義されています。今、別の関数としてこのグリッドを操作するダイヤモンドスクエアアルゴリズムがあります。stdroutine
。グリッドをグローバル変数として宣言することはできません。ユーザーがサイズを定義できるようにする必要があるからです(理由はありませんが、サイズチェックはまだ実装されていません)。 stdroutine
の内容をmain
に貼り付けたくないのは、あまり面倒なく(複数のプリセットルーチンを実行するには最終的に必要となる)複数行を連続して呼び出せるようにしたいからです。だから、stdroutine
に私の配列へのポインタを与えようとしましたが、もし私がそれを言うなら、配列が実際にどこにあるのか理解できると期待しています。 stdroutine
は実際にファンクションmean
を呼び出します。これはグリッドも機能する必要があります。ここに私のコードです(わいせつ間違っている、しかしまあ、私は良く知りません):配列へのポインタを配列intに変換する
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.
}
ダイヤモンド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には2つのルーチン、すなわちmt_init
とmt_random
が含まれており、それぞれメルセンヌ・ツイスターPRNGを初期化して実行します)。
どのようにしてグリッド・プレイをすべての関数thそれらを呼び出す時?現時点では、Xcode 4.3から4つのエラー、diamond-square.hの3つのエラー、「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;
}
あなたの平均の定義には最終的な引数として 'int ** grid [x] [y]'がありますが、平方アルゴリズムのセクションでは、グリッドを意味するために渡しません。初期設定では、角を(0,0)、(x、0)、(0、y)、(x、y)に設定します。配列は、(0,0)、(x-1,0)、(0、y-1)、(x-1、y-1)として索引付けする必要があります。 – DanS
それは良い点です。それをキャッチするためにありがとう! – mszegedy
mean()を見ると、なぜあなたは 'int ** grid [x] [y]'を渡しているのか分かりません。ポインターをポインターに渡す通常の理由は、配列のサイズを変更できることです。配列を扱っているので、すでにポインタなので、引数のサイズには何のメリットもありません。私はそれを単純化して 'int grid [] []'または 'const int grid [] []'を渡します。また、if(sqd == false){else}(sqd == true){} 'は、if(sqd){} else {}' – DanS