funcode综合教程 拼图游戏

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
#include "CommonAPI.h"
#include "LessonX.h"
#include<bits/stdc++.h>
///
//
// 主函数入口
//
//
int g_GameState=0;
const int BLOCK_COUNT=4;
//	二维数组,存储N*N的矩阵方块信息
int	g_iBlockState[BLOCK_COUNT][BLOCK_COUNT];
//	一维数组,存储上面二维数组中的方块精灵的名字。TO DO 思考一下数	    //	组大小一样的二维数组索引与一维数组索引如何相互转换?
char	g_szBlockName[BLOCK_COUNT * BLOCK_COUNT][64];
// 	按方块大小,在编辑器里摆放的第一块方块的起始坐标
const float	g_fBlockStartX		=	-40.625f;
const float	g_fBlockStartY		=	-28.125f;
// 	屏幕高度75 / 4块 = 18.75每块的大小.编辑器里预先摆放好的方块宽和高  //	必须与此值一致
const float		g_fBlockSize		=	18.75f;
int	iLoopX		= 0, iLoopY		= 0, iLoop = 0;
int	iOneIndex	= 0, iRandIndex = 0;
/* 	用做随机的数组,当随机抽取到此数组中的一个时,比如随机到第五个,则将	*	第五个取出来用。第五个后面的数组都往前移动一位,将第五个覆盖掉,数组	*	总数减一,下次再在这剩余的14个数值里随机抽取
*/
int	iDataCount	=	BLOCK_COUNT * BLOCK_COUNT - 1;
int	iRandData[BLOCK_COUNT * BLOCK_COUNT - 1] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int XYToOneIndex( const int iIndexX, const int iIndexY )
{
    return (iIndexY * BLOCK_COUNT + iIndexX);
}
void MoveSpriteToBlock( const char *szName, const int iIndexX, const int iIndexY )
{
    float	fPosX	=	g_fBlockStartX + iIndexX * g_fBlockSize;
    float	fPosY	=	g_fBlockStartY + iIndexY * g_fBlockSize;
    dSetSpritePosition( szName, fPosX, fPosY );
}
int  IsGameWin()
{
    int	iLoopX	= 0, iLoopY = 0;
    int	iResult	= 1;
    for( iLoopY = 0; iLoopY < BLOCK_COUNT; iLoopY++ )
    {
        for( iLoopX = 0; iLoopX < BLOCK_COUNT; iLoopX++ )
        {
            // 数组的最后一个
            if( BLOCK_COUNT - 1 == iLoopX && BLOCK_COUNT - 1 == iLoopY )
                break;
            // 其中一个值不等于,那么就没有胜利
            if( g_iBlockState[iLoopY][iLoopX] != iResult )
                return 0;
            iResult++;
        }
    }
    return 1;

}
// 一维数组索引转换到二维数组索引X,注意这2个数组大小必须一致
int OneIndexToX( const int iIndex )
{
    return (iIndex % BLOCK_COUNT);
}
// 一维数组索引转换到二维数组索引Y,注意这2个数组大小必须一致
int OneIndexToY( const int iIndex )
{
    return (iIndex / BLOCK_COUNT);
}


int PASCAL WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR     lpCmdLine,
                   int       nCmdShow)
{
    // 初始化游戏引擎
    if( !dInitGameEngine( hInstance, lpCmdLine ) )
        return 0;

    // To do : 在此使用API更改窗口标题
    dSetWindowTitle("拼图");
    // 引擎主循环,处理屏幕图像刷新等工作
    while( dEngineMainLoop() )
    {
        // 获取两次调用之间的时间差,传递给游戏逻辑处理
        float	fTimeDelta	=	dGetTimeDelta();

        // 执行游戏主循环
        GameMainLoop( fTimeDelta );
    };

    // 关闭游戏引擎
    dShutdownGameEngine();
    return 0;
}

