move a ball one after another

2019-09-17 14:44发布

问题:

I am writing a code of game bean machine(Galton box), its mechanism that one ball fall and move randomly until it get to one of the slots (randomly) and then another ball comes doing the same thing and so on, the problem is that all balls fall at the same time which something I do not want, I want each ball to fall when the current one finishes its travel..can anyone helps me ! Thanks..

here is the code:

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;
import java.util.Scanner;
import java.lang.Iterable;

import javax.swing.*;


public class BallPanel extends JPanel  {

int x=1, y=1;
Collection <Ball> ball;
public static void main(String [] args){
      // create the list
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
    JFrame frame= new JFrame("Bean game");
    frame.add(new BallPanel());
    frame.setSize(300,500);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
        }
    });    
}

public BallPanel() {

    JPanel panel = new JPanel();
    ball=new ArrayList<>(); 
    for(int i=1;i<=4;i++){
        ball.add(new Ball(x,y));
        x++;
        y++;
    }
     Timer timer = new Timer(400, new ActionListener()
    { 
        public void actionPerformed(ActionEvent e) {
            for (Ball b: ball) {
                  b.move();repaint();
            }

        }
    });
      timer.start();
}

protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int raduis=10;
    int  i=0;
    int width=(getWidth()/8);
    int space=(getWidth()-8*30)/2;
    g.setColor(Color.BLACK);
    for(i=0;i<=8;i++){
        g.drawLine(space+(30*i),getHeight()-5*(raduis) ,space+(30*i) ,getHeight() );
        if(i!=0 && i!=8)
            g.fillOval(space+(30*i)-5, getHeight()-5*(raduis)-5, 10, 10);
        if(i==0){
            g.drawLine(space,getHeight()-5*(raduis) , space+((8)*15)-(raduis/2)-15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2);
            g.drawLine(space+((8)*15)-(raduis/2)-15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 , space+((8)*15)-(raduis/2)-15 , getHeight()/2-8*8);//vertical line

        }
        if(i==8){
            g.drawLine(space+(30*i), getHeight()-5*(raduis), space+((8)*15)+(raduis/2)+15, getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2);
            g.drawLine(space+((8)*15)+(raduis/2)+15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 , space+((8)*15)+(raduis/2)+15 , getHeight()/2-8*8);//vertical line

        }

    }


    int o=1;
    for(i=1;i<=8-2;i++){
        int k=2;
        for(int j=i;j<=8-2;j++){
            g.fillOval(space+((i+k)*15)-raduis/2, getHeight()-(5*raduis)-(30*o)-raduis/2, raduis, raduis); 
            k=k+2;   
         }o++;
    }
    for (Ball b : ball) {
         b.draw(g);
    }
}
public class Ball {
    Random rand=new Random();
    private int n;
    private int raduis = 10;
    private int moveRaduis=12;
    private int L = 0;
    private int R = 0;
    private int D = 0;
    int x, y; 

    public Ball(int x, int y){
        this.x=x;
        this.y=y;
    }  

    public void draw(Graphics g) {
        g.setColor(Color.RED);
        g.fillOval(getWidth()/2 -raduis/2  + R + L, 0 + D , moveRaduis, moveRaduis);

    }
    public void move() {
        n=1+rand.nextInt(100);
        if(n<=51){
            D+=15;

            if(D<=(getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2))
                L=0;
            else if(D>getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 && D<getHeight()-5*(raduis))
            {
                D+=15;
                L-=15;

            }
            else if(D>=getHeight()-5*(raduis))
            {
                if(D==31*15)D-=15;
                D=D;

            }

        }
        else if (n>=51 && n<=100){
            D+=15;
            if(D<=getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2)
                R=0;
            else if(D>getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 && D<getHeight()-5*(raduis))
                {
                D+=15;
                R+=15;
            }
            else if(D>=getHeight()-5*(raduis)){
                if(D==31*15)D-=15;
                D=D;

            }

        }

    }
}
}

回答1:

So, your movement code moves all the balls on each iteration, what you need to do is have an "active" ball, for example...

private Ball activeBall;

Timer timer = new Timer(400, new ActionListener() { 
    public void actionPerformed(ActionEvent e) {
        if (activeBall != null && activeBall.hasCompleted()) {
            activeBall = null;
        }
        if (activeBall == null && ball.size() > 0) {
            activeBall = ball.remove(0);
        }
        if (activeBall != null) {
            activeBall.move();
            repaint();
        }
    }
});

You'll need to add in some kind of check to determine the ball has completed it's run though