⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bluegammon.java

📁 --- --- --- 基于J2ME的游戏程序--------很有技巧性的程序
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
// Copyright (c) 2005 Sony Ericsson Mobile Communications AB
//
// This software is provided "AS IS," without a warranty of any kind. 
// ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 
// INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 
// PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 
//
// THIS SOFTWARE IS COMPLEMENTARY OF JAYWAY AB (www.jayway.se)

package bluegammon;

import bluegammon.gui.MenuCanvas;
import bluegammon.gui.PopupCanvas;
import bluegammon.gui.StringInputHandler;
import bluegammon.gui.popup.Popup;
import bluegammon.gui.popup.PopupListener;
import bluegammon.io.BackgammonConnection;
import bluegammon.io.Handshake;
import bluegammon.io.PlayerListenerProxy;
import bluegammon.logic.BoardMediator;
import bluegammon.logic.GameRecord;
import bluegammon.logic.LocalPlayer;
import bluegammon.logic.Player;
import bluegammon.logic.RemotePlayer;
import bluegammon.logic.Rules;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;

/**
 * <p>
 * The <code>Bluegammon</code> class represents the Bluegammon MIDlet
 * game altogether. It coordinates the macro state of the application.
 * </p><p>
 * This class collects common functionality as starting and stopping a
 * backgammon game, showing a popup, or getting string input from user. It is
 * invoked statically since it mainly is a mediator.
 * </p>
 *  
 * @author Peter Andersson
 */
public class Bluegammon implements PopupListener, CommandListener
{
  /** Current canvas that is displayed */
  protected static PopupCanvas m_currentCanvas;
  /** Current listener to popups */
  protected static PopupListener m_popupListener;
  /** Popup instance cache */
  protected static Popup m_popupCache;
  /** Text box used for collecting user string input */
  protected static TextBox m_textBox;
  /** Handler when user has entered string input */
  protected static StringInputHandler m_inputHandler;
  /** The connection used in remote games */
  protected static BackgammonConnection m_remoteConnection;
  /** Instance of this class, used as PopupListener or CommandListener */
  protected static Bluegammon m_inst;
	
  /** Key for device id (int)*/
  public static final int	DEVICE_ID				= 0;
  /** Key for player name (char[])*/
  public static final int	PLAYER_NAME				= 1;
  /** Key for saved game boolean flag (boolean)*/
  public static final int	HAS_SAVED_LOCAL_GAME	= 2;
  /** Key for saved game data (byte[])*/
  public static final int	SAVED_GAME_DATA			= 3;
  /** Key for preferred color (boolean)*/
  public static final int	BLACK_PREFERRED			= 4;
  /** Key for audio off (boolean)*/	// Negative flag because default boolean = false
  public static final int	AUDIO_OFF				= 5;
  /** Key for vibration off (boolean)*/
  public static final int	VIBRA_OFF				= 6;
  /** Key for preferred rules (int)*/
  public static final int   RULES_PREFERRED         = 7;
  
  /** Max number of opponent scores that can be persistent */
  public static final int GAMERECORDS_SIZE = 16;
  /** First key in gamerecords, device ids (int) */
  public static final int GAMEREC_OP_ID			    = 8;
  /** First key in gamerecords, opponent name (char[]) */
  public static final int GAMEREC_OP_NAME			= GAMEREC_OP_ID + GAMERECORDS_SIZE;
  /** First key in gamerecords, player score (int) */
  public static final int GAMEREC_MY_SCORE			= GAMEREC_OP_NAME + GAMERECORDS_SIZE;
  /** First key in gamerecords, opponent score (int) */
  public static final int GAMEREC_OP_SCORE			= GAMEREC_MY_SCORE + GAMERECORDS_SIZE;
  /** First key in gamerecords, number of games against this opponent (int) */
  public static final int GAMEREC_GAME_COUNT		= GAMEREC_OP_SCORE + GAMERECORDS_SIZE;
  /** First key in gamerecords, timestamp (long) */
  public static final int GAMEREC_TIMESTAMP			= GAMEREC_GAME_COUNT + GAMERECORDS_SIZE;
  /** First key in gamerecords, saved game data (byte[]) */
  public static final int GAMEREC_SAVED_GAME_DATA	= GAMEREC_TIMESTAMP + GAMERECORDS_SIZE;

