View Single Post
  #2 (permalink)  
Old 11-08-2007, 10:26 PM
hardwired hardwired is offline
Senior Member
 
Join Date: Jul 2007
Posts: 1,022
hardwired is on a distinguished road
The basic idea is to design your graphic component class so that it can render itself (including its state) at any time. Keep your logic in another class and communicate with the graphic component to query/change its state. There are many ways to put these things together and imagination plays a big role in how you do it. Here's an example demonstrating (one way of) how to encapsulate state in the graphic component and how to communicate with it from a class that handles user input.
Code:
import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import javax.swing.*; public class BoardGame extends MouseAdapter implements ActionListener { BoardPanel board; int turn = 0; public void mousePressed(MouseEvent e) { Point p = e.getPoint(); if(board.contains(p)) { Point cell = board.getCell(p); if(board.isCellEmpty(cell)) { board.setToken(cell, turn++ % 2); // check for winner } } } public void actionPerformed(ActionEvent e) { String ac = e.getActionCommand(); if(ac.equals("RESET")) { board.clearBoard(); turn = 0; } } private JPanel getBoard() { board = new BoardPanel(); board.addMouseListener(this); return board; } private JPanel getControls() { JButton reset = new JButton("reset"); reset.setActionCommand("RESET"); reset.addActionListener(this); JPanel panel = new JPanel(); panel.add(reset); return panel; } public static void main(String[] args) { BoardGame game = new BoardGame(); JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.getContentPane().add(game.getBoard()); f.getContentPane().add(game.getControls(), "Last"); f.setSize(400,400); f.setLocation(200,200); f.setVisible(true); } } class BoardPanel extends JPanel { final int NAUGHT = 0; final int CROSS = 1; final int COLS = 3; final int ROWS = 3; final int PAD = 20; int[][] tokens = new int[ROWS][COLS]; double xInc; // cell width double yInc; // cell height BoardPanel() { clearBoard(); } public void clearBoard() { for(int j = 0; j < ROWS; j++) for(int k = 0; k < COLS; k++) tokens[j][k] = -1; repaint(); } public boolean contains(Point p) { Rectangle r = getBounds(); r.grow(-PAD, -PAD); return r.contains(p); } public Point getCell(Point p) { Point cell = new Point(); for(int j = 0; j < ROWS; j++) { double y = PAD + j*yInc; if(p.y < y + yInc) { cell.y = j; break; } } for(int j = 0; j < COLS; j++) { double x = PAD + j*xInc; if(p.x < x + xInc ) { cell.x = j; break; } } return cell; } public boolean isCellEmpty(Point p) { return tokens[p.x][p.y] == -1; } public void setToken(Point p, int token) { tokens[p.x][p.y] = token; repaint(); } protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setStroke(new BasicStroke(4f)); g2.setPaint(Color.blue); int w = getWidth(); int h = getHeight(); xInc = (double)(w - 2*PAD)/COLS; yInc = (double)(h - 2*PAD)/ROWS; // Horizontal grid lines. for(int j = 0; j <= ROWS; j++) { double y = PAD + j*yInc; g2.draw(new Line2D.Double(PAD, y, w-PAD, y)); } // Vertical grid lines. for(int j = 0; j <= COLS; j++) { double x = PAD + j*xInc; g2.draw(new Line2D.Double(x, PAD, x, h-PAD)); } // Draw tokens. g2.setPaint(Color.red); double tokenWidth = xInc*4/5; double tokenHeight = yInc*4/5; for(int j = 0; j < ROWS; j++) { for(int k = 0; k < COLS; k++) { int token = tokens[j][k]; double d = Math.min(tokenWidth, tokenHeight); double x = PAD + j*xInc + (xInc - d)/2; double y = PAD + k*yInc + (yInc - d)/2; switch(token) { case NAUGHT: g2.draw(new Ellipse2D.Double(x, y, d, d)); break; case CROSS: g2.draw(new Line2D.Double(x, y, x+d, y+d)); g2.draw(new Line2D.Double(x+d, y, x, y+d)); } } } } }
Reply With Quote