//==========================================================================
//
// 引擎捕捉鼠标移动消息后,将调用到本函数
// 参数 fMouseX, fMouseY:为鼠标当前坐标
//
void dOnMouseMove( const float fMouseX, const float fMouseY )
{
    // 可以在此添加游戏需要的响应函数
    OnMouseMove(fMouseX, fMouseY );
}
//==========================================================================
//
// 引擎捕捉鼠标点击消息后,将调用到本函数
// 参数 iMouseType:鼠标按键值,见 enum MouseTypes 定义
// 参数 fMouseX, fMouseY:为鼠标当前坐标
//
void dOnMouseClick( const int iMouseType, const float fMouseX, const float fMouseY )
{
    // 可以在此添加游戏需要的响应函数
    if( 2 != iMouseType )
    {

    }
    int	iClickIndex	=	-1;
    int	iLoop	=	0;
    for( iLoop = 0; iLoop < BLOCK_COUNT * BLOCK_COUNT; iLoop++ )
    {
        if( '\0' == g_szBlockName[iLoop][0] )
            continue;
        // 使用API dIsPointInSprite 判断指定坐标是否位于某个名字的精灵内部
        if( dIsPointInSprite( g_szBlockName[iLoop], fMouseX, fMouseY ) )
        {
            iClickIndex	=	iLoop;
            break;
        }
    }
    // 判断鼠标是否点中方块
    if( -1 == iClickIndex )
        return;
    // 将该一维数组的Index转换成二维数组的X,Y
    int	iIndexX	=	OneIndexToX( iClickIndex );
    int	iIndexY	=	OneIndexToY( iClickIndex );
// TODO 在二维数组里查找鼠标点击的方块上下左右4个方向上是否有空位:
// 注意边界判断,否则数组访问会越界。比如判断左边时,需要判断是否已经是	//最左边的索引(iIndexX == 0)
// 如果有空位(值为0),则将该空位的索引赋值给下面这2个变量
    int	iEmptyIndexX = -1, iEmptyIndexY = -1;

// X 左方向(4个方向均需要判断是否是位于边缘,iIndexX > 0 即起此作用)
    if( iIndexX > 0 )
    {
        if( 0 == g_iBlockState[iIndexY][iIndexX - 1] )
        {
            iEmptyIndexX = iIndexX - 1;
            iEmptyIndexY = iIndexY;
        }
    }
    // X 右方向
    if( -1 == iEmptyIndexX && iIndexX < BLOCK_COUNT - 1 )
    {
        if( 0 == g_iBlockState[iIndexY][iIndexX + 1] )
        {
            iEmptyIndexX = iIndexX + 1;
            iEmptyIndexY = iIndexY;
        }
    }
    // Y 上方向
    if( -1 == iEmptyIndexY && iIndexY > 0 )
    {
        if( 0 == g_iBlockState[iIndexY - 1][iIndexX] )
        {
            iEmptyIndexX = iIndexX;
            iEmptyIndexY = iIndexY - 1;
        }
    }
    // Y 下方向
    if( -1 == iEmptyIndexY && iIndexY < BLOCK_COUNT - 1 )
    {
        if( 0 == g_iBlockState[iIndexY + 1][iIndexX] )
        {
            iEmptyIndexX = iIndexX;
            iEmptyIndexY = iIndexY + 1;
        }
    }
    // 判断是否找到空位
    if( -1 == iEmptyIndexX || -1 == iEmptyIndexY )
        return;
// 有空位,在二维数组里,将该索引对应的值进行交换
    g_iBlockState[iEmptyIndexY][iEmptyIndexX] = g_iBlockState[iIndexY][iIndexX];
    g_iBlockState[iIndexY][iIndexX]	=	0;
// 对应的名字也进行交换
    int	iOneIndex	=	XYToOneIndex( iEmptyIndexX, iEmptyIndexY );
    strcpy( g_szBlockName[iOneIndex], g_szBlockName[iClickIndex] );
    g_szBlockName[iClickIndex][0]	=	'\0';
// 将该精灵移动到对应的位置
    MoveSpriteToBlock( g_szBlockName[iOneIndex], iEmptyIndexX, iEmptyIndexY );


    OnMouseClick(iMouseType, fMouseX, fMouseY);

}
//==========================================================================
//
// 引擎捕捉鼠标弹起消息后,将调用到本函数
// 参数 iMouseType:鼠标按键值,见 enum MouseTypes 定义
// 参数 fMouseX, fMouseY:为鼠标当前坐标
//
void dOnMouseUp( const int iMouseType, const float fMouseX, const float fMouseY )
{
    // 可以在此添加游戏需要的响应函数
    OnMouseUp(iMouseType, fMouseX, fMouseY);

}
//==========================================================================
//
// 引擎捕捉键盘按下消息后,将调用到本函数
// 参数 iKey:被按下的键,值见 enum KeyCodes 宏定义
// 参数 iAltPress, iShiftPress,iCtrlPress:键盘上的功能键Alt,Ctrl,Shift当前是否也处于按下状态(0未按下,1按下)
//
void dOnKeyDown( const int iKey, const int iAltPress, const int iShiftPress, const int iCtrlPress )
{
    // 可以在此添加游戏需要的响应函数
    if(KEY_SPACE == iKey)
    {
        g_GameState=1-g_GameState;
    }
    if(g_GameState)
    {
        dSetSpriteVisible("GameBegin",0);
        for( iLoopY = 0; iLoopY < BLOCK_COUNT; iLoopY++ )
        {
            for( iLoopX = 0; iLoopX < BLOCK_COUNT; iLoopX++ )
            {
                iOneIndex	=	XYToOneIndex( iLoopX, iLoopY );
                // 数组的最后一个
                if( BLOCK_COUNT - 1 == iLoopX && BLOCK_COUNT - 1 == iLoopY )
                {
                    g_iBlockState[iLoopY][iLoopX] = 0;
                    g_szBlockName[iOneIndex][0] = '\0';
                }
                else
                {
                    // 在当前剩余未使用到的数值里随机一个出来,赋值给二维数组
                    iRandIndex	=	dRandomRange( 0, iDataCount - 1 );
                    g_iBlockState[iLoopY][iLoopX] = iRandData[iRandIndex];
                    /* 	给对应的名字数组赋值。该名字的方块已经预先在地图里摆放好,因此只需要生成对应的名字即可,不用创建精灵 */
                    strcpy( g_szBlockName[iOneIndex], dMakeSpriteName( "PictureBlock", 	g_iBlockState[iLoopY][iLoopX] ) );
                    // 将该精灵移动到对应的位置
                    MoveSpriteToBlock( g_szBlockName[iOneIndex], iLoopX, iLoopY );
                }
                for( iLoop = iRandIndex; iLoop < iDataCount - 1; iLoop++ )
                {
                    iRandData[iLoop] = iRandData[iLoop + 1];
                }
                // 剩余有效值总数减一
                iDataCount--;
            }
        }
    }
    if(KEY_Q == iKey)
    {
//        for(int item=0; item<BLOCK_COUNT*BLOCK_COUNT; item++)
//        {
            char szName[100]="PictureBlock",str[10];
            int len_1=strlen(szName),len_2=0;
            int cmp=item+1;
            while(cmp>0)
            {
                str[len_2++]=(cmp%10)+'0';
                cmp/=10;
            }
            for(int item=0; item<len_2; item++)
            {
                szName[len_1+item]=str[len_2-1-item];
            }
//            MoveSpriteToBlock(g_szBlockName[item],item%BLOCK_COUNT,item/BLOCK_COUNT);
//        }
        int len=0;
        for( iLoopY = 0; iLoopY < BLOCK_COUNT; iLoopY++ )
        {
            for( iLoopX = 0; iLoopX < BLOCK_COUNT; iLoopX++ )
            {
                iOneIndex	=	XYToOneIndex( iLoopX, iLoopY );
                // 数组的最后一个
                if( BLOCK_COUNT - 1 == iLoopX && BLOCK_COUNT - 1 == iLoopY )
                {
                    g_iBlockState[iLoopY][iLoopX] = 0;
                    g_szBlockName[iOneIndex][0] = '\0';
                }
                else
                {
                    // 在当前剩余未使用到的数值里随机一个出来,赋值给二维数组
                    iRandIndex	=	len++;
                    g_iBlockState[iLoopY][iLoopX] = iRandData[iRandIndex];
                    /* 	给对应的名字数组赋值。该名字的方块已经预先在地图里摆放好,因此只需要生成对应的名字即可,不用创建精灵 */
                    strcpy( g_szBlockName[iOneIndex], dMakeSpriteName( "PictureBlock", 	g_iBlockState[iLoopY][iLoopX] ) );
                    // 将该精灵移动到对应的位置
                    MoveSpriteToBlock( g_szBlockName[iOneIndex], iLoopX, iLoopY );
                }
            }
        }
        OnKeyDown(iKey, iAltPress, iShiftPress, iCtrlPress);
    }
}
//==========================================================================
//
// 引擎捕捉键盘弹起消息后,将调用到本函数
// 参数 iKey:弹起的键,值见 enum KeyCodes 宏定义
//
    void dOnKeyUp( const int iKey )
    {
        // 可以在此添加游戏需要的响应函数
        OnKeyUp(iKey);
    }

//===========================================================================
//
// 引擎捕捉到精灵与精灵碰撞之后,调用此函数
// 精灵之间要产生碰撞,必须在编辑器或者代码里设置精灵发送及接受碰撞
// 参数 szSrcName:发起碰撞的精灵名字
// 参数 szTarName:被碰撞的精灵名字
//
    void dOnSpriteColSprite( const char *szSrcName, const char *szTarName )
    {
        // 可以在此添加游戏需要的响应函数
        OnSpriteColSprite(szSrcName, szTarName);
    }

//===========================================================================
//
// 引擎捕捉到精灵与世界边界碰撞之后,调用此函数.
// 精灵之间要产生碰撞,必须在编辑器或者代码里设置精灵的世界边界限制
// 参数 szName:碰撞到边界的精灵名字
// 参数 iColSide:碰撞到的边界 0 左边,1 右边,2 上边,3 下边
//
    void dOnSpriteColWorldLimit( const char *szName, const int iColSide )
    {
        // 可以在此添加游戏需要的响应函数
        OnSpriteColWorldLimit(szName, iColSide);
    }

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值