Checkers game : Game « J2ME « Java

Java
1. 2D Graphics GUI
2. 3D
3. Advanced Graphics
4. Ant
5. Apache Common
6. Chart
7. Collections Data Structure
8. Database SQL JDBC
9. Design Pattern
10. Development Class
11. Email
12. Event
13. File Input Output
14. Game
15. Hibernate
16. J2EE
17. J2ME
18. JDK 6
19. JSP
20. JSTL
21. Language Basics
22. Network Protocol
23. PDF RTF
24. Regular Expressions
25. Security
26. Servlets
27. Spring
28. Swing Components
29. Swing JFC
30. SWT JFace Eclipse
31. Threads
32. Tiny Application
33. Velocity
34. Web Services SOA
35. XML
Microsoft Office Word 2007 Tutorial
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Java » J2ME » GameScreenshots 
Checkers game
Checkers game

/*
Title:  J2ME Games With MIDP2
Authors:  Carol Hamer
Publisher:  Apress
ISBN:   1590593820
*/
import java.util.Vector;
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.rms.*;


import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

/**
 * This is the main class of the checkers game.
 *
 @author Carol Hamer
 */
public class Checkers extends MIDlet implements CommandListener {

  //-----------------------------------------------------
  //    game object fields

  /**
   * The canvas that the checkerboard is drawn on.
   */
  private CheckersCanvas myCanvas;

  /**
   * The class that makes the http connection.
   */
  private Communicator myCommunicator;

  //-----------------------------------------------------
  //    command fields

  /**
   * The button to exit the game.
   */
  private Command myExitCommand = new Command("Exit", Command.EXIT, 99);

  //-----------------------------------------------------
  //    initialization and game state changes

  /**
   * Initialize the canvas and the commands.
   */
  public Checkers() {
    try 
      //create the canvas and set up the commands:
      myCanvas = new CheckersCanvas(Display.getDisplay(this));
      myCanvas.addCommand(myExitCommand);
      myCanvas.setCommandListener(this);
      CheckersGame game = myCanvas.getGame();
      myCommunicator = new Communicator(this, myCanvas, game);
      game.setCommunicator(myCommunicator);
    catch(Exception e) {
      // if there's an error during creation, display it as an alert.
      errorMsg(e);
    }
  }

  //----------------------------------------------------------------
  //  implementation of MIDlet
  // these methods may be called by the application management 
  // software at any time, so we always check fields for null 
  // before calling methods on them.

  /**
   * Start the application.
   */
  public void startApp() throws MIDletStateChangeException {
    // tell the canvas to set up the game data and paint the 
    // checkerboard.
    if(myCanvas != null) {
      myCanvas.start();
    }
    // tell the communicator to start its thread and make a
    // connection.
    if(myCommunicator != null) {
      myCommunicator.start();
    }
  }
  
  /**
   * Throw out the garbage.
   */
  public void destroyApp(boolean unconditional
      throws MIDletStateChangeException {
    // tell the communicator to send the end game 
    // message to the other player and then disconnect:
    if(myCommunicator != null) {
      myCommunicator.endGame();
    }
    // throw the larger game objects in the garbage:
    myCommunicator = null;
    myCanvas = null;
    System.gc();
  }

  /**
   * Pause the game.
   * This method merely ends the game because this 
   * version of the Checkers game does not support 
   * re-entering a game that is in play.  A possible 
   * improvement to the game would be to allow 
   * a player to diconeect and leave a game and then 
   * later return to it, using some sort of session
   * token to find the correct game in progress on 
   * the server side.
   */
  public void pauseApp() {
    try {
      destroyApp(false);
      notifyDestroyed();
    catch (MIDletStateChangeException ex) {
    }
  }

  //----------------------------------------------------------------
  //  implementation of CommandListener

  /*
   * Respond to a command issued on the Canvas.
   */
  public void commandAction(Command c, Displayable s) {
    if(c == myExitCommand) {
      try {
          destroyApp(false);
          notifyDestroyed();
      catch (MIDletStateChangeException ex) {
      }
    }
  }
  
  //-------------------------------------------------------
  //  error methods

  /**
   * Converts an exception to a message and displays 
   * the message..
   */
  void errorMsg(Exception e) {
    e.printStackTrace();
    if(e.getMessage() == null) {
      errorMsg(e.getClass().getName());
    else {
      errorMsg(e.getMessage());
    }
  }

  /**
   * Displays an error message alert if something goes wrong.
   */
  void errorMsg(String msg) {
    Alert errorAlert = new Alert("error"
         msg, null, AlertType.ERROR);
    errorAlert.setCommandListener(this);
    errorAlert.setTimeout(Alert.FOREVER);
    Display.getDisplay(this).setCurrent(errorAlert);
  }

}

/**
 * This class is the display of the game.
 
 @author Carol Hamer
 */
class CheckersCanvas extends Canvas {

  //---------------------------------------------------------
  //   static fields

  /**
   * color constant
   */
  public static final int BLACK = 0;

  /**
   * color constant
   */
  public static final int WHITE = 0xffffff;

  /**
   * color constant.
   * (not quite bright red)
   */
  public static final int RED = 0xf96868;

  /**
   * color constant
   */
  public static final int GREY = 0xc6c6c6;

  /**
   * color constant
   */
  public static final int LT_GREY = 0xe5e3e3;

  /**
   * how many rows and columns the display is divided into.
   */
  public static final int GRID_WIDTH = 8;

  //---------------------------------------------------------
  //   instance fields

  /**
   * The black crown to draw on the red pieces..
   */
  private Image myBlackCrown;

  /**
   * The red crown to draw on the black pieces..
   */
  private Image myWhiteCrown;

  /**
   * a handle to the display.
   */
  private Display myDisplay;

  /**
   * a handle to the object that stores the game logic
   * and game data.
   */
  private CheckersGame myGame;

  /**
   * checkers dimension: the width of the squares of the checkerboard.
   */
  private int mySquareSize;

  /**
   * checkers dimension: the minimum width possible for the 
   * checkerboard squares.
   */
  private int myMinSquareSize = 15;

  /**
   * whether or not we're waiting for another player to join 
   * the game.
   */
  private boolean myIsWaiting;

  //-----------------------------------------------------
  //    gets / sets

  /**
   @return a handle to the class that holds the logic of the 
   * checkers game.
   */
  CheckersGame getGame() {
    return(myGame);
  }

  /**
   * Display a screen to inform the player that we're 
   * waiting for another player.
   */
  void setWaitScreen(boolean wait) {
    myIsWaiting = wait;
  }

  //-----------------------------------------------------
  //    initialization and game state changes

  /**
   * Constructor performs size calculations.
   @throws Exception if the display size is too 
   *         small to make a checkers.
   */
  CheckersCanvas(Display dthrows Exception {
    myDisplay = d;
    myGame = new CheckersGame();
    // a few calculations to make the right checkerboard 
    // for the current display.
    int width = getWidth();
    int height = getHeight();
    // get the smaller dimension fo the two possible 
    // screen dimensions in order to determine how 
    // big to make the checkerboard.
    int screenSquareWidth = height;
    if(width < height) {
      screenSquareWidth = width;
    }
    mySquareSize = screenSquareWidth / GRID_WIDTH;
    // if the display is too small to make a reasonable checkerboard, 
    // then we throw an Exception
    if(mySquareSize < myMinSquareSize) {
      throw(new Exception("Display too small"));
    }
    // initialize the crown images:
    myBlackCrown = Image.createImage("/blackCrown.png");
    myWhiteCrown = Image.createImage("/whiteCrown.png");
  }

  /**
   * This is called as soon as the application begins.
   */
  void start() {
    myDisplay.setCurrent(this);
    // prepare the game data for the first move:
    myGame.start();
  }

  //-------------------------------------------------------
  //  graphics methods

  /**
   * Repaint the checkerboard..
   */
  protected void paint(Graphics g) {
    int width = getWidth();
    int height = getHeight();
    g.setColor(WHITE);
    // clear the board (including the region around
    // the board, which can get menu stuff and other 
    // garbage painted onto it...)
    g.fillRect(00, width, height);
    // If we need to wait for another player to join the 
    // game before we can start, this displays the appropriate
    // message:
    if(myIsWaiting) {
      // perform some calculations to place the text correctly:
      Font font = g.getFont();
      int fontHeight = font.getHeight();
      int fontWidth = font.stringWidth("waiting for another player");
      g.setColor(WHITE);
      g.fillRect((width - fontWidth)/2(height - fontHeight)/2,
           fontWidth + 2, fontHeight);
      // write in black
      g.setColor(BLACK);
      g.setFont(font);
      g.drawString("waiting for another player"(width - fontWidth)/2
       (height - fontHeight)/2,
       g.TOP|g.LEFT);
      return;
    }
    // now draw the checkerboard:
    // first the dark squares:
    byte offset = 0;
    for(byte i = 0; i < 4; i++) {
      for(byte j = 0; j < 8; j++) {
  // the offset is used to handle the fact that in every 
  // other row the dark squares are shifted one place 
  // to the right.
  if(j % != 0) {
    offset = 1;
  else {
    offset = 0;
  }
  // now if this is a selected square, we draw it lighter:
  if(myGame.isSelected(i, j)) {
    g.setColor(LT_GREY);
    g.fillRect((2*i + offset)*mySquareSize, j*mySquareSize, 
           mySquareSize, mySquareSize);
  else {
    // if it's not selected, we draw it dark grey:
    g.setColor(GREY);
    g.fillRect((2*i + offset)*mySquareSize, j*mySquareSize, 
         mySquareSize, mySquareSize);
  }
  // now put the pieces in their places:
  g.setColor(RED);
  int piece = myGame.getPiece(i, j);
  int circleOffset = 2;
  int circleSize = mySquareSize - 2*circleOffset;
  if(piece < 0) {
    // color the piece in black
    g.setColor(BLACK);
    g.fillRoundRect((2*i + offset)*mySquareSize + circleOffset, 
        j*mySquareSize + circleOffset, 
       circleSize, circleSize, circleSize, circleSize);
    // if the player is a king, draw a crown on:
    if(piece < -1) {
      g.drawImage(myWhiteCrown, 
          (2*i + offset)*mySquareSize + mySquareSize/2
          j*mySquareSize + + mySquareSize/2
          Graphics.VCENTER|Graphics.HCENTER);
    }
  else if(piece > 0) {
    // color the piece in red
    g.fillRoundRect((2*i + offset)*mySquareSize + circleOffset, 
        j*mySquareSize + circleOffset, 
       circleSize, circleSize, circleSize, circleSize);
    // if the player is a king, draw a crown on:
    if(piece > 1) {
      g.drawImage(myBlackCrown, 
          (2*i + offset)*mySquareSize + mySquareSize/2
          j*mySquareSize + + mySquareSize/2
          Graphics.VCENTER|Graphics.HCENTER);
    }
  }
      }
    }
    // now the blank squares:
    // actually, this part is probably not necessary...
    g.setColor(WHITE);
    for(int i = 0; i < 4; i++) {
      for(int j = 0; j < 8; j++) {
  if(j % == 0) {
    offset = 1;
  else {
    offset = 0;
  }
  g.fillRect((2*i + offset)*mySquareSize, j*mySquareSize, 
       mySquareSize, mySquareSize);
      }
    }
    // if the player has reached the end of the game, 
    // we display the end message.
    if(myGame.getGameOver()) {
      // perform some calculations to place the text correctly:
      Font font = g.getFont();
      int fontHeight = font.getHeight();
      int fontWidth = font.stringWidth("Game Over");
      g.setColor(WHITE);
      g.fillRect((width - fontWidth)/2(height - fontHeight)/2,
           fontWidth + 2, fontHeight);
      // write in black
      g.setColor(BLACK);
      g.setFont(font);
      g.drawString("Game Over"(width - fontWidth)/2
       (height - fontHeight)/2,
       g.TOP|g.LEFT);
    }
  }

  //-------------------------------------------------------
  //  handle keystrokes

  /**
   * Move the player.
   */
  public void keyPressed(int keyCode) {  
    if(myGame.isMyTurn()) {
      int action = getGameAction(keyCode);   
      switch (action) {
      case LEFT:
  myGame.leftPressed();
  break;
      case RIGHT:
  myGame.rightPressed();
  break;
      case UP:
  myGame.upPressed();
  break;
      case DOWN:
  myGame.deselect();
  break;
      }
      repaint();
      serviceRepaints();
    }
  }

}

/**
 * This class contacts a remote server in order to 
 * play a game of checkers against an opponent..
 *
 @author Carol Hamer
 */
class Communicator extends Thread {

  //--------------------------------------------------------
  //  static fields

  /**
   * This is the URL to contact.
   * IMPORTANT: before compiling, the following URL
   * must be changed to the correct URL of the 
   * machine running the server code.
   */
  public static final String SERVER_URL 
    "socket://malbec:8007";

  /**
   * The int to signal that the game is to begin.
   */
  public static final byte START_GAME_FLAG = -4;

  /**
   * The byte to signal that the game is to end.
   */
  public static final byte END_GAME_FLAG = -3;

  /**
   * The byte to signal the end of a turn.
   */
  public static final byte END_TURN_FLAG = -2;

  //--------------------------------------------------------
  //  game instance fields

  /**
   * The MIDlet subclass, used to set the Display 
   * in the case where an error message needs to be sent..
   */
  private Checkers myCheckers;

  /**
   * The Canvas subclass, used to set the Display 
   * in the case where an error message needs to be sent..
   */
  private CheckersCanvas myCanvas;

  /**
   * The game logic class that we send the opponent's 
   * moves to..
   */
  private CheckersGame myGame;

  /**
   * Whether or not the MIDlet class has requested the 
   * game to end.
   */
  private boolean myShouldStop;

  //--------------------------------------------------------
  //  data exchange instance fields

  /**
   * The data from the local player that is to 
   * be sent to the opponent.
   */
  private byte[] myMove;

  /**
   * Whether or not the current turn is done and 
   * should be sent.
   */
  private boolean myTurnIsDone = true;

  //--------------------------------------------------------
  //  initialization

  /**
   * Constructor is used only when the program wants 
   * to spawn a data-fetching thread, not for merely 
   * reading local data with static methods.
   */
  Communicator(Checkers checkers, CheckersCanvas canvas, 
         CheckersGame game) {
    myCheckers = checkers;
    myCanvas = canvas;
    myGame = game;
  }

  //--------------------------------------------------------
  //  methods called by CheckersGame to send move
  //    information to the opponent.

  /**
   * Stop the game entirely.  Notify the servlet that 
   * the user is exiting the game.
   */
  synchronized void endGame() {
    myShouldStop = true;
    if(myGame != null) {
      myGame.setGameOver();
    }
    notify();
  }

  /**
   * This is called when the player moves a piece.
   */
  synchronized void move(byte sourceX, byte sourceY, byte destinationX, 
        byte destinationY) {
    myMove = new byte[4];
    myMove[0= sourceX;
    myMove[1= sourceY;
    myMove[2= destinationX;
    myMove[3= destinationY;
    myTurnIsDone = false;
    notify();
  }

  /**
   * This is called when the local player's turn is over.
   */
  synchronized void endTurn() {
    myTurnIsDone = true;
    notify();
  }

  //--------------------------------------------------------
  //  main communication method

  /**
   * Makes a connection to the server and sends and receives
   * information about moves.
   */
  public void run() {
    DataInputStream dis = null;
    DataOutputStream dos = null;
    SocketConnection conn = null;
    byte[] fourBytes = new byte[4];
    try {
      // tell the user that we're waiting for the other player to join:
      myCanvas.setWaitScreen(true);
      myCanvas.repaint();
      myCanvas.serviceRepaints();
      // now make the connection:
      conn = (SocketConnection)Connector.open(SERVER_URL);
      conn.setSocketOption(SocketConnection.KEEPALIVE, 1);
      dos = conn.openDataOutputStream();
      dis = conn.openDataInputStream();
      // we read four bytes to make sure the connection works...
      dis.readFully(fourBytes);
      if(fourBytes[0!= START_GAME_FLAG) {
  throw(new Exception("server-side error"));
      }
      // On this line it will block waiting for another 
      // player to join the game or make a move:
      dis.readFully(fourBytes);
      // if the server sends the start game flag again, 
      // that means that we start with the local player's turn.
      // Otherwise, we read the other player's first move from the 
      // stream:
      if(fourBytes[0!= START_GAME_FLAG) {
  // verify that the other player sent a move 
  // and not just a message ending the game...
  if(fourBytes[0== END_GAME_FLAG) {
    throw(new Exception("other player quit"));
  }
  // we move the opponent on the local screen.
  // then we read from the opponent again, 
  // in case there's a double-jump:
  while(fourBytes[0!= END_TURN_FLAG) {
    myGame.moveOpponent(fourBytes);
    dis.readFully(fourBytes);
  }
      }
      // now signal the local game that the opponent is done
      // so the board must be updated and the local player 
      // prompted to make a move:
      myGame.endOpponentTurn();
      myCanvas.setWaitScreen(false);
      myCanvas.repaint();
      myCanvas.serviceRepaints();
      // begin main game loop:
      while(! myShouldStop) {
  // now it's the local player's turn.
  // wait for the player to move a piece:
  synchronized(this) {
    wait();
  }
  // after every wait, we check if the game 
  // ended while we were waiting...
  if(myShouldStop) {
    break;
  }
  while(! myTurnIsDone) {
    // send the current move:
    if(myMove != null) {
      dos.write(myMove, 0, myMove.length);
      myMove = null;
    }
    // If the player can continue the move with a double 
    // jump, we wait for the player to do it:
    synchronized(this) {
      // make sure the turn isn't done before we start waiting
      // (the end turn notify might accidentally be called 
      // before we start waiting...)
      if(! myTurnIsDone) {
        wait();
      
    }
  }
  // after every wait, we check if the game 
  // ended while we were waiting...
  if(myShouldStop) {
    break;
  }
  // now we tell the other player the this player's 
  // turn is over:
  fourBytes[0= END_TURN_FLAG;
  dos.write(fourBytes, 0, fourBytes.length);
  // now that we've sent the move, we wait for a response:
  dis.readFully(fourBytes);
  while((fourBytes[0!= END_TURN_FLAG&& 
        (fourBytes[0!= END_GAME_FLAG&& (!myShouldStop)) {
    // we move the opponent on the local screen.
    // then we read from the opponent again, 
    // in case there's a double-jump:
    myGame.moveOpponent(fourBytes);
    dis.readFully(fourBytes);
  }
  // if the other player has left the game, we tell the 
  // local user that the game is over.
  if((fourBytes[0== END_GAME_FLAG|| (myShouldStop)) {
    endGame();
    break;
  }
  myGame.endOpponentTurn();
  myCanvas.repaint();
  myCanvas.serviceRepaints();
      // end while loop
    catch(Exception e) {
      // if there's an error, we display its messsage and 
      // end the game.
      myCheckers.errorMsg(e.getMessage());
    finally {
      // now we send the information that we're leaving the game,
      // then close up and delete everything.
      try {
  if(dos != null) {
    dos.write(END_GAME_FLAG);
    dos.close();
  }
  if(dis != null) {
    dis.close();
  }
  if(conn != null) {
    conn.close();
  }
  dis = null;
  dos = null;
  conn = null;
      catch(Exception e) {
  // if this throws, at least we made our best effort 
  // to close everything up....
      }
    }
    // one last paint job to display the "Game Over"
    myCanvas.repaint();
    myCanvas.serviceRepaints();
  }
    
}


/**
 * This class is a set of simple utility functions that 
 * can be used to convert standard data types to bytes 
 * and back again.  It is used especially for data storage, 
 * but also for sending and receiving data.
 
 @author Carol Hamer