  /** Nbr of keys */
  protected static final int	NBR_OF_KEYS			= 8 + 7 * GAMERECORDS_SIZE;
	
  /** Command used during user string input */
  protected static final Command OK =
    new Command(Resources.getString(Resources.TXT_C_OK), Command.OK, 1);
  /** Command used during user string input */
  protected static final Command CANCEL =
    new Command(Resources.getString(Resources.TXT_C_CANCEL), Command.CANCEL, 1);

  /** Represents a game that is only played on this device */
  public static int GAME_TYPE_LOCAL = 0;
  /** Represents a distributed game where this device acts server */
  public static int GAME_TYPE_REMOTE_SERVER = 1;
  /** Represents a distributed game where this device acts client */
  public static int GAME_TYPE_REMOTE_CLIENT = 2;

  /** Current game type */
  protected static int m_gameType;

  /**
   * Sets current game type, one of <code>GAME_TYPE_LOCAL</code>, 
   * <code>GAME_TYPE_REMOTE_SERVER</code>, <code>GAME_TYPE_REMOTE_CLIENT</code>.
   * @param gameType The current game type.
   */
  protected static void setGameType(int gameType)
  {
    m_gameType = gameType;
  }

  /**
   * Returns current game type, one of <code>GAME_TYPE_LOCAL</code>, 
   * <code>GAME_TYPE_REMOTE_SERVER</code>, <code>GAME_TYPE_REMOTE_CLIENT</code>.
   * @return The current game type.
   */
  public static int getGameType()
  {
    return m_gameType;
  }

  /**
   * Sets the connection used in remote game. Must be set before invoking
   * <code>startRemoteGame</code>
   * @param conn	The connection used with remote player.
   */
  public synchronized static void setBackgammonConnection(BackgammonConnection conn)
  {
    m_remoteConnection = conn;
  }

  /**
   * Returns true if there exists a saved phone game
   * 
   * @return true if saved game exists, false otherwise
   */
  public static boolean hasSavedLocalGame()
  {
    return RmsFacade.getBoolean(HAS_SAVED_LOCAL_GAME);
  }

  /**
   * Start a new game for two players on one phone.
   */
  public synchronized static void startLocalGame()
  {
    setGameType(GAME_TYPE_LOCAL);
    Audio.stopSound(Audio.MUSIC);
    Player p1 =
      new LocalPlayer(1, "Whitey".toCharArray(), true, BoardMediator.getCanvas());
    Player p2 =
      new LocalPlayer(2, "Blackie".toCharArray(), false, BoardMediator.getCanvas());
    Audio.stopSound(Audio.MUSIC);
    BoardMediator.init(p1, p2, false);
    setCanvas(BoardMediator.getCanvas());
  }

