// Class ClickerController is the controller for this application. The idea
// is that the computer and the user alternate turns, clicking where circles
// should appear. This class constructs a single view that has a mouse
// listener. Obviously the computer doesn't actually click anywhere, so this
// class simulates random computer moves when appropriate, including a short
// delay to make it seem like the computer had to decide where to click.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import javax.swing.Timer;
public class ClickerController {
private JFrame frame; // top-level application frame
private ClickerModel model; // the model
private ClickerPanel panel; // the view
private boolean userFirst; // is the user supposed to go first?
private Random random; // used to make random computer moves
private Timer timer; // used to delay the computer move
private boolean clickOkay; // whether we are accepting user clicks
// Constructs a controller for the given model, with the second argument
// indicating whether or not the user should go first.
public ClickerController(ClickerModel model, boolean userFirst) {
this.model = model;
frame = new JFrame("CSE190L Clicker");
frame.setSize(600, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// construct the view, add it to the frame, register it with the model,
// set up its one control (a mouse listener)
panel = new ClickerPanel(model);
frame.add(panel, BorderLayout.CENTER);
model.addListener(panel);
panel.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
handleClick(e);
}
});
random = new Random();
this.userFirst = userFirst;
timer = new Timer(2000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
computerMove();
clickOkay = true;
}
});
timer.setRepeats(false);
}
// launch the program, asking the computer for a move if it is first
public void run() {
frame.setVisible(true);
if (!userFirst)
computerMove();
clickOkay = true;
}
// Handle a mouse click from the user. The user might have clicked while
// the computer was making a move. Such clicks should be ignored. We
// accomplish this by keeping a flag indicating whether user clicks are
// okay. If not, we ignore them.
private void handleClick(MouseEvent e) {
// ignore user clicks that happened while the computer was moving
if (!clickOkay)
return;
model.add(e.getPoint(), ClickerModel.Player.HUMAN);
clickOkay = false;
timer.start();
}
// Makes a random computer move, "clicking" on a random position that will
// lead to a circle that is within the bounds of the view.
private void computerMove() {
int x = ClickerPanel.RADIUS +
random.nextInt(panel.getWidth() - 2 * ClickerPanel.RADIUS);
int y = ClickerPanel.RADIUS +
random.nextInt(panel.getHeight() - 2 * ClickerPanel.RADIUS);
model.add(new Point(x, y), ClickerModel.Player.COMPUTER);
}
}