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

📄 boardstate.java

📁 手机应用程序之蓝牙编程源代码。。蓝牙编程爱好者课用
💻 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.logic;

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

/**
 * <p>
 * Singleton class holding game logic and state of a game. There can
 * only be one state per device, thus the singleton pattern.</p><p>
 * Extends the <code>Board</code> class with player-, turn-, dice- and rule-logic.
 * The <code>BoardState</code> is detached from gui. State reports when
 * pieces are moved etc can be retreived by implementing the
 * <code>BoardStateListener</code> interface and registering this instance
 * in the <code>BoardState</code>.
 * </p>
 * 
 * @see bluegammon.logic.BoardMediator
 * @author Peter Andersson
 */
public class BoardState extends Board
{

	// Interaction game states
    /** Flag indicating if turns should be chosen */
	protected boolean m_chooseTurns = true;
    /** Flag indicating if dice is thrown */
	protected boolean m_diceThrown = false;

	// Player and turn state
	/** Player one */
	protected static Player m_player1;
	/** Player two */
	protected static Player m_player2;
	/** Current player */
	protected static Player m_currentPlayer;
	
	// Rule game states
	/** Flag indicating if game is finished */
	protected boolean m_gameFinished = true;
	/** Integer array of the dice values */
	protected int[] m_dice = new int[4];
	/** Number of dice values (2 for different dice values, 4 for double throw) */
	protected int m_diceVals = 2;
	/** Flag indicating if possible moves for current player has been calculated */
	protected boolean m_possibleMovesCalculated = false;
	/** Integer array of possible moves */
	protected int[][] m_possibleMoves = new int[256][3];
	/** Possible move board source index */
	public static final int PM_SOUR = 0;
	/** Possible move board destination index */
	public static final int PM_DEST = 1;
	/** Possible move dice value index */
	public static final int PM_DICE = 2;
	/** Number of possible moves for current player */
	protected int m_possibleMoveCount = 0;
	/** Integer array of undoable moves */
	protected int[][] m_undoableMoves = new int[5][4];
	/** Undoable move board source index */
	protected static final int UNDO_SOURCE  = 0;
	/** Undoable move board destination index */
	protected static final int UNDO_DEST = 1;
	/** Undoable move on guard flag (if >=0, guard will be moved to this pos ) */
	protected static final int UNDO_GUARD = 2;
	/** The dicevalue that should be put back to dicevalues */
	protected static final int UNDO_DICEVALUE = 3;
	/** Number of undoable moves */
	protected int m_undoableMoveCount = 0;

	/** Listener of this state. For compact framework, only allow one listener. */
	protected BoardStateListener m_listener;
	/** BoardState instance */
	protected static BoardState m_instance;
	
	/**
	 * Registers a boardstate-listener that will receive
	 * events upon state changes.
	 * 
	 * @param listener	The listener.
	 */
	public void setGameListener(BoardStateListener listener)
	{
		m_listener = listener;
	}
	
	// Player stats
	
	/**
	 * Defines the two backgammon players.
	 * @param player1	Player one.
	 * @param player2	Player two.
	 */
	public void setPlayers(Player player1, Player player2)
	{
	  m_player1 = player1;
	  m_player2 = player2;
	}
	
	/**
	 * Returns whether the game is finished or not
	 * @return	true if finished, false otherwise
	 */
	public boolean isGameFinished()
	{
		return m_gameFinished;
	}

	/**
	 * Marks this game as finished 
	 * @param b	true for finished, false otherwise
	 */
	public void setGameFinished(boolean b)
	{
		m_gameFinished = b;
	    m_possibleMovesCalculated = false;
	}
	
	/**
	 * Returns the color of current player.
	 * @return	true for white player, false for black player
	 */
	public boolean isCurrentPlayerWhite()
	{
		return m_currentPlayer.isWhite();
	}
	
	/**
	 * Returns current player.
	 * @return	current player.
	 */
	public Player getCurrentPlayer()
	{
	  return m_currentPlayer;
	}
	
	/**
	 * Returns waiting player.
	 * @return	noncurrent player.
	 */
	public Player getWaitingPlayer()
	{
	  if (m_player1 == m_currentPlayer)
	  {
	    return m_player2;
	  }
	  else
	  {
	    return m_player1;
	  }
	}
	
	/**
	 * Sets the turn to the player having specified color
	 * without notifying listener about the change.
	 * @param white		True for white player, false for black player
	 */
	public void setCurrentPlayer(boolean white)
	{
	    Player p = m_player1;
	    if (white && !m_player1.isWhite() ||
	        !white && m_player1.isWhite())
	    {
	      p = m_player2;
	    }
		m_currentPlayer = p;
	}
	
	/**
	 * Sets the turn to the player having specified color
	 * and notifies listener about the change.
	 * @param whiteTurn		True for white player, false for black player
	 */
	public void setTurn(boolean whiteTurn)
	{
	  	setCurrentPlayer(whiteTurn);
		if (m_listener != null) m_listener.turnChange(whiteTurn);
	}
	
	// Movement

	/**
	 * Moves a piece of specified color, from specified index
	 * to specified destination on board. Handles specific backgammon rules, i.e.
	 * if white moves to an index where one black piece resides, whereas the black
	 * piece is put under guard. Step (1) of performing a move.
	 * @param index		The source index to move from
	 * @param dest		The destination index to move to
	 * @param white		The color of the piece to move
	 */
	public synchronized void makeMove(int index, int dest, boolean white)
	{
		int[] player = WHITE, opponent = BLACK;
		if (!white)
		{
			player = BLACK;
			opponent = WHITE;
		}
		player[index] -= 1;
		player[dest] += 1;
		m_undoableMoves[m_undoableMoveCount][UNDO_SOURCE] = dest;
		m_undoableMoves[m_undoableMoveCount][UNDO_DEST]   = index;
		m_undoableMoves[m_undoableMoveCount][UNDO_GUARD]  = -1;
		if (m_listener != null) m_listener.pieceMoved(white, index, dest);
		if (dest != POS_OUT && opponent[dest] == 1)
		{
			m_undoableMoves[m_undoableMoveCount][UNDO_GUARD]  = dest;
			opponent[dest] = 0;
			opponent[POS_GUARD]++;
			if (m_listener != null) m_listener.pieceMoved(!white, dest, POS_GUARD);
		}
		
		if (player[POS_OUT] == 15)
		{
			setGameFinished(true); 
			if (m_listener != null)
				m_listener.gameFinished(
				    white, 
				    calculatePiecesLeft(!white),
				    calculatePoints(!white));
		}
	}
	
	/**
	 * Consumes a dice value, called when a player moves a piece.
	 * Populates undoable moves vector and consumes the dice value
	 * used for move.
	 * Step (2) of performing a move.
	 * @param diceIndex	The diceindex that was used for the move.
	 */
	public synchronized void consumeDice(int diceIndex)
	{
		m_undoableMoves[m_undoableMoveCount][UNDO_DICEVALUE] = m_dice[diceIndex];
		for (int d = diceIndex; d < m_dice.length-1; d++)
		{
			m_dice[d] = m_dice[d+1];
		}
		m_diceVals--;
		m_possibleMovesCalculated = false;
	}
	
	/**
	 * Commits a move, step (3) of performing a move. Updates
	 * undoable move count and checks if game is ended because of this
	 * move.
	 * @param white		The color of the pieces whose moves are to be commited.
	 * @param diceValue	The dicevalue that was used for the move.
	 */
	public synchronized void commitMove(boolean white, int diceValue)
	{
		int[] player = WHITE, opponent = BLACK;
		if (!white)
		{
			player = BLACK;
			opponent = WHITE;
		}
		m_undoableMoveCount++;
		if (m_listener != null) m_listener.undoAdded(m_undoableMoveCount, diceValue);
	}
	
	
	/**
	 * Undoes the last move. Does nothing if there are no moves to undo.
	 * @param white		The color of the player that undoes
	 * @return the source index of the undoed move.
	 */
	public synchronized int undoLastMove(boolean white)
	{
		int oldSource = -1;
		if (m_undoableMoveCount > 0)
		{
			int[] player = WHITE, opponent = BLACK;
			if (!white)
			{
				player = BLACK;
				opponent = WHITE;
			}

			m_undoableMoveCount--;
			int source = m_undoableMoves[m_undoableMoveCount][UNDO_SOURCE];
			int dest = m_undoableMoves[m_undoableMoveCount][UNDO_DEST];
			int guard = m_undoableMoves[m_undoableMoveCount][UNDO_GUARD];
			int diceVal = m_undoableMoves[m_undoableMoveCount][UNDO_DICEVALUE];
			oldSource = dest;
			player[source]--;
			player[dest]++;
			if (m_listener != null) m_listener.pieceMoved(white, source, dest);
			if (guard >= 0)
			{
				opponent[POS_GUARD]--;
				opponent[guard]++;
				if (m_listener != null) m_listener.pieceMoved(!white, POS_GUARD, guard);
			}
			m_dice[m_diceVals++] = diceVal; 
			m_possibleMovesCalculated = false;
			if (m_listener != null) m_listener.undoPerformed(m_undoableMoveCount, diceVal);
		}
		return oldSource;
	}
	
	// Game intelligence
		
	/**
	 * Calculates possible moves and returns array, composed as
	 * int[possibleMoveIndex][PM_SOUR | PM_DEST | PM_DICE] where PM_SOUR
	 * denotes the source index, PM_DEST denotes the destination index, and 
	 * PM_DICE denotes the dice value index that is used for the move.<br><br>
	 * The array is sorted depending on player color, allowing consistent
	 * movement of source and destination cursors by simply increasing or
	 * decreasing the move index. <br><br>
	 * To get number of possible moves, i.e. the length of the array, see

⌨️ 快捷键说明

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