1

私は、効率性とパターン マッチングの機能に重点を置いてライフ ゲームを実装しようとしています。パターンはウインカー、グライダー、クロスなどです。

世界の 1D 配列と、幅と高さがあります。ムーア近傍のインデックスを計算したい隣人を見つけるために、これらがハッシュであるかどうかを確認し、ハッシュである場合は get_neighbours 関数の戻り変数を増やします。北と南は機能しているように見えますが、東と西は機能していません。NE、SE、SW、NW はすべて、以前のロジックに基づいています (つまり、西に北に行く)。

int get_neighbours(int loc) {
    int neighbours = 0;

    int n = mod(loc - grid_width, total);
    int e = mod(loc + 1, grid_width) + grid_width;
    int s = mod(loc + grid_width, total);
    int w = mod(loc - 1, grid_width) + grid_width;
    int nw = mod(w - grid_width, total);
    int ne = mod(e - grid_width, total);
    int se = mod(e + grid_width, total);
    int sw = mod(w + grid_width, total);

    //Northwest
    if (grid[nw] == '#') {
        neighbours++;
    }
    //North
    if (grid[n] == '#') {
        neighbours++;
    }
    //Northeast
    if (grid[ne] == '#') {
        neighbours++;
    }
    //East
    if (grid[e] == '#') {
        neighbours++;
    }
    //Southeast
    if (grid[se] == '#') {
        neighbours++;
    }
    //South
    if (grid[s] == '#') {
        neighbours++;
    }
    //Southwest
    if (grid[sw] == '#') {
        neighbours++;
    }
    //West
    if (grid[w] == '#') {
        neighbours++;
    }
    return neighbours;
}

int mod(int a, int b) {
    int ret = a % b;
    if (b < 0) {
        return mod(-a, -b);
    }
    else if (ret < 0) {
        ret += b;
    }
    return ret;
}

パターン マッチングでは、5x5 サブアレイを構築するために上記と同じロジックを使用しようとしました。これは基本的に「読み取りヘッド」を使用します。これは、指定された場所から東に 5 スペース移動するまで世界を進みます。次に、元の位置に戻り、適切な行数だけ南に移動してから、再び東に移動し、25 個のインデックスが収集されるまで続けます。

char *get_subarray(int loc) {
    char *subarray;
    subarray = malloc(sizeof(char) * 25);

    int i = 0;
    int ptr = loc;

    while (i < 25) {
        subarray[i] = grid[ptr];
        if ((i + 1) % 5 == 0) {
            //return the read head to the original location, then travel south through the grid once for each of the times we have traversed a row
            ptr = loc;
            for (int k = 0; k <= (i / 5); k++) {
                ptr = mod(ptr + grid_width, total);
            }
        } else {
            ptr = mod(ptr + 1, grid_width) + grid_width;
        }
        i++;
    }
    subarray[i] = '\0';
    return subarray;

}

そうすることで、世界から部分配列を構築し、パターンの文字列に対してこれを strcmp() できます。

int cpu_get_crosses() {
    int crosses = 0;

    for (int i = 0; i < total; i++) {
        if (strcmp(get_subarray(i), "       #   # #   #       ") == 0) {
            crosses++;
        }
    }
    return crosses;
}

参考までに、インデックス付きの 7x5 グリッド (境界付き):

34|28 29 30 31 32 33 34|28
--|--------------------|--
6 |0  1  2  3  4  5  6 |0
13|7  8  9  10 11 12 13|7 
20|14 15 16 17 18 19 20|14
27|21 22 23 24 25 26 27|21
34|28 29 30 31 32 33 34|28
--|--------------------|--
6 |0  1  2  3  4  5  6 |0

境界条件を維持しながらムーア近傍のインデックスを計算できるロジックを知りたいので、近傍とサブアレイを正しく計算できます (これらは両方とも同じロジックを使用するため)。

EDIT: Googlerが必要な場合はサブアレイ関数。

char *get_subarray(int loc) {
    char *subarray;
    subarray = malloc(sizeof(char) * 25); //5x5 (=25) subarray

    int i = 0;
    int row = loc / grid_width;
    int ptr = loc;

    while (i < 25) {
        subarray[i] = grid[ptr];
        if ((i + 1) % 5 == 0) {
            //return the read head to the original location, then travel south through the grid once for each of the times we have traversed a row
            ptr = loc;
            for (int k = 0; k <= (i / 5); k++) {
                ptr = mod(ptr + grid_width, total);
            }
            row = ptr / grid_width;
        } else {
            ptr = mod(ptr + 1, grid_width) + row * grid_width;
        }
        i++;
    }
    subarray[i] = '\0';
    return subarray;
}
4

1 に答える 1