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

📄 puzzleapp.c

📁 在Palm上可以正常运行的类似拼图小游戏源代码!
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
 *
 * Copyright (c) 1995-2004 PalmSource, Inc. All rights reserved.
 *
 * File: PuzzleApp.c
 *
 * Description:
 *	  This is the main source module for the Puzzle(15) game.
 *
 *****************************************************************************/

#include <PalmOS.h>

#include "PuzzleRsc.h"

/***********************************************************************
 *
 *	Entry Points
 *
 ***********************************************************************/


/***********************************************************************
 *
 *	Internal Constants
 *
 ***********************************************************************/
#define puzzleAppCreator	'0910'

#define version20			0x02000000

#define boardX				18
#define boardY				26


#define pieceWidth			30
#define pieceHeight			30

#define pieceCornerDiameter	7

#define pieceFrameWidth		1
#define pieceSpace			pieceFrameWidth		// space between pieces
#define boardFrameMargin	pieceFrameWidth
#define boardFrameWidth		3

#define boardRows			4
#define boardColumns		4

#define numPositions		(boardRows * boardColumns)

#define minRow				0
#define minColumn			0
#define maxRow				(boardRows - 1)					// 0-based
#define maxColumn			(boardColumns - 1)				// 0-based

#define emptySquareID		0

// Number of moves the puzzle is shuffled from a solved position
#define numShuffleMoves		700


/***********************************************************************
 *
 *	Internal Structures
 *
 ***********************************************************************/
typedef struct PieceCoordType {
	Int16		row;							// 0-based
	Int16		col;							// 0-based
	} PieceCoordType;


typedef union GameBoardType {
	UInt8		square[numPositions];
	UInt32	save[(numPositions+3)/4];
	} GameBoardType;


/***********************************************************************
 *
 *	Private global variables
 *
 ***********************************************************************/
static GameBoardType	GameBoard;
static Int16			EmptyPos;


/***********************************************************************
 *
 *	Internal Functions
 *
 ***********************************************************************/
static UInt16 StartApplication (void);
static void StopApplication (void);
static Boolean MainFormDoCommand (UInt16 command);
static void MainFormInit (FormPtr frm);
static Boolean MainFormHandleEvent (EventPtr event);
static void AppEventLoop (void);


static void		InitGameBoard(void);
static Int16	CoordToPosition(PieceCoordType coord);
static PieceCoordType	PositionToCoord(Int16 pos);
static Int16	GetEmptyPos(void);
static void		MoveOnePiece(Int16 from, Boolean draw);
static void		MoveRange(Int16 from, Boolean draw);
static void		DrawGameBoard(void);
static Int16	MapPenPosition(Int16 penX, Int16 penY);
static void		DrawPiece(Int16 pos);
static void		ShuffleGameBoard(UInt32 moves);
static void		SaveGameBoard(void);
static void		LoadGameBoard(void);




/***********************************************************************
 *
 * FUNCTION:	InitGameBoard
 *
 * DESCRIPTION:	Generate a new game.
 *
 * PARAMETERS:	none
 *
 * RETURNED:	nothing
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			vmk		8/19/95		Initial Version
 *
 ***********************************************************************/
static void InitGameBoard(void)
{
	UInt8		i;
	for ( i=0; i < (numPositions - 1); i++ )
		GameBoard.square[i] = i + 1;
	GameBoard.square[numPositions - 1] = emptySquareID;
	EmptyPos = numPositions - 1;
}


/***********************************************************************
 *
 * FUNCTION:	ShuffleGameBoard
 *
 * DESCRIPTION:	Shuffle the game board, updating it visually with each step.
 *
 * PARAMETERS:	moves		-- number of moves to shuffle
 *
 * RETURNED:	nothing
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			vmk		8/20/95		Initial Version
 *
 ***********************************************************************/
static void ShuffleGameBoard(UInt32 moves)
{
	UInt16		rand;
	PieceCoordType	coord;


	InitGameBoard();
	
	do	{
		rand = (UInt16)SysRandom( 0 ) % 8;				// generate 0-7
		coord = PositionToCoord( EmptyPos );
		if ( rand & 4L )
			coord.row = (Int16)(rand & 3L);
		else
			coord.col = (Int16)(rand & 3L);
		MoveRange( CoordToPosition(coord), false/*draw*/ );
		}
	while ( --moves );
}


/***********************************************************************
 *
 * FUNCTION:	SaveGameBoard
 *
 * DESCRIPTION:	Save game in the feature registry.
 *
 * PARAMETERS:	none
 *
 * RETURNED:	nothing
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			vmk		8/19/95		Initial Version
 *
 ***********************************************************************/
