Galton box animation: Difference between revisions
Content added Content deleted
(Updated D entry) |
(Updated D entry) |
||
Line 405: | Line 405: | ||
enum centerH = pinsBaseW + (boxW - (pinsBaseW * 2 - 1)) / 2 - 1; |
enum centerH = pinsBaseW + (boxW - (pinsBaseW * 2 - 1)) / 2 - 1; |
||
enum Cell : char { empty = ' ', |
|||
alias CellBaseType = char; |
|||
ball = 'o', |
|||
wall = '|', |
|||
corner = '+', |
|||
floor = '-', |
|||
pin = '.' } |
|||
⚫ | |||
Cell[boxW][boxH] box; // Galton box. Will be printed upside-down. |
Cell[boxW][boxH] box; // Galton box. Will be printed upside-down. |
||
Line 418: | Line 417: | ||
int x, y; // Position. |
int x, y; // Position. |
||
this(in int x_, in int y_) nothrow |
this(in int x_, in int y_) nothrow @safe @nogc |
||
in { |
in { |
||
assert(box[y_][x_] == Cell.empty); |
assert(box[y_][x_] == Cell.empty); |
||
Line 436: | Line 435: | ||
return; // Reached the bottom of the box. |
return; // Reached the bottom of the box. |
||
with (Cell) { |
final switch (box[y - 1][x]) with (Cell) { |
||
case empty: |
|||
box[y][x] = Cell.empty; |
|||
y--; |
|||
box[y][x] = Cell.ball; |
|||
⚫ | |||
case ball, wall, corner, floor: |
|||
// It's frozen. (It always piles on other balls). |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
box[y][x] = Cell.ball; |
box[y][x] = Cell.ball; |
||
return; |
|||
} else if (box[y][x - 1] == Cell.empty) { |
|||
x++; |
|||
} else { |
|||
x--; |
|||
} |
|||
box[y][x] = Cell.ball; |
|||
break; |
|||
⚫ | |||
x += uniform(0, 2) * 2 - 1; |
|||
box[y][x] = Cell.ball; |
|||
return; |
|||
} else if (box[y][x - 1] == Cell.empty) |
|||
x++; |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} |
} |
||
} |
} |
||
Line 467: | Line 464: | ||
void initializeBox() { |
void initializeBox() { |
||
// Set ceiling and floor: |
// Set ceiling and floor: |
||
box[0][] = |
box[0][] = Cell.corner ~ [Cell.floor].replicate(boxW - 2) ~ Cell.corner; |
||
~ Cell.corner)[]; |
|||
box[$ - 1][] = box[0][]; |
box[$ - 1][] = box[0][]; |
||
// Set walls: |
// Set walls: |
||
foreach (r; 1 .. boxH - 1) |
foreach (immutable r; 1 .. boxH - 1) |
||
box[r][0] = box[r][$ - 1] = Cell.wall; |
box[r][0] = box[r][$ - 1] = Cell.wall; |
||
Line 478: | Line 474: | ||
foreach (immutable nPins; 1 .. pinsBaseW + 1) |
foreach (immutable nPins; 1 .. pinsBaseW + 1) |
||
foreach (pin; 0 .. nPins) |
foreach (pin; 0 .. nPins) |
||
box[boxH - 2 - nPins][centerH + 1 - nPins + pin * 2] |
box[boxH - 2 - nPins][centerH + 1 - nPins + pin * 2] = Cell.pin; |
||
= Cell.pin; |
|||
} |
} |
||
void drawBox() { |
void drawBox() { |
||
foreach_reverse (ref row; box) |
foreach_reverse (const ref row; box) |
||
writefln("%(%c%)", row); |
|||
} |
} |
||
Line 495: | Line 490: | ||
if (i < nMaxBalls) |
if (i < nMaxBalls) |
||
balls ~= Ball(centerH, boxH - 2); // Add ball. |
balls ~= Ball(centerH, boxH - 2); // Add ball. |
||
drawBox |
drawBox; |
||
// Next step for the simulation. |
// Next step for the simulation. |