?? puzzleapp.c
字號(hào):
/******************************************************************************
*
* 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)
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -