1

マトリックスについて質問があります。チェッカーの動きを計算するプログラムがあります。Java で解決しましたが、十分に高速に実行されないため、C で試してみることにしました。

問題は、Java では 2 次元行列をパラメーターとして関数に渡すことができることですが、C ではそれを行うことができません。コンパイラーは、できないと言います。私はこことウェブを掘り下げて、動的割り当てやこのようなものを見ましたが、よくわかりません。

私の問題は次のとおりです。

  • checagemこれを機能させるには、二次元行列を関数(再帰関数)に渡すにはどうすればよいですか?
  • main()ここでは 0 ループを示しているため、これは機能していますか (コード)。それがマトリックスのせいなのか、それとも何なのかはわかりません。

コードは次のとおりです。

#include <stdio.h>
#include <stdlib.h>

int checagem(int m[][100], int xo, int xd, int yd, int n) {
    int r = 0;
    if (0 <= xd && xd < n && 0 <= yd && yd < n) {
        if (yd == 0) {
            if (m[yd][xd] != 1) {
                r += 1;
            }
        } else if (m[yd][xd] == 0 || m[yd][xd] == 2) {
            r += checagem(m, xd, xd - 1, yd - 1, n);
            r += checagem(m, xd, xd + 1, yd - 1, n);
        } else if (m[yd][xd] == 1) {
            if (xo - xd > 0) {
                if (pulavel(xd - 1, yd - 1, m, n)==1) {
                    r += checagem(m, xd, xd - 1, yd - 1, n);
                }
            } else if (xo - xd < 0) {
                if (pulavel(xd + 1, yd - 1, m, n)==1) {
                    r += checagem(m, xd, xd + 1, yd - 1, n);
                }
            }
        }
    } else {
        r += 0;
    }
    return r;
}

int pulavel(int x, int y, int m[][100], int n) {
    int r = 1;
    if (x < 0 || x > n - 1 || m[y][x] == 1) {
       r=0 ;
    }
    return r;
}

int main(){
    //variaveis
    int n = 0, t = 1, x = -1, y = -1, teste = 1;
    int i,j;
    //logica
    scanf("%d %*c",&t);

    while (teste > 0) {
        scanf("%d %*c",&n);
        if (n > 1 || n <= 100) {
            int tabuleiro[n][n];
            for (i = 0; i < n; i++) {
                char l[n];
                scanf("%s %*c", &l);
                for (j = 0; j < n; j++){
                    switch(l[j]){
                    case ('.'): tabuleiro[i][j] = 0;break;
                    case ('b'): tabuleiro[i][j] = 1;break;
                    case ('w'): tabuleiro[i][j] = 2;
                                x = j;
                                y = i;break;
                    }
                }
            }
            int r = checagem(tabuleiro, x, x, y, n);
            printf("%d", r); 
        }
    }
}

入力は次のコンテストのようなものです: http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=3108

4

1 に答える 1

1

あなたの問題は、関数で宣言int tabuleiro[n][n];していることですが、関数は VLA が渡されることを期待していません。配列の前に次元を渡す必要があるため、次のように修正します。main()checagem()

int checagem(int n, int m[n][n], int xo, int xd, int yd)
{
    ...
}

次に、配列の境界をオーバーフローしないようにしてください (もちろん、C はあなたを止めないからです)。

もちろん、 に並行して変更をpulavel()加え、両方の関数の呼び出しを変更する必要があります。

これは正常にコンパイルされます。実行は試していません。配列のアドレスを取らないでください。コンパイラを混乱させなくても、混乱するでしょう(scanf("%s %*c", &l);. コードをアップグレードして、scanf()呼び出しが成功することを確認してください。で読んでいる形式はわかりscanf("%s %*c", l)ませんが、予期しないデータに損傷を与えているのではないかと思います。標準の GCC コンパイル オプションからのコンパイル警告を回避するために、関数を並べ替えて作成static(および に追加) しましvoidた。int main(void)

gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -c ck.c

コード:

#include <stdio.h>
#include <stdlib.h>

static
int pulavel(int n, int x, int y, int m[n][n])
{
    int r = 1;
    if (x < 0 || x > n - 1 || m[y][x] == 1)
       r=0;
    return r;
}

static
int checagem(int n, int m[n][n], int xo, int xd, int yd)
{
    int r = 0;
    if (0 <= xd && xd < n && 0 <= yd && yd < n) {
        if (yd == 0) {
            if (m[yd][xd] != 1) {
                r += 1;
            }
        } else if (m[yd][xd] == 0 || m[yd][xd] == 2) {
            r += checagem(n, m, xd, xd - 1, yd - 1);
            r += checagem(n, m, xd, xd + 1, yd - 1);
        } else if (m[yd][xd] == 1) {
            if (xo - xd > 0) {
                if (pulavel(n, xd - 1, yd - 1, m)==1) {
                    r += checagem(n, m, xd, xd - 1, yd - 1);
                }
            } else if (xo - xd < 0) {
                if (pulavel(n, xd + 1, yd - 1, m)==1) {
                    r += checagem(n, m, xd, xd + 1, yd - 1);
                }
            }
        }
    } else {
        r += 0;
    }
    return r;
}

int main(void)
{
    //variaveis
    int n = 0, t = 1, x = -1, y = -1, teste = 1;
    int i,j;
    //logica
    scanf("%d %*c",&t);

    while (teste > 0) {
        scanf("%d %*c",&n);
        if (n > 1 || n <= 100) {
            int tabuleiro[n][n];
            for (i = 0; i < n; i++) {
                char l[n];
                scanf("%s %*c", l);
                for (j = 0; j < n; j++){
                    switch(l[j]){
                    case ('.'): tabuleiro[i][j] = 0;break;
                    case ('b'): tabuleiro[i][j] = 1;break;
                    case ('w'): tabuleiro[i][j] = 2;
                                x = j;
                                y = i;break;
                    }
                }
            }
            int r = checagem(n, tabuleiro, x, x, y);
            printf("%d", r); 
        }
    }
}
于 2013-04-19T00:49:48.180 に答える