// C4Applet.java //So that I can view the source file in applet viewer //<Applet Code="C4Applet.class" Width=450 Height=390> </Applet> /** * * @author Sean Bridges * @version 1.0 * * */ import java.applet.*; import java.awt.*; public class C4Applet extends Applet { //------------------------------------------------------ //class variables final static String ABOUT = "Four in a row, created by Sean Bridges, www.oocities.org/sbridges.geo"; private final static String L1 = "Level 1"; private final static String L2 = "Level 2"; private final static String L3 = "Level 3"; private final static String L4 = "Level 4"; private final static String L5 = "Level 5"; private final static String L6 = "Level 6"; private final static String L7 = "Level 7"; private final static String L8 = "Level 8"; private final static String STARTING_LEVEL = L4; private final static int STARTING_DEPTH = 4; private final static String RED_PIECE_IMAGE_NAME = "redpiece.gif"; private final static String BLACK_PIECE_IMAGE_NAME = "blackpiece.gif"; private final static String BOARD_IMAGE_NAME = "board.jpg"; //------------------------------------------------ //instance variables private Button restart; private Choice levels; private ImagePanel imagePanel; private MinimaxPlayer computer; private AsynchronousPlayer human; private C4Board board; private GameMaster gameMaster; //------------------------------------------------ //instance methods public void init () { System.out.println("C4Applet initializing"); System.out.println(ABOUT); Image blackPieceImage = null; Image redPieceImage = null; Image boardImage = null; //load the images try { System.out.println("Loading images..."); blackPieceImage = this.getImage(getCodeBase(),BLACK_PIECE_IMAGE_NAME); redPieceImage = this.getImage(getCodeBase(),RED_PIECE_IMAGE_NAME); boardImage = this.getImage(getCodeBase(), BOARD_IMAGE_NAME); MediaTracker imageTracker = new MediaTracker(this); imageTracker.addImage(boardImage, 1); imageTracker.addImage(redPieceImage, 2); imageTracker.addImage(blackPieceImage, 3); imageTracker.waitForAll(); System.out.println("Images loaded"); }//end try catch (Exception e) { System.out.println("Error loading images"); e.printStackTrace(); } //if the init method is called more than once, //then remove all will remove the components that were //previously contained on the applet. //Done mainly so that the appletviewer restart works. removeAll(); //create the game human = new AsynchronousPlayer("human",C4Board.FIRST_PLAYER_NUMBER); computer = new MinimaxPlayer("computer", C4Board.SECOND_PLAYER_NUMBER, human); computer.setDepth(STARTING_DEPTH); board = new C4Board(human, computer); Player[] players = new Player[2]; players[0] = human; players[1] = computer; gameMaster = new GameMaster(board, players); //lay out the components this.setLayout(new BorderLayout()); //the control panel has the level drop down list and //the restart button Panel controlPanel = new Panel(); controlPanel.setBackground(Color.white); controlPanel.setLayout(new FlowLayout() ); restart = new Button("restart"); levels = new Choice(); levels.add(L1); levels.add(L2); levels.add(L3); levels.add(L4); levels.add(L5); levels.add(L6); levels.add(L7); levels.add(L8); levels.select(STARTING_LEVEL); controlPanel.add(restart); controlPanel.add(new Label(" Level")); controlPanel.add(levels); this.add(controlPanel, BorderLayout.SOUTH); //the image panel draws the board. imagePanel = new ImagePanel(gameMaster, board, computer, human,boardImage, redPieceImage, blackPieceImage); this.add(imagePanel, BorderLayout.CENTER); } public void start() { System.out.println("C4Applet starting"); gameMaster.startGame(); this.repaint(); } public void stop() { System.out.println("C4Applet stopping"); gameMaster.stopGame(); } public String getAppletInfo() { return ABOUT; } //---------------------------------------------- //event handling public boolean action (Event evt, Object arg) { if(arg.equals("restart")) { gameMaster.restartGame(); } else if(evt.target.equals(levels)) { if(levels.getSelectedItem() == L1) { computer.setDepth(1); } if(levels.getSelectedItem() == L2) { computer.setDepth(2); } if(levels.getSelectedItem() == L3) { computer.setDepth(3); } if(levels.getSelectedItem() == L4) { computer.setDepth(4); } if(levels.getSelectedItem() == L5) { computer.setDepth(5); } if(levels.getSelectedItem() == L6) { computer.setDepth(6); } if(levels.getSelectedItem() == L7) { computer.setDepth(7); } if(levels.getSelectedItem() == L8) { computer.setDepth(8); } } else { return super.action(evt,arg); } return true; } }//end class C4Applet class ImagePanel extends Panel implements GameEventListener { //---------------------------------------- //class variables private final static int BOARD_TOP_X = 5; private final static int BOARD_TOP_Y = 25; private final static int BOARD_WIDTH = 420; private final static int BOARD_HEIGHT = 320; private final static int COLUMN_WIDTH = 50; private final static int ROW_HEIGHT = 50; private final static int X_OFFSET = 15; private final static int Y_OFFSET = 15; private final static int TEXT_TOP_X = 80; private final static int TEXT_TOP_Y = 80; private final static Font TEXT_FONT = new Font("SansSerif", Font.BOLD, 36); private final static int TIP_DIAMETER = 20; private final static int TIP_TOP_X = 5; private final static int TIP_TOP_Y = 5; private final static int BLACK_TIP_OFFSET = 15; private final static int RED_TIP_OFFSET = 35; //---------------------------------------- //instance variables //drawing is done to a buffer offscreen so that the user doesnt see //the screen flicker private Image offscreenImage; private Graphics offscreenGraphics; Image boardImage; Image blackPieceImage; Image redPieceImage; private Move lastComputerMove; private GameMaster game; private Player computer; private AsynchronousPlayer human; private C4Board board; //the column in which the mouse is currently in, if -1, the mouse is in no column int blackColumn = -1; //---------------------------------------- //constructors ImagePanel(GameMaster aGame, C4Board aBoard, Player computer, AsynchronousPlayer human, Image boardImage, Image redPieceImage, Image blackPieceImage) { super(); this.setBackground(Color.white); this.redPieceImage = redPieceImage; this.blackPieceImage = blackPieceImage; this.boardImage = boardImage; game = aGame; board = aBoard; this.computer = computer; this.human = human; game.addListener(this); } //---------------------------------------- //instance methods public void paint(Graphics g) { g.drawImage(offscreenImage,0,0, this); } public void update() { Graphics g = this.getGraphics(); g.drawImage(offscreenImage,0,0, this); } //---------------------------------------- //mouse management /** * the mouse has moved * we want to track which column the player is in */ public boolean mouseMove(Event evt,int x, int y) { if((BOARD_TOP_X < x) & (x < (BOARD_TOP_X + BOARD_WIDTH))) { if((TIP_TOP_Y < y) & (y < (BOARD_TOP_Y + BOARD_HEIGHT))) { x = x - BOARD_TOP_X - 10; int column = x /COLUMN_WIDTH; if(column >= C4Board.NUMBER_OF_COLUMNS) { column = -1; } setBlackColumn(column); } } else { setBlackColumn(-1); } return true; } /** * Set the column where the black tip is. * If the column hasn't changed does nothing, * if the column has changed, draws the new tip, * and or clears the old, and updates the screen. */ private void setBlackColumn(int newColumn) { if(newColumn != blackColumn) { if(newColumn != -1) { drawBlackTip(newColumn); } if(blackColumn != -1) { clearBlackTip(blackColumn); } blackColumn = newColumn; update(); } } public boolean mouseDown(Event evt, int x, int y) { if(blackColumn != -1) { C4Move move = new C4Move(human, blackColumn); human.makeMove(move); } return true; } //---------------------------------------- //drawing private void resetOffScreen() { offscreenImage = createImage(this.getSize().width, this.getSize().height); offscreenGraphics = offscreenImage.getGraphics(); drawBoard(); update(); } private void drawBoard() { offscreenGraphics.drawImage(boardImage, BOARD_TOP_X,BOARD_TOP_Y,this); } /** * Draw a red tip above the given column. * Draws to offscreen, must call update to see it onscreen. */ private void drawRedTip(int column) { offscreenGraphics.setColor(Color.red); offscreenGraphics.fillOval((column * COLUMN_WIDTH) + (TIP_TOP_X + RED_TIP_OFFSET), TIP_TOP_Y, TIP_DIAMETER, TIP_DIAMETER); } /** * Draw a black tip above the given column. * Draws to offscreen, must call update to see it onscreen. */ private void drawBlackTip(int column) { offscreenGraphics.setColor(Color.black); offscreenGraphics.fillOval((column * COLUMN_WIDTH) + (TIP_TOP_X + BLACK_TIP_OFFSET), TIP_TOP_Y, TIP_DIAMETER, TIP_DIAMETER); } private void clearBlackTip(int column) { offscreenGraphics.setColor(Color.white); offscreenGraphics.fillOval((column * COLUMN_WIDTH) + (TIP_TOP_X + BLACK_TIP_OFFSET), TIP_TOP_Y, TIP_DIAMETER, TIP_DIAMETER); } private void clearRedTip(int column) { offscreenGraphics.setColor(Color.white); offscreenGraphics.fillOval((column * COLUMN_WIDTH) + (TIP_TOP_X + RED_TIP_OFFSET), TIP_TOP_Y, TIP_DIAMETER, TIP_DIAMETER); } private void drawBlackToken(int row, int column) { int xPos = BOARD_TOP_X + (column * COLUMN_WIDTH) + X_OFFSET; int yPos = BOARD_TOP_Y + ((C4Board.NUMBER_OF_ROWS - 1 - row) * ROW_HEIGHT) + Y_OFFSET; offscreenGraphics.drawImage(blackPieceImage,xPos,yPos,this); } private void drawRedToken(int row, int column) { int xPos = BOARD_TOP_X + (column * COLUMN_WIDTH) + X_OFFSET; int yPos = BOARD_TOP_Y + ((C4Board.NUMBER_OF_ROWS - 1 - row) * ROW_HEIGHT) + Y_OFFSET; offscreenGraphics.drawImage(redPieceImage,xPos,yPos,this); } //------------------------------------------------- //GameEventListener methods /** The game has started. */ public void gameStarted() { lastComputerMove = null; resetOffScreen(); } /** The game has stopped */ public void gameStoped() { if(board.isGameOver()) { offscreenGraphics.setFont(TEXT_FONT); offscreenGraphics.setColor(Color.black); if(board.getBoardStats().getScore(human) != 0) { offscreenGraphics.drawString("You win", TEXT_TOP_X, TEXT_TOP_Y); } else if(board.getBoardStats().getScore(computer) != 0) { offscreenGraphics.drawString("You lose", TEXT_TOP_X, TEXT_TOP_Y); } else { offscreenGraphics.drawString("Tie game", TEXT_TOP_X, TEXT_TOP_Y); } update(); } } /** * The game has been restarted. */ public void gameRestarted() { lastComputerMove = null; resetOffScreen(); } /** * A player has moved. */ public void moveMade(Move aMove) { int column = aMove.toInt(); int row = board.numerOfChipsInColumn(column) - 1; if(aMove.maker().getNumber() == C4Board.FIRST_PLAYER_NUMBER) { drawBlackToken(row,column); update(); } else { drawRedToken(row, column); if(lastComputerMove != null) { clearRedTip(lastComputerMove.toInt()); } drawRedTip(aMove.toInt()); lastComputerMove = aMove; update(); } } }