有没有更简单的方法来做这个检查?

时间:2020-12-21 19:18:35

标签: c matrix random coding-style code-cleanup

我必须用随机数 01 填充矩阵,但如果一个单元格包含 1,则它周围的其他 8 个必须为 0。作为初学者,我尝试过以这种方式实现我的代码:

for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        a[i][j] = rand() % 2;
        if (a[i][j] == 1) {
            a[i-1][j-1] = 0; 
            a[i-1][j]   = 0; 
            a[i-1][j+1] = 0;
            a[i][j-1]   = 0; 
            a[i][j+1]   = 0;
            a[i+1][j+1] = 0; 
            a[i+1][j]   = 0; 
            a[i+1][j+1] = 0;
        }
    }
}

当然,我确信有一种更简单的方法来编写这段代码。你能帮助我吗?提前致谢!

6 个答案:

答案 0 :(得分:1)

您可能应该分两步完成,否则,您可以在之前擦除的单元格上再次写入 1。此外,您必须避免在矩阵之外写入。这是一个例子:

int main()
{
    // First fills the matrix :
    int a[5][5] = {0};
    printf("Random Matrix :\n");
    for (int i = 0; i < 5; i++){
        for (int j = 0; j < 5; j++){
            a[i][j] = rand() % 2;
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
    // Next filters it :
    printf("---------\nFiltered Matrix :\n");
    for (int i = 0; i < 5; i++){
        for (int j = 0; j < 5; j++){
            if (a[i][j] == 1) {
                if (i > 0) {
                    a[i-1][j]              = 0; 
                    if (j > 0) a[i-1][j-1] = 0;
                    if (j < 4) a[i-1][j+1] = 0;
                }
                if (i < 4) {
                    a[i+1][j]              = 0; 
                    if (j < 4) a[i+1][j+1] = 0;
                }
                if (j > 0) a[i][j-1] = 0; 
                if (j < 4) a[i][j+1] = 0; 
               
            }
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

输出

Random Matrix :
1 0 1 1 1 
1 0 0 1 1 
0 1 0 1 1 
0 0 0 0 0 
1 0 1 1 0 
---------
Filtered Matrix :
1 0 1 0 1 
0 0 0 0 0 
0 1 0 1 0 
0 0 0 0 0 
1 0 1 0 0 

答案 1 :(得分:1)

除了访问数组越界外,您的程序很好。这是一个更通用的方法,适用于大于 1 个单元格的范围

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

#define ROW 5
#define COL 5
#define RAN 1 // range

int main() {

    int a[ROW][COL];
    
    for (int i = 0; i < ROW; i++) {
    
        for (int j = 0; j < COL; j++) {
        
            if( (a[i][j] = rand() % 2) ) {
                
                for(int k = i-RAN; k <= i+RAN && k < ROW; k++) {
                    
                    for(int l = j-RAN; l <= j+RAN && l < COL; l++) {
                        
                        if( k >= 0 && l >= 0 && !(k == i && l == j)) {
                            
                            a[k][l] = 0;
                        }
                    }
                }
            }
        }
    }
    
    for (int i = 0; i < ROW; i++) {
    
        for (int j = 0; j < COL; j++) {
            
            printf("%d ", a[i][j]);
        }
        puts("");
    }
    
    return 0;
}

答案 2 :(得分:1)

有一种更简单的方法可以做到这一点:您需要使用曼哈顿公式。所以,代码可以是:

int distance = sqrt(pow((x1-x2),2) + pow((y1-y2),2))

其中 x1, y1 是我的单元格的坐标,x2, y2 是包含 1 的其他单元格的坐标。如果距离 < 1,您不能将单元格设置为 1。因此,您可以创建一个包含以下坐标的矩阵所有包含 1 的单元格并在将单元格设置为 1 之前对整个矩阵进行检查。

答案 3 :(得分:0)

我认为没有一种更简单或更干净的方法来完成这项工作。您的代码很清晰,并且尽可能简短。有一些替代方案具有更好的属性,例如不将 #include "./header.h" #define KEY 777 #define SIZE 50 struct message { long type; double no1, no2; char operator; char ans[SIZE]; }; int main() { struct message msg; int qid = msgget((key_t)KEY, IPC_CREAT | 0666); if (qid < 0 && errno != EEXIST) perror("Error creating queue"); else { if (msgrcv(qid, &msg, sizeof(msg) - sizeof(msg.type), 1, 0) < 0) perror("Reading error"); else { printf("%lf\n", msg.no1); int flag = 0; double ans = 0; switch (msg.operator) { case '+': ans = msg.no1 + msg.no2; break; case '-': ans = msg.no1 - msg.no2; break; case '/': ans = msg.no1 / msg.no2; break; case '*': ans = msg.no1 * msg.no2; break; default: flag = 1; snprintf(msg.ans, sizeof(msg.ans), "Invalid Operator"); break; } printf("final decision\n"); if (flag == 0) { snprintf(msg.ans, sizeof(msg.ans), "Total = %lf", ans); } printf("%s\n", msg.ans); // msg.type = 2; // if (msgsnd(qid, &msg, sizeof(msg), 0) < 0) // perror("Error to reply"); } msgctl(qid, IPC_RMID, NULL); } return 0; } 的外观偏向边缘,尤其是矩阵的右下角,但这是一个不同的标准。

正如我在评论中所写的那样,您确实需要避免超出数组的边界(这会使您的代码更复杂一些),当然也没有必要将 0 添加到您的随机数中。

您可能可以通过以某种其他方式对矩阵进行编码来巧妙做到这一点,例如在 1 数组中按位进行编码,但这不会更简单,而且可能也不干净。

解决溢出问题的一种非常简洁的方法可能是将数组声明为每个维度中两个大的元素,并对实际元素使用基于一的索引。这将为真实数据的所有方面提供一个余量,这样您的所有写入都在实际数组的范围内,即使有些超出了有意义的数据。即:

unsigned char

您将生成的实际矩阵视为仅具有 int a[7][7] = {0}; // a[1][1] ... a[5][5] will contain the real data for (int i = 1; i < 6; i++) { for (int j = 1; j < 6; j++) { a[i][j] = rand() % 2; if (a[i][j] == 1) { a[i-1][j-1] = 0; // ... } } } 1 <= i && i <= 5 的元素。那么,使用 1 <= j && j <= 5i - 1 等索引并不重要,因为这些索引对所有 j + 1i 的真实数据都有效.

答案 4 :(得分:0)

一些想法

您的代码是循环中的循环。对于 2D 数组,您可以考虑在一个循环中完成所有操作。对于小数组,即:1-5 真的没关系。对于较大的数组,如果将 i,j 计算为数组的函数,则算法会更快。 请参阅:Map a 2D array onto a 1D array

您也可以根据代码的缩进目的将变量命名为“a”、“i”、j 之类的名称,例如 row、col 或更有意义的名称。

另一部分让我有点困惑。假设你的数组是 5x5 并且假设你的最终目标是确保每个 '1' 总是有 8 零的邻居,一旦第一个随机数生成产生“1”并强制 8 个邻居为零,多达 4 个邻居不再需要更新。 (i,j+1)/(i+1,j)/(i+1,j+1)/(i-1,j)。正如@Weather Vane 所指出的,您正在覆盖您的工作,这可能是您感到“多余”的地方。

#define MAX_ARRAY 5


int in_bounds(int row,int col)
{
if (row >= MAX_ARRAY) return 0;
if (col >= MAX_ARRAY) return 0;
return 1;
}

void print_matrix (int matrix[MAX_ARRAY][MAX_ARRAY],int size)
{

for (int i=0;i<size;i++)
 {
 for (int j=0;j<size;j++)
  {
  fprintf(stdout,"%d",matrix[i][j]);
//  fprintf(stdout,"%d,%d ",i,j);
  }
 fprintf(stdout,"\n");

 }
}

int main()
{
//for stack overflow: https://stackoverflow.com/questions/65398722/is-there-a-cleaner-way-to-write-this-c-code/65399364#65399364
   srand(time(0));
    int matrix[MAX_ARRAY][MAX_ARRAY];
     memset(matrix, -1, sizeof(int) * MAX_ARRAY * MAX_ARRAY);
  
    for (int counter=0;counter<MAX_ARRAY * MAX_ARRAY;counter++)
      {
      int col=counter / MAX_ARRAY;
      int row=counter % MAX_ARRAY;

      if (matrix[row][col] == -1)
        {
        matrix[row][col] = rand() %2;
        if (matrix[row][col] == 1)
         {
            if (in_bounds(row,col+1)) matrix[row][col+1] = 0;
            if (in_bounds(row+1,col)) matrix[row+1][col] = 0;
            if (in_bounds(row+1,col+1)) matrix[row+1][col+1] = 0;
            if (in_bounds(row-1,col)) matrix[row-1][col] = 0;
            if (in_bounds(col,row-1)) matrix[col][row-1] = 0;
            if (in_bounds(row-1,col-1)) matrix[row-1][col-1] = 0;
            if (in_bounds(row-1,col+1)) matrix[row-1][col+1] = 0;
            if (in_bounds(row+1,col-1)) matrix[row+1][col-1] = 0;
        }
       }

  }
print_matrix(matrix,MAX_ARRAY);
}    

答案 5 :(得分:0)

您的代码有问题:您写入坐标范围超出 0..4 的矩阵单元格。

这是修改后的版本:

for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        a[i][j] = 0;
        if (rand() % 2) {
            for (int ii = i - 1; i <= i + 1; i++) {
                if (ii >= 0 && ii < 5) {
                    for (jj = j - 1; j <= j + 1; j++) {
                        if (jj >= 0 && jj < 5)
                            a[ii][jj] = 0;
                    }
                }
            }
            a[i][j] = 1;
        }
    }
}
相关问题