// PROGRAM sandpile // 1次元の砂山のモデル #include "TrueBASIC.h" int main(); void initial(int height[], int N[], int *L, int *IC1_, int *IC2_); void check(int height[], int L, int move[], int *unstable); void slide(int height[], int L, int move[], int IC1_); void show_distribution(int N[], int L, int grain, int IC2_); int main() { int IC1_ = 1, IC2_ = 2, grain, height[52], L, move[101], N[52], topple, unstable; GWopen(0); initial(height, N, &L, &IC1_, &IC2_); grain = 0; do { ++(height[1]); // 最初の格子点に砂粒を加える GWselvp(IC1_); GWsetogn(0, L + height[1]); GWsrect(1.1f, height[1] - 0.4f, 1.9f, height[1] + 0.4f, BLUE); topple = 0; // 崩れ落ちる砂粒の数 ++grain; // 加えられた砂粒の数 do { check(height, L, move, &unstable); if(unstable == 1) { slide(height, L, move, IC1_); ++topple; } } while(!(unstable == 0)); ++(N[topple]); show_distribution(N, L, grain, IC2_); } while(!TBkeyinput()); GWquit(); return 0; } void initial(int height[], int N[], int *L, int *IC1_, int *IC2_) { int i, topple; char Stmp1_[_LBUFF_]; GWsetogn(0, 1); GWvport(0.0f, 0.0f, 0.7f*GWaspect(1), 1.0f); GWinput("lattice size L = ", Stmp1_, _LBUFF_); sscanf(Stmp1_, "%d", L); // L = 20 としてみよ for(i = 1; i <= (*L); ++i) height[i] = 0; height[(*L) + 1] = 0; // 境界条件 GWindow(-1.0f, -2.0f, (*L)+1.0f, 40.0f); GWsetpen(BLACK, -1, -1, 4); GWline(1.0f, -0.05f, (*L)+1.0f, -0.05f); GWsavevp(*IC1_); // 配列の初期化 for(topple = 0; topple <= (*L); ++topple) N[topple] = 0; GWvport(0.72f*GWaspect(1), 0.4f, GWaspect(1), 1.0f); GWindow(-0.1f, -0.05f, (*L)+1.0f, 1.01f); GWline(0.0f, -0.01f, (*L)+0.2f, -0.01f); GWline(-0.05f, -0.01f, -0.05f, 1.0f); GWsavevp(*IC2_); GWsetogn(1, 0); } void check(int height[], int L, int move[], int *unstable) { int i; (*unstable) = 0; for(i = 1; i <= L; ++i) { if(height[i] - height[i + 1] > 1) { move[i] = 1; (*unstable) = 1; } else move[i] = 0; } } void slide(int height[], int L, int move[], int IC1_) { int i; GWselvp(IC1_); for(i = 1; i <= L; ++i) { if(move[i] == 1) { GWerase(i*L+height[i], -1); --(height[i]); // 砂粒が崩れ落ちる if(i < L) { // 次の格子点が砂粒を受けるとる ++(height[i + 1]); GWsetogn(0, (i + 1)*L+height[i + 1]); GWsrect(i + 0.1f, height[i + 1] - 0.4f, i + 0.9f, height[i + 1] + 0.4f, BLUE); } } } } void show_distribution(int N[], int L, int grain, int IC2_) { int topple; // 前の図を消去 GWselvp(IC2_); for(topple = 0; topple <= L; ++topple) { if(N[topple] > 0) { GWerase(topple+10000, -1); GWsetogn(0, topple+10000); GWsrect((float)(topple), 0.0f, (float)(topple+0.2), (float)N[topple]/(float)grain, BLACK); } } }