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

📄 jcmodel.java

📁 非常好的java collapse游戏代码
💻 JAVA
字号:
/*
 * JCollapse - Java Collapse Game
 * Copyright (C) 2005 Erico Gon鏰lves Rimoli
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package sourceforge.net.projects.jcollapse.engine;

import java.util.ArrayList;
import java.util.concurrent.ConcurrentLinkedQueue;

import sourceforge.net.projects.jcollapse.engine.block.Block;
import sourceforge.net.projects.jcollapse.engine.board.Board;
import sourceforge.net.projects.jcollapse.engine.board.GameBoard;

/**
 * This the main class model for JCollapse Game Engine.
 * <p>Project started in 2005-09-25</p> 
 * @author erico
 */
public class JCModel {
	/**
	 * The version of JCollapse Engine
	 */
	public final static String ENGINE_VERSION = "0.1.0";
	
	private ArrayList<JCListener> m_JCListener;
	private GameBoard m_GameBoard; 
	private ConcurrentLinkedQueue<Block> m_BlockStack;

	/**
	 * Constructor
	 * @param width The horizontal blocks size (quantity of Block's in x axis)
	 * @param height The horizontal blocks size (quantity of Block's in y axis)
	 * @throws InvalidDimensionException If uset set an invalid dimension
	 */
	public JCModel( int width, int height ) throws InvalidDimensionException {
		m_JCListener = new ArrayList<JCListener>(1);
		m_BlockStack = new ConcurrentLinkedQueue<Block>();
		
		m_GameBoard = new GameBoard( width, height );
	}
	
	/**
	 * The GameBoard represent base and main Board objects
	 * @return the GameBoard object
	 */
	public GameBoard getGameBoard() {
		return m_GameBoard;
	}
	
	/**
	 * Add new Block to the Block stack
	 * The engine pop the first Block from stack to the board game when user call enterBlock event
	 * @param block The Block object
	 */
	public void pushBlock( Block block ) {
		m_BlockStack.add( block );
	}
	
	/**
	 * Remove Block from stack
	 * @return the removed Block
	 */
	public Block popBlock() {
		return m_BlockStack.poll();
	}
	
	/**
	 * Clear stack of Block's
	 */
	public void clearStack() {
		m_BlockStack.clear();
	}
	
	/**
	 * Return the number of elements of stack
	 * @return The number of elements of stack
	 */
	public int countStackBlocks() {
		return m_BlockStack.size();
	}
	
	/**
	 * This method return true when block stack has more than 0 Block's
	 * or when base board are full (don't care about block stack size).
	 * It's mean that when we don't have blocks in stack and base board are full, you can
	 * call rollBlock method to dispatch the base board line to the main board.
	 * @return true if roll Block method can be called
	 */
	public boolean hasBlockToRoll() {
		if( m_BlockStack.size() > 0 || m_GameBoard.isBaseBoardFull() )
			return true;
		
		return false;
	}
	
	/**
	 * Add the JCListener
	 * @param jCollapseListener The JCollapse listener object
	 */
	public void addJCollapseListener( JCListener jCollapseListener ) {
		m_JCListener.add( jCollapseListener );
	}
	
	/**
	 * Remove JCListener
	 * @param jCollapseListener The JCListener object
	 * @return true if event are removed
	 */
	public boolean removeJCollapseEvent( JCListener jCollapseListener ) {
		return m_JCListener.remove( jCollapseListener );
	}
	
	/**
	 * Roll block from stack to the base Board
	 * @throws EmptyBlockStackException fired when you call this method and stack is empty
	 * and the base Board not full
	 */
	public void rollBlock() throws EmptyBlockStackException {
		int bw = m_GameBoard.getBoardWidth();
		int i;
		boolean baseBoardFull;
		
		//if no blocks to roll and base board are not full, fire exception
		if( !hasBlockToRoll() )
			throw new EmptyBlockStackException();
		
		//if BASEBOARD is not full...
		baseBoardFull = m_GameBoard.isBaseBoardFull();
		if( !baseBoardFull )
			for( i = bw - 1; i > 0; i-- )
				m_GameBoard.getBaseBoard().moveBlock( i, i - 1 );

		//if base is full, clean base and add new base row to the board
		else
			flushBaseBoard();
		
		//add new bock to the boardbase block list if we have
		//blocks in stack.
		if( countStackBlocks() > 0 )
			m_GameBoard.getBaseBoard().setBlock( 0, popBlock() );
		
		fireBlockRolled( countStackBlocks(), baseBoardFull );
	}
	
	/**
	 * If base Board are full, Block's rolls to the main Board 
	 */
	private void flushBaseBoard() {
		int bw, bh, i;
		
		assert( m_GameBoard.isBaseBoardFull() );
		
		if( m_GameBoard.hasBlockOnTop() ) {
			fireGameOver();
			return;
		}
		
		bw = m_GameBoard.getBoardWidth();
		bh = m_GameBoard.getBoardHeight();
		
		for( i = bw * bh - 1; i >= bw; i-- )
			m_GameBoard.getMainBoard().moveBlock( i - bw, i );
		
		for( i = 0; i < bw; i++ )
			m_GameBoard.getMainBoard().setBlock( i, m_GameBoard.getBaseBoard().getBlock( i ) );

		m_GameBoard.getBaseBoard().clear();
	}
	
	private void fireGameOver() {
		for( JCListener l : m_JCListener )
			l.gameOver();
	}
	
	private void fireBlockRolled( int remainder, boolean isBaseBoardFull ) {
		for( JCListener l : m_JCListener )
			l.blockRolled( remainder, isBaseBoardFull );
	}
	
	private void fireBoardTouched( int removedBlocks, Block block ) {
		for( JCListener l : m_JCListener )
			l.boardTouched( removedBlocks, m_BlockStack.size(), block );
	}
	
	/**
	 * When user touch screen Board in position (x,y), the engine apply rule for
	 * touched block, then the boardTouched event are fired with the number of
	 * removed blocks
	 * @param x The x position
	 * @param y The y position
	 * @throws InvalidPositionException If position is out of Board
	 */
	public void touchBoard( int x, int y ) throws InvalidPositionException {
		int pos;
		int removedBlocks = 0;
		Block block;
		
		if( x < 0 || y < 0 ||
			x >= m_GameBoard.getBoardWidth() || y >= m_GameBoard.getBoardHeight() )
			throw new InvalidPositionException( "Invalid position exception: " + x + ", " + y );
		
		pos = y * m_GameBoard.getBoardWidth() + x;
		block = m_GameBoard.getMainBoard().getBlock( pos );
		
		if( block != null ) {
			removedBlocks = block.touched( x,
						   				   y,
						   				   m_GameBoard.getMainBoard() );

			validBoard( m_GameBoard.getMainBoard() );
		}
		
		fireBoardTouched( removedBlocks, block );
	}
	
	/**
	 * When some blocks disappeared from board, we get some
	 * white spaces. Then, this method clean these spaces.
	 * It will be filled by blocks that appear in top of these spaces
	 * @param board the main Board object
	 */
	private void validBoard( Board board ) {
		int bh = m_GameBoard.getBoardHeight();
		
		for( int x = 0; x < m_GameBoard.getBoardWidth(); x++ )
			for( int y = 0; y < bh; y++ )
				if( board.getBlock( x, y ) == null )
					for( int y1 = y + 1; y1 < bh; y1++ )
						if( board.getBlock( x, y1 ) != null ) {
							board.moveBlock( x, y1, x, y );
							break;
						}
	}
	
	/**
	 * Get the version of JCollapse Engine
	 * @return the JCollapse Engine
	 */
	public static String getVersion() {
		return ENGINE_VERSION;
	}
}

⌨️ 快捷键说明

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