C语言isMagicsquare函数:函数代码中有什么逻辑错误?

时间:2019-03-02 22:29:28

标签: c arrays function for-loop

尽管当前示例的输出正确,但是我的代码似乎存在逻辑错误,在其他情况下无法提供正确的输出。

我以前已经解决了这个问题:

“如果没有重复的数字,使用了所有数字,最后一列的总和是正确的,但是倒数第二列的总和是不正确的,那么在代码中会发生什么?”

任何帮助将不胜感激。

我当前的代码:

/* Magic Square */
#include <stdio.h>

#define MAX_N 100
#define TRUE  1
#define FALSE 0

int isMagicSquare(int square[MAX_N][MAX_N], int n);

int main(void) {
    int square1[MAX_N][MAX_N] = {
            {4, 9, 2},
            {3, 5, 7},
            {8, 1, 6}};

    // should print TRUE
    int check1 = isMagicSquare(square1, 3);
    if (check1 == TRUE) {
        printf("TRUE\n");
    } else {
        printf("FALSE\n");
    }

    int square2[MAX_N][MAX_N] = {
            {20,  6,  7, 17},
            { 9, 15, 14, 12},
            {13, 11, 10, 16},
            { 8, 18, 19, 5} };

            /*{ 1 , 2 , 3 , 4 , },
            { 5 , 6 , 7 , 8 , },
            { 9 , 10, 11, 12, },
            { 13, 14, 15, 16,} };*/

            /*{16, 2, 3, 13,}, 
            {5, 11, 10, 8 ,},
            {9,  7, 6, 12 ,},
            {4, 14, 15, 1, } };*/ 

    // should print FALSE
    int check2 = isMagicSquare(square2, 4);
    if (check2 == TRUE) {
        printf("TRUE\n");
    } else {
        printf("FALSE\n");
    }

    int square3[MAX_N][MAX_N] = {
            {17, 24,  1, 15,  8},
            {23,  5,  7, 16, 14},
            { 4,  6, 13, 22, 20},
            {10, 12, 19,  3, 21}, 
            {11, 18, 25,  9,  2}};

    // should print FALSE
    int check3 = isMagicSquare(square3, 5);
    if (check3 == TRUE) {
        printf("TRUE\n");
    } else {
        printf("FALSE\n");
    }

    return 0;
}

int isMagicSquare(int square[MAX_N][MAX_N], int n) {
    int row, col;
    int drow, dcol;
    int sum, sum1, sum2, sum3;
    int boolean = 0;

    //For Diagonals
    sum = 0;
    for (row = 0; row < n; row++) {
        for (col = 0; col < n; col++) {
            if (row == col)
                sum += square[row][col];
        }
    }

    for (row = 0; row < n; row++) {
        sum3 = 0;
        for (col = 0; col < n; col++) {
            sum3 += square[n-row-1][col]; 
        }
        if (sum == sum3)
            boolean = 1;
        else {
            return FALSE;
        }
    }

    //For Rows
    for (row = 0; row < n; row++) {
        sum1 = 0;
        for (col = 0; col < n; col++) {
            sum1 = sum1 + square[row][col];
        }
        if (sum == sum1)
            boolean = 1;
        else {
            return FALSE;
        }
    }

    //For Columns
    for (row = 0; row < n; row++) {
        sum2 = 0;
        for (col = 0; col < n; col++) {
            sum2 = sum2 + square[col][row];
        }
        if (sum == sum2)
            boolean = 1;
        else {
            return FALSE;
        }
    }

    if (boolean == 1) {
        //Check if All Numbers is used

        for (row = 0; row < n; row++) {
            for (col = 0; col < n; col++) {
                if(square[row][col] > n*n || square[row][col] < 0) {
                    boolean = 0;
                    break;
                }
            }
        }

        //Check for Repeating Numbers
        for (row = 0; row < n; row++) {
            for(col = 0; col < n; col++) {

                for(drow = row + 1; drow < n; drow++){
                    for(dcol = col + 1; dcol < n; dcol++) {
                        if(square[row][col] == square[drow][dcol]) {
                            boolean = 0;
                            break;
                        }
                    }   
                }
            }
        }
        // if Statement End
    }
    else {
        boolean = 0;
    }

    if (boolean == 1)
        return TRUE;
    else
        return FALSE;
}

2 个答案:

答案 0 :(得分:3)

在计算循环中似乎将sum3 var重新初始化为0,加上对角和相等检查应在循环外部。

我会这样修改:

//For Diagonals
sum = 0;
sum3 = 0;
for (row = 0; row < n; row++) {
    sum  += square[row][row];
    sum3 += square[row][n - 1 - row];
}
if (sum == sum3)
    boolean = 1;
else {
    return FALSE;
}

顺便说一句,由于对角线是线性的,因此我简化了对角线计算,不需要两个嵌套循环。

我在最终检查中发现了一些其他错误:

-0不应为有效值

-返回而不是仅仅中断(break仅存在于内部循环中,外部循环继续)

for (row = 0; row < n; row++) {
    for (col = 0; col < n; col++) {
        if(square[row][col] > n*n || square[row][col] <= 0) {
            return FALSE;
        }
    }
}

//Check for Repeating Numbers
int storedNumbers[n * n];
for (row = 0; row < n; row++) {
    for(col = 0; col < n; col++) {
        storedNumbers[row + n * col] = square[row][col];
    }
}

然后扫描storedNumbers以查找重复项。 Searching for duplicate values in an array

欢呼

答案 1 :(得分:1)

您可以使用更紧凑的方案来检查所有数字1 .. (n*n)是否使用重复的代码,例如:

int counts[n * n];  // Can't use an initializer with a VLA
memset(counts, '\0', sizeof(counts));

for (int i = 0; i < n; i++)
{
    for (int j = 0; j < n; j++)
    {
        if (square[i][j] <= 0 || square[i][j] > n * n)
            return FALSE;
        counts[square[i][j] - 1]++;  // Map 1..n*n to 0..n*n-1
        // if (++counts[square[i][j] - 1] > 1)
        //     return FALSE;
    }
}

for (int i = 0; i < n * n; i++)
{
    if (counts[i] != 1)
        return FALSE;
}

由于要检查n*n个元素,因此此代码使用的空间和时间相对于幻方中的元素数量是线性的,且在最佳常数因子之内。