package com.horstmann.flip; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.Timer; import edu.lhup.ai.IPiece; import edu.lhup.ai.IPlayer; public class FlipPanel extends JComponent { public FlipPanel(FlipBoard board, IPlayer player) { this.board = board; this.player = player; int h = playerRow() / 2; images[0][h] = new ImageIcon(getClass().getResource("eye.png")); images[0][1 - h] = new ImageIcon(getClass().getResource("hal.png")); for (int i = 1; i <= 6; i++) for (int j = 0; j < 2; j++) images[i][j] = new ImageIcon(getClass().getResource("gnome-dice-" + i + (j == 0 ? "" : "-gray") + ".png")); IPiece[][] pieces = board.getBoard(); for (int i = 0; i < pieces.length; i++) for (int j = 0; j < pieces[i].length; j++) { Visual visual = new Visual(); visual.dx = (int)(10 * Math.random()); visual.dy = (int)(10 * Math.random()); visual.x = j + (i % 2 == 0 ? 0 : pieces[i - 1].length); visual.y = i / 2; visuals.put(pieces[i][j], visual); } setPreferredSize(new Dimension(600, 500)); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent event) { if (!waitingForInput) return; Die die = (Die) findPiece(event.getPoint()); if (die == null) return; Visual visual = visuals.get(die); if (visual.gray && visual.y == playerRow()) return; // can't flip an unflippable if (visual.y == 1) { if (visual.gray) return; visual.gray = true; move += die; repaint(); } else { move += (visual.y == playerRow() ? "f" : "p" ) + die; setInputString(move); move = ""; } } }); } private int playerRow() { return board.getPlayers()[0] == player ? 0 : 2; } private IPiece findPiece(Point p) { for (IPiece piece : visuals.keySet()) if (getBounds(piece).contains(p)) return piece; return null; } public void updateBoard() { IPiece[][] pieces = board.getBoard(); int maxlength = 0; for (int i = 0; i < pieces.length; i++) maxlength += pieces[i].length; boolean[][] occupied = new boolean[3][maxlength]; List movedPieces = new ArrayList(); for (int i = 0; i < pieces.length; i++) for (int j = 0; j < pieces[i].length; j++) { Visual visual = visuals.get(pieces[i][j]); int y = i / 2; if (y == visual.y) // piece has not moved { occupied[y][visual.x] = true; } else { visual.y = y; // remember desired y movedPieces.add(pieces[i][j]); } visual.gray = i % 2 == 1; } for (IPiece piece : movedPieces) { Visual visual = visuals.get(piece); int x = 0; while (occupied[visual.y][x]) x++; visual.x = x; occupied[visual.y][x] = true; } repaint(); } public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; int count = 0; IPiece[][] pieces = board.getBoard(); for (int i = 0; i < pieces.length; i++) for (int j = 0; j < pieces[i].length; j++) { IPiece piece = pieces[i][j]; Visual visual = visuals.get(piece); g2.drawImage(getImage(piece), 100 + visual.x * 100 + visual.dx, visual.y * 100 + visual.dy, null); count++; } for (int h = 0; h < 2; h++) g2.drawImage(images[0][h].getImage(), 10, 10 + 200 * h, null); } private Image getImage(IPiece piece) { Visual visual = visuals.get(piece); return images[((Die) piece).getValue()][visual.gray ? 1 : 0].getImage(); } private Rectangle getBounds(IPiece piece) { Visual visual = visuals.get(piece); Image image = getImage(piece); return new Rectangle(100 + visual.x * 100 + visual.dx, visual.y * 100 + visual.dy, image.getWidth(null), image.getHeight(null)); } public synchronized void setWaitingForInput(boolean waitingForInput) { this.waitingForInput = waitingForInput; move = ""; inputString = null; } public synchronized String getInputString() throws InterruptedException { setWaitingForInput(true); while (inputString == null) wait(); return inputString; } public synchronized void setInputString(String inputString) { this.inputString = inputString; notifyAll(); } private FlipBoard board; private IPlayer player; private Map visuals = new HashMap(); private ImageIcon[][] images = new ImageIcon[7][2]; private boolean waitingForInput; private String move = ""; private String inputString; private static class Visual { public int x; public int y; public int dx; public int dy; public boolean gray; public String toString() { return "(x=" + x + ",y=" + y + (gray ? "*" : "") + ")"; } } }