132 lines
4.1 KiB
Java
132 lines
4.1 KiB
Java
import java.util.Random;
|
|
import java.util.List;
|
|
import java.util.ArrayList;
|
|
|
|
public class GaltonBox {
|
|
public static void main( final String[] args ) {
|
|
new GaltonBox( 8, 200 ).run();
|
|
}
|
|
|
|
private final int m_pinRows;
|
|
private final int m_startRow;
|
|
private final Position[] m_balls;
|
|
private final Random m_random = new Random();
|
|
|
|
public GaltonBox( final int pinRows, final int ballCount ) {
|
|
m_pinRows = pinRows;
|
|
m_startRow = pinRows + 1;
|
|
m_balls = new Position[ ballCount ];
|
|
|
|
for ( int ball = 0; ball < ballCount; ball++ )
|
|
m_balls[ ball ] = new Position( m_startRow, 0, 'o' );
|
|
}
|
|
|
|
private static class Position {
|
|
int m_row;
|
|
int m_col;
|
|
char m_char;
|
|
|
|
Position( final int row, final int col, final char ch ) {
|
|
m_row = row;
|
|
m_col = col;
|
|
m_char = ch;
|
|
}
|
|
}
|
|
|
|
public void run() {
|
|
for ( int ballsInPlay = m_balls.length; ballsInPlay > 0; ) {
|
|
ballsInPlay = dropBalls();
|
|
print();
|
|
}
|
|
}
|
|
|
|
private int dropBalls() {
|
|
int ballsInPlay = 0;
|
|
int ballToStart = -1;
|
|
|
|
// Pick a ball to start dropping
|
|
for ( int ball = 0; ball < m_balls.length; ball++ )
|
|
if ( m_balls[ ball ].m_row == m_startRow )
|
|
ballToStart = ball;
|
|
|
|
// Drop balls that are already in play
|
|
for ( int ball = 0; ball < m_balls.length; ball++ )
|
|
if ( ball == ballToStart ) {
|
|
m_balls[ ball ].m_row = m_pinRows;
|
|
ballsInPlay++;
|
|
}
|
|
else if ( m_balls[ ball ].m_row > 0 && m_balls[ ball ].m_row != m_startRow ) {
|
|
m_balls[ ball ].m_row -= 1;
|
|
m_balls[ ball ].m_col += m_random.nextInt( 2 );
|
|
if ( 0 != m_balls[ ball ].m_row )
|
|
ballsInPlay++;
|
|
}
|
|
|
|
return ballsInPlay;
|
|
}
|
|
|
|
private void print() {
|
|
for ( int row = m_startRow; row --> 1; ) {
|
|
for ( int ball = 0; ball < m_balls.length; ball++ )
|
|
if ( m_balls[ ball ].m_row == row )
|
|
printBall( m_balls[ ball ] );
|
|
System.out.println();
|
|
printPins( row );
|
|
}
|
|
printCollectors();
|
|
System.out.println();
|
|
}
|
|
|
|
private static void printBall( final Position pos ) {
|
|
for ( int col = pos.m_row + 1; col --> 0; )
|
|
System.out.print( ' ' );
|
|
for ( int col = 0; col < pos.m_col; col++ )
|
|
System.out.print( " " );
|
|
System.out.print( pos.m_char );
|
|
}
|
|
|
|
private void printPins( final int row ) {
|
|
for ( int col = row + 1; col --> 0; )
|
|
System.out.print( ' ' );
|
|
for ( int col = m_startRow - row; col --> 0; )
|
|
System.out.print( ". " );
|
|
System.out.println();
|
|
}
|
|
|
|
private void printCollectors() {
|
|
final List<List<Position>> collectors = new ArrayList<List<Position>>();
|
|
|
|
for ( int col = 0; col < m_startRow; col++ ) {
|
|
final List<Position> collector = new ArrayList<Position>();
|
|
|
|
collectors.add( collector );
|
|
for ( int ball = 0; ball < m_balls.length; ball++ )
|
|
if ( m_balls[ ball ].m_row == 0 && m_balls[ ball ].m_col == col )
|
|
collector.add( m_balls[ ball ] );
|
|
}
|
|
|
|
for ( int row = 0, rows = longest( collectors ); row < rows; row++ ) {
|
|
for ( int col = 0; col < m_startRow; col++ ) {
|
|
final List<Position> collector = collectors.get( col );
|
|
final int pos = row + collector.size() - rows;
|
|
|
|
System.out.print( '|' );
|
|
if ( pos >= 0 )
|
|
System.out.print( collector.get( pos ).m_char );
|
|
else
|
|
System.out.print( ' ' );
|
|
}
|
|
System.out.println( '|' );
|
|
}
|
|
}
|
|
|
|
private static final int longest( final List<List<Position>> collectors ) {
|
|
int result = 0;
|
|
|
|
for ( final List<Position> collector : collectors )
|
|
result = Math.max( collector.size(), result );
|
|
|
|
return result;
|
|
}
|
|
}
|