C语言粒子模拟代码优化:消除嵌套if-else与提升扩展性
C语言粒子表面相互作用模拟代码优化方案
问题背景
使用C语言模拟两种粒子在方形表面的相互作用,模拟流程为:
- 从空表面随机选择一个位点
- 生成随机数r,若r小于阈值Y则选择粒子#1,否则选择粒子#2
- 若选择粒子#1,检查四个近邻,任一近邻为粒子#2则反应生成粒子#3,否则粒子#1吸附
- 粒子#2逻辑类似,检测近邻是否存在粒子#1
现有代码存在大量嵌套if-else,维护调试难度高,后续需扩展更多粒子类型及交互逻辑,需进行代码精简优化。
核心优化方向
1. 用数组封装邻居偏移量,消除重复代码
将四个方向的邻居偏移量存入数组,通过循环统一计算邻居坐标,替代原有的rightneighbor/leftneighbor等重复函数,减少冗余代码。
2. 抽象粒子交互规则,用结构体映射逻辑
定义结构体存储粒子类型、反应目标、计数器等信息,新增粒子时只需扩展结构体数组,无需修改核心执行逻辑。
3. 简化随机选择逻辑,避免多层嵌套
通过随机数直接索引邻居数组,替代原有的多个if-else判断分支,简化代码结构。
4. 修复原代码bug
原代码中粒子#2吸附时错误累加particle1计数,已修正为particle2。
优化后的完整代码
#include <stdio.h> #include <stdlib.h> #include <time.h> // 网格尺寸定义 #define MAX_X 5 #define MAX_Y 5 #define TOTAL_CELLS (MAX_X * MAX_Y) // 粒子1选择阈值 #define Y 0.55 // 粒子状态枚举 typedef enum { S_EMPTY, P1_OCCUPIED, P2_OCCUPIED, P3_OCCUPIED // 补充粒子3的状态定义 } gstate; // 邻居方向偏移量:右、左、上、下 typedef struct { int dx; int dy; } NeighborOffset; const NeighborOffset neighbor_offsets[] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}}; #define NEIGHBOR_COUNT (sizeof(neighbor_offsets)/sizeof(neighbor_offsets[0])) // 粒子交互规则结构体 typedef struct { gstate self_type; // 当前粒子类型 gstate react_target; // 触发反应的目标粒子类型 int* self_counter; // 当前粒子计数器 int* product_counter; // 反应产物计数器 } ParticleRule; // 生成网格内随机坐标 void generate_coords(int* x, int* y) { *x = rand() % MAX_X; *y = rand() % MAX_Y; } // 初始化网格为空 void grid_init(gstate grid[MAX_Y][MAX_X]) { for (int y = 0; y < MAX_Y; y++) { for (int x = 0; x < MAX_X; x++) { grid[y][x] = S_EMPTY; } } } // 计算周期性边界下的坐标 int wrap_coord(int coord, int max) { if (coord < 0) return coord + max; if (coord >= max) return coord - max; return coord; } // 获取指定方向的邻居坐标及状态 gstate get_neighbor_state(gstate grid[MAX_Y][MAX_X], int x, int y, int offset_idx) { int nx = wrap_coord(x + neighbor_offsets[offset_idx].dx, MAX_X); int ny = wrap_coord(y + neighbor_offsets[offset_idx].dy, MAX_Y); return grid[ny][nx]; } // 更新邻居坐标(用于调试打印) void get_neighbor_coord(int x, int y, int offset_idx, int* nx, int* ny) { *nx = wrap_coord(x + neighbor_offsets[offset_idx].dx, MAX_X); *ny = wrap_coord(y + neighbor_offsets[offset_idx].dy, MAX_Y); } int main() { srand((unsigned)time(0)); gstate grid[MAX_Y][MAX_X]; grid_init(grid); int particle1 = 0, particle2 = 0, particle3 = 0; int avail_cells = TOTAL_CELLS; int rounds = 0; // 定义粒子交互规则 ParticleRule p1_rule = {P1_OCCUPIED, P2_OCCUPIED, &particle1, &particle3}; ParticleRule p2_rule = {P2_OCCUPIED, P1_OCCUPIED, &particle2, &particle3}; while (rounds < TOTAL_CELLS) { int x, y; generate_coords(&x, &y); if (grid[y][x] != S_EMPTY) { rounds++; continue; } // 选择粒子类型 double r = (double)rand() / RAND_MAX; printf("r = %.4lf\n", r); ParticleRule* rule = (r <= Y) ? &p1_rule : &p2_rule; printf("选择粒子%s (r = %.4lf %s Y = %.2lf)\n", rule == &p1_rule ? "#1" : "#2", r, rule == &p1_rule ? "<=" : ">", Y); // 随机选择一个邻居方向 int neighbor_idx = rand() % NEIGHBOR_COUNT; int nx, ny; get_neighbor_coord(x, y, neighbor_idx, &nx, &ny); const char* dir_names[] = {"右", "左", "上", "下"}; printf("选择%s邻居: (%d,%d)\n", dir_names[neighbor_idx], ny, nx); // 检查邻居状态并执行交互 gstate neighbor_state = get_neighbor_state(grid, x, y, neighbor_idx); if (neighbor_state == rule->react_target) { // 发生反应:清空邻居位点,产物计数+1 grid[ny][nx] = S_EMPTY; (*rule->product_counter)++; avail_cells++; } else { // 吸附当前粒子 grid[y][x] = rule->self_type; (*rule->self_counter)++; avail_cells--; } rounds++; } // 输出结果 printf("\n模拟结束,共执行%d轮\n", rounds); printf("粒子#1数量: %d\n", particle1); printf("粒子#2数量: %d\n", particle2); printf("粒子#3数量: %d\n", particle3); printf("可用位点数量: %d\n", avail_cells); printf("已占用位点数量: %d\n", TOTAL_CELLS - avail_cells); return 0; }
优化后优势
- 可扩展性:新增粒子类型时,只需添加对应的
ParticleRule结构体和状态枚举,核心逻辑无需修改 - 可读性:消除多层嵌套,代码结构清晰,交互逻辑集中在规则结构体中
- 可维护性:重复逻辑统一封装,减少代码冗余,调试时只需关注核心规则和坐标计算
内容的提问来源于stack exchange,提问作者Auyk
相关产品推荐
相关产品推荐