static void SaveGameBoard(void)
{
	UInt16		featureNum;
	UInt16		numFeatures;
	
	numFeatures = sizeof(GameBoard.save) / sizeof(GameBoard.save[0]);
	
	for ( featureNum = 0; featureNum < numFeatures; featureNum++ )
		FtrSet( puzzleAppCreator, featureNum, GameBoard.save[featureNum] );
}


/***********************************************************************
 *
 * FUNCTION:	LoadGameBoard
 *
 * DESCRIPTION:	Load saved game from the feature registry.
 *
 * PARAMETERS:	none
 *
 * RETURNED:	nothing
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			vmk		8/19/95		Initial Version
 *
 ***********************************************************************/
static void LoadGameBoard(void)
{
	Err		err = 0;
	UInt16		featureNum;
	UInt16		numFeatures;
	
	numFeatures = sizeof(GameBoard.save) / sizeof(GameBoard.save[0]);
	
	// Load game board from feature registry
	for ( featureNum = 0; featureNum < numFeatures; featureNum++ )
		{
		err = FtrGet( puzzleAppCreator, featureNum, &GameBoard.save[featureNum] );
		if ( err )	break;
		}

	// Initialize the board of load failed
	if ( !err  )
		{
		EmptyPos = GetEmptyPos();
		}
	else
		{
		InitGameBoard();
		}
}


/***********************************************************************
 *
 * FUNCTION:	GetEmptyPos
 *
 * DESCRIPTION:	Get position of the empty square
 *
 * PARAMETERS:	none
  *
 * RETURNED:	position of the empty square(0-based)
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			vmk		8/19/95		Initial Version
 *
 ***********************************************************************/
static Int16 GetEmptyPos(void)
{
	Int16		pos;
	
	for ( pos=0; pos < numPositions; pos++ )
		if ( GameBoard.square[pos] == emptySquareID )
			return( pos );
	
	ErrDisplay( "didn't find empty square position" );
	return( 0 );
}


/***********************************************************************
 *
 * FUNCTION:	CoordToPosition
 *
 * DESCRIPTION:	Convert row and column pair to a 0-based position
 *
 * PARAMETERS:	coord		-- piece row and column
  *
 * RETURNED:	piece position (0-based)
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			vmk		8/19/95		Initial Version
 *
 ***********************************************************************/
static Int16 CoordToPosition(PieceCoordType coord)
{
	return( (coord.row * boardColumns) + coord.col );
}


/***********************************************************************
 *
 * FUNCTION:	PositionToCoord
 *
 * DESCRIPTION:	Convert a 0-based position to row and column pair
 *
 * PARAMETERS:	pos		-- piece position (0-based)
 *
 * RETURNED:	row and column
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			vmk		8/19/95		Initial Version
 *
 ***********************************************************************/
static PieceCoordType PositionToCoord(Int16 pos)
{
	PieceCoordType		coord;
	
	ErrFatalDisplayIf( pos >= numPositions, "pos out of bounds" );

	coord.row = pos / boardColumns;
	coord.col = pos % boardColumns;
	
	return( coord );
}


/***********************************************************************
 *
 * FUNCTION:	MapPenPosition
 *
 * DESCRIPTION:	Map a screen-relative pen position to a game piece
 *						position;
 *
 * PARAMETERS:	penX		-- display-relative x position
 *				penY		-- display-relative y position
 *
 * RETURNED:	piece position (0-based)
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			vmk		8/19/95		Initial Version
 *
 ***********************************************************************/
static Int16 MapPenPosition(Int16 penX, Int16 penY)
{
	Int16		x;
	Int16		y;
	RectangleType	rect;
	PieceCoordType	coord;
	
	// Map display relative coordinates to window-relative
	x = (Int16)penX;
	y = (Int16)penY;
	WinDisplayToWindowPt( &x, &y );
	
	rect.topLeft.x = boardX + boardFrameMargin;
	rect.topLeft.y = boardY + boardFrameMargin;
	rect.extent.x = (boardColumns * pieceWidth) +
			((boardColumns - 1) * pieceSpace);
	rect.extent.y = (boardRows * pieceHeight) +
			((boardRows - 1) * pieceSpace);
	
	if ( !RctPtInRectangle(x, y, &rect) )
		return( -1 );
	
	// Convert to board-relative coordinates
	x -= boardX;
	y -= boardY;
	
	if ( x < 0 )
		{
		ErrDisplay( "board x is negative" );
		x = 0;
		}
	if ( y < 0 )
		{
		ErrDisplay( "board y is negative" );
		y = 0;
		}
	
	// Get the piece position
	coord.col = x / (pieceWidth + pieceSpace);
	coord.row = y / (pieceHeight + pieceSpace);
	if ( coord.col > maxColumn )
		{
		ErrDisplay( "column out of bounds" );
		coord.col = maxColumn;
		}
	if ( coord.row > maxRow )
		{
		ErrDisplay( "row out of bounds" );
		coord.row = maxRow;
		}
	
	return( CoordToPosition(coord) );
}