  /**
   * Starts a remote game, either as server or as client. This method uses the
   * connection set in method <code>setBackgammonConnection</code>. It handshakes
   * with the other device and starts a new game, or resumes a game if any of the
   * devices has a saved game. On conflicting preferred settings (color and rules)
   * the server wins.
   * 
   * @param server		True if server, false if client.
   * @param localName	The name of this player.
   * @see Bluegammon#setBackgammonConnection(BackgammonConnection)
   */
  public static void startRemoteGame(boolean server, char[] localName)
  {
    DataInputStream in = m_remoteConnection.getInput();
    DataOutputStream out = m_remoteConnection.getOutput();
    if (in == null || out == null)
    {
      // Occurs when connecting to a closed connection
      // i.e. the remote device pressed cancel during connecting phase
      return;
    }
    Bluegammon.showPopup(Resources.getChars(Resources.TXT_STARTING_GAME), null, 10, 0, 0, null);
    setGameType(server ? GAME_TYPE_REMOTE_SERVER : GAME_TYPE_REMOTE_CLIENT);
    Handshake handshake = new Handshake();
    boolean fail = false;
    try
    {
      if (server)
      {
        handshake.serverHandshake(in, out, new String(localName));
      }
      else
      {
        handshake.clientHandshake(in, out, new String(localName));
      }
    }
    catch (Throwable t)
    {
      fail = true;
      Bluegammon.showPopup(Resources.getChars(Resources.TXT_HANDSHAKE_FAIL), Popup.ALT_OK, 0, 0, 0, null);
      System.err.println("Handshake failed");
      t.printStackTrace();
      return;
    }
    
    if (!fail)
    {
      boolean resumed = handshake.getSavedGame() != null;
      Player p1 =
        new LocalPlayer(Device.getDeviceId(),
	                    localName,
	                    handshake.isWhite(),
	                    BoardMediator.getCanvas());
      PlayerListenerProxy proxy = new PlayerListenerProxy(out);
      p1.addListener(proxy);
      Player p2 =
        new RemotePlayer(handshake.getRemoteId(),
	                     handshake.getRemoteName(),
	                     !handshake.isWhite(),
	                     in);
      BoardMediator.init(p1, p2, resumed);
      
      if (resumed)
      {
        boolean remoteResume = handshake.isRemoteResume();
        byte[] b = handshake.getSavedGame();
        ByteArrayInputStream bais = new ByteArrayInputStream(b);
        try
        {
          BoardMediator.loadGame(bais, remoteResume);
          bais.close();
        }
        catch (IOException e)
        {
          e.printStackTrace();
        }
        b = null;
        bais = null;
        System.gc();
      }
      
      setCanvas(BoardMediator.getCanvas());
      Audio.stopSound(Audio.MUSIC);
      
      // Show the rules of this game if connecting as client or
      // if this is a resumed game
      if (!server || resumed)
      {
        showRules();
      }
      else
      {
        Popup p = Bluegammon.getCurrentPopup();
        if (p != null) p.dispose();
      }
    }
    getCanvas().repaint();
  }

  /**
   * Resumes a saved game
   */
  public static void resumeSavedLocalGame()
  {
    Player p1 = new LocalPlayer(1, "Whitey".toCharArray(), true,
        BoardMediator.getCanvas());
    Player p2 = new LocalPlayer(2, "Blackey".toCharArray(), false,
        BoardMediator.getCanvas());
    BoardMediator.init(p1, p2, true);

    setGameType(GAME_TYPE_LOCAL);
    byte[] b = RmsFacade.get(SAVED_GAME_DATA);
    ByteArrayInputStream bais = new ByteArrayInputStream(b);
    try
    {
      BoardMediator.loadGame(bais, false);
      bais.close();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
    b = null;
    bais = null;
    System.gc();

    Audio.stopSound(Audio.MUSIC);
    setCanvas(BoardMediator.getCanvas());
    showRules();
  }

  /**
   * Exits a game. If the game is not finished it is stored,
   * so it can be resumed later.
   */
  public synchronized static void exitGame()
  {
    // Local game
    if (getGameType() == GAME_TYPE_LOCAL)
    {
      if (!BoardMediator.isGameFinished())
      {
        // Local game is not finished, save it
        try
        {
          if (BoardMediator.getCurrentPlayer() != null)
          {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            BoardMediator.saveGame(baos);
            baos.close();
            RmsFacade.set(SAVED_GAME_DATA, baos.toByteArray());
            RmsFacade.setBoolean(HAS_SAVED_LOCAL_GAME, true);
          }
        }
        catch (IOException e)
        {
          e.printStackTrace();
        }
      }
      else
      {
        // Local game is finished, remove any local saved game
        RmsFacade.set(SAVED_GAME_DATA, null);
        RmsFacade.setBoolean(HAS_SAVED_LOCAL_GAME, false);
      }
    }
    
    // Remote game
    else if (getGameType() == GAME_TYPE_REMOTE_CLIENT ||
             getGameType() == GAME_TYPE_REMOTE_SERVER)
    {
      Player opponent = BoardMediator.getOpponentPlayer();
      if (!BoardMediator.isGameFinished())
      {
        // Remote game is not finished, save it
        try
        {
          if (BoardMediator.getCurrentPlayer() != null)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -