import java.awt.*; import javax.swing.*; import java.util.*; import javax.swing.event.*; public class JBrainTetris extends JTetris { private Brain brain; private Brain.Move bestMove; private int lastCount; private JCheckBox brainMode; private JCheckBox animate; private JPanel little; private JSlider adversary; private JLabel randomIndicator; JBrainTetris(int pixels) { super(pixels); brain = new DefaultBrain(); bestMove = null; lastCount = count; } /** * Overrides pickNextPiece() so that the "adversary" can select * the worst possible next piece. */ public Piece pickNextPiece() { if(random.nextInt(100) >= adversary.getValue()) { randomIndicator.setText("ok"); return super.pickNextPiece(); } randomIndicator.setText("*ok*"); return getWorstPiece(); } /** * Overrides tick(), Enables the brain to play tetris. */ public void tick(int verb) { if(brainMode.isSelected()) { board.undo(); if(lastCount != count || bestMove == null) { bestMove = brain.bestMove(board, currentPiece, HEIGHT, bestMove); lastCount = count; } if(verb == DOWN && bestMove != null) { if(bestMove.x < currentX) super.tick(LEFT); else if(bestMove.x > currentX) super.tick(RIGHT); if(!bestMove.piece.equals(currentPiece)) super.tick(ROTATE); else if(!animate.isSelected() && bestMove.x == currentX) { super.tick(DROP); super.tick(DOWN); } } } super.tick(verb); } /** Override - Adds "Brain check box and Adversary panel" Creates the panel of UI controls -- controls wired up to call methods on the JTetris. This code is very repetitive. */ public JComponent createControlPanel() { JComponent panel = super.createControlPanel(); panel.add(new JLabel("Brain:")); brainMode = new JCheckBox("Brain active"); animate = new JCheckBox("Animate fall"); animate.setSelected(true); animate.setEnabled(false); panel.add(brainMode); panel.add(animate); little = new JPanel(); little.add(new JLabel("Adversary: ")); adversary = new JSlider(0, 100, 0); adversary.setPreferredSize(new Dimension(100, 15)); little.add(adversary); panel.add(little); randomIndicator = new JLabel(""); panel.add(randomIndicator); brainMode.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { updateAnimateBox(); } }); return panel; } /** Creates a frame with a JTetris. Taken from JTetris.java */ public static void main(String[] args) { // Set GUI Look And Feel Boilerplate. // Do this incantation at the start of main() to tell Swing // to use the GUI LookAndFeel of the native platform. It's ok // to ignore the exception. try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ignored) { } JBrainTetris tetris = new JBrainTetris(16); JFrame frame = JBrainTetris.createFrame(tetris); frame.setVisible(true); } // ------------ Private Methods -------------- // /* * returns the worst possible piece given a particular board configuration */ private Piece getWorstPiece() { java.util.List<Piece> pieces = Arrays.asList(Piece.getPieces()); Brain.Move worst = brain.bestMove(board, pieces.get(0), HEIGHT, null); for(Piece piece : pieces) { if(piece.equals(worst.piece)) continue; Brain.Move working = brain.bestMove(board, piece, HEIGHT, null); if(working.score > worst.score) worst = working; } return worst.piece; } /* * enables the Animate fall check box. There's no sense in * letting the user check/un-check a box that will have no effect * when the brain is not enabled. */ private void updateAnimateBox() { if(brainMode.isSelected()) animate.setEnabled(true); else animate.setEnabled(false); } }