/***********************************************************************
 *
 * FUNCTION:	DrawPiece
 *
 * DESCRIPTION:	Draw a game piece
 *
 * PARAMETERS:	pos		-- piece position (0-based)
 *
 * RETURNED:	nothing
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			vmk		8/19/95		Initial Version
 *
 ***********************************************************************/
static void DrawPiece(Int16 pos)
{
	RectangleType	rect;
	PieceCoordType	coord;
	FontID			oldFontID;
	
	ErrFatalDisplayIf( pos >= numPositions, "pos out of bounds" );
	
	// Compute the piece rectangle
	coord = PositionToCoord( pos );
	//PrvPieceCoordToRect( coord, &rect );
	rect.topLeft.x = boardX + boardFrameMargin + (pieceWidth * coord.col) +
			(coord.col * pieceSpace);
	rect.topLeft.y = boardY + boardFrameMargin + pieceHeight *coord.row +
			(coord.row * pieceSpace);
	rect.extent.x = pieceWidth;
	rect.extent.y = pieceHeight;
	
	// Erase the old piece

	// If this is the empty square, erase the old game piece
	if ( GameBoard.square[pos] == emptySquareID )
		{
		RectangleType	erase;
	
		WinEraseRectangle( &rect, 0/*cornerDiam*/ );
		
		// Clean up the pieces of frame around board edges
		if ( coord.col == minColumn )
			{
			erase = rect;
			erase.topLeft.x -= pieceFrameWidth;
			erase.topLeft.y -= pieceFrameWidth;
			erase.extent.x = pieceFrameWidth;
			erase.extent.y = pieceHeight + (pieceFrameWidth * 2);
			WinEraseRectangle( &erase, 0/*cornerDiam*/ );
			}
		else if ( coord.col == maxColumn )
			{
			erase = rect;
			erase.topLeft.x += rect.extent.x;
			erase.topLeft.y -= pieceFrameWidth;
			erase.extent.x = pieceFrameWidth;
			erase.extent.y = pieceHeight + (pieceFrameWidth * 2);
			WinEraseRectangle( &erase, 0/*cornerDiam*/ );
			}
			
		if ( coord.row == minRow )
			{
			erase = rect;
			erase.topLeft.x -= pieceFrameWidth;
			erase.topLeft.y -= pieceFrameWidth;
			erase.extent.x = pieceWidth + (pieceFrameWidth * 2);
			erase.extent.y = pieceFrameWidth;
			WinEraseRectangle( &erase, 0/*cornerDiam*/ );
			}
		else if ( coord.row == maxRow )
			{
			erase = rect;
			erase.topLeft.x -= pieceFrameWidth;
			erase.topLeft.y += rect.extent.y;
			erase.extent.x = pieceWidth + (pieceFrameWidth * 2);
			erase.extent.y = pieceFrameWidth;
			WinEraseRectangle( &erase, 0/*cornerDiam*/ );
			}
		} // If this is the empty square, erase the old game piece
	
	// Erase the old piece frame
	else
		{
		// For now, we are always drawing new pieces over empty squares,
		// and do not need to erase anything
		//WinEraseRectangleFrame( frameBits.word, &rect );
		}
	
	//
	// Draw the new piece
	//
	
	if ( GameBoard.square[pos] != emptySquareID )
		{
		FrameBitsType	frameBits;
		Char				text[32];
		UInt16				textLen;
		Int16				textHeight;
		Int16				textWidth;
		Int16				x, y;
		
		// Draw the frame
		frameBits.word = 0;					// initialize the entire structure
		frameBits.bits.cornerDiam = pieceCornerDiameter;
		frameBits.bits.shadowWidth = 0;
		frameBits.bits.width = pieceFrameWidth;
		WinDrawRectangleFrame( frameBits.word, &rect );
		
		// Draw the label
		StrIToA( text, GameBoard.square[pos] );
		textLen = StrLen( text );
		oldFontID = FntSetFont( ledFont );
		textHeight = FntLineHeight();
		textWidth = FntCharsWidth( text, textLen );
		x = rect.topLeft.x + ((rect.extent.x - textWidth) / 2);
		y = rect.topLeft.y + ((rect.extent.y - textHeight) /2 );
		WinDrawChars( text, textLen, x, y);
		FntSetFont( oldFontID );
		}

}


/***********************************************************************
 *
 * FUNCTION:	DrawGameBoard
 *
 * DESCRIPTION:	Draw the game board
 *
 * PARAMETERS:	pos		-- piece position (0-based)
 *
 * RETURNED:	nothing
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			vmk		8/19/95		Initial Version
 *			vmk		12/17/97	Fixed drawing glitch by initializing the "word"
 *								field of frameBits.
 *
 ***********************************************************************/
static void DrawGameBoard(void)

⌨️ 快捷键说明

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