十滴水游戲 C++ 源代碼 - 我的一種實現

x 軸從左到右 遞增； y軸從上到下遞增；

#ifndef _POS_H_

#define _POS_H_

struct Pos
{

Pos()
{
}

Pos( int iX, int iY ) : iXPos( iX ), iYPos( iY )
{
}

int iXPos;

int iYPos;
};

#endif

#ifndef _DROP_H_

#define _DROP_H_

#include "Pos.h"

struct  Drop
{
void assign( const Pos& stCurPos,  int iDropCount  )
{
stCenter = stCurPos;
iDropCount = iDropCount;
}

bool operator == ( const Drop& other  )
{
return ( stCenter.iXPos == other.stCenter.iXPos
&& stCenter.iYPos == other.stCenter.iYPos
&& iDropCount == other.iDropCount );
}

bool operator != ( const Drop& other  )
{
return !( *this == other );
}

void setDropCount( int iDC )
{
iDropCount = iDC;
}

Pos stCenter;

int iDropCount;
};

#endif

#ifndef _BOMB_H_

#define _BOMB_H_

#include "Pos.h"

#include "CommData.h"

struct   Bomb
{

public:

void assign( const Pos& stCurPos, Direction d  );

int  move( int iMaxX, int iMaxY, int iWidth, int iHeight   );

int outOfGrid(  int iMaxX, int iMaxY,  int iWidth, int iHeight );

public:

Pos stCenter;

Direction iDirection; //  0 left, 1 right, 2 up, 3 down

};

#endif

#include "Bomb.h"

#include <iostream>

using namespace std;

void Bomb::assign( const Pos& stCurPos,  Direction d  )
{
stCenter =  stCurPos;
iDirection = d;
}

int  Bomb::move( int iMaxX, int iMaxY, int iWidth, int iHeight  )
{
stCenter.iXPos += iDirectionPlus[ 2 * iDirection ];

stCenter.iYPos += iDirectionPlus[ 2 * iDirection + 1 ];

//cout << "stCenter.iXPos is " << stCenter.iXPos
// << ", stCenter.iYPos is " << stCenter.iYPos   << endl;

return outOfGrid( iMaxX, iMaxY , iWidth, iHeight );
}

int Bomb::outOfGrid(  int iMaxX, int iMaxY, int iWidth, int iHeight  )
{
if ( stCenter.iXPos <= 0 )
{
return 1;
}
else if ( stCenter.iXPos >= iMaxX - iWidth / 2  )
{
return 2;
}
else if ( stCenter.iYPos <= 0 )
{
return 3;
}
else if ( stCenter.iYPos >= iMaxY - iHeight / 2  )
{
return 4;
}

return 0;
}

#ifndef _COMM_DATA_H_

#define _COMM_DATA_H_

const int iStep = 1;

const int iDirectionPlus[]  = { 0, 0, -iStep, 0, iStep, 0, 0, -iStep, 0, iStep  } ;

enum Direction { No_Direction = 0, Left , Right, Up, Down };

enum  ComboEffect { No_Effect,  Double  , Tripple, Excellent,  HolyShit, GodLike  };

const int iColumn = 6;

const int iRow = 6;

const int iScale = 1;

const int iDropWidth = iStep * iScale * 24;

const int iDropHeight = iStep * iScale * 12;

const int iBombWidth = iStep * iScale * 6;

const int iBombHeight = iStep * iScale * 6;

const int iXStartPos = 0;

const int iYStartPos = 0;

const int iBombLimit = 5; // 5滴水時爆炸

const int iBombDropCount = 1;

#endif

#ifndef _UTIL_H_

#define _UTIL_H_

#include "Pos.h"

#define MY_ABS(x)   ((x)>0?(x):-(x))

int interRect( const Pos& stCenter1, int iWidth1, int iHeight1,
const Pos& stCenter2, int iWidth2, int iHeight2  );

int interRectCircle( const Pos& stCenter1, int iWidth1, int iHeight1,
const Pos& stCenter2, int iR );

#endif

#include "Util.h"

using namespace std;

#include "Util.h"

using namespace std;

int interRect( const Pos& stCenter1, int iWidth1, int iHeight1,
const Pos& stCenter2, int iWidth2, int iHeight2  )
{
if (   MY_ABS(  (  stCenter1.iXPos -  stCenter2.iXPos ) * 2  ) <  iWidth1 +  iWidth2
&&   MY_ABS(  (  stCenter1.iYPos -  stCenter2.iYPos ) * 2  ) <  iHeight1 +  iHeight2 )
{
return 1;
}

return 0;
}

int interRectCircle( const Pos& stCenter1, int iWidth1, int iHeight1,
const Pos& stCenter2, int iR )
{
int iXabsDouble =  MY_ABS( (  stCenter1.iXPos -  stCenter2.iXPos ) ) * 2 ;
int iYabsDouble =  MY_ABS( (  stCenter1.iYPos -  stCenter2.iYPos ) ) * 2 ;

//首先判斷是否在矩形中心周圍的  w + 2 * iR 寬度的大矩形內

if (   iXabsDouble    <  iWidth1 + 2 * iR
&&  iYabsDouble   <  iHeight1 +  2 * iR )
{
//在大矩形內，查看是否在雞毛蒜皮的擴展矩形內

if ( iXabsDouble   < iWidth1  || iYabsDouble   < iHeight1 )
{
return 1;
}

//不在擴展矩形內，只能算距離了，是否在  1 / 4 圓內

if ( (  iXabsDouble  - iWidth1    )  * ( iXabsDouble  - iWidth1    )
+ ( iYabsDouble  - iHeight1    )  * ( iYabsDouble  - iHeight1    )  < 4 * iR * iR )
{
return 1;
}
}

return 0;
}

#ifndef _GAME_STATE_H_

#define _GAME_STATE_H_

#include "Bomb.h"

#include "Drop.h"

#include "CommData.h"

#include <list>

using namespace std;

class GameState
{

public:

void init( const Pos& stOrig, int iBombLimit, int iColumn, int iRow,
int iDropWidth,int iDropHeight,  int iBombWidth , int iBombHeight );

int putOne( Drop * pCurGrid, int iIndex  );

void printAll();

void printGrid( Drop * pGrid , int iTotal, int iColumn   );

private:

void clearAll();

void getGridDrop( const Pos& stPos, int& iIndex  );

void updateAll();

private:

//原點位置，從左到右遞增X，從上到下遞增Y

Pos stOrigPos;

int iBombLimit;

int iColumn;

int iRow;

int iMaxX;

int iMaxY;

int iDropWidth;

int iDropHeight;

int iBombWidth;

int iBombHeight;

Drop * pGrid;

//當前的炸彈列表

list<Bomb> bombList;

//當前要展示的爆炸效果的位置列表

list<Pos> explodeList;

//當前要展示的撞地效果的位置列表

list<Pos> hitGroundList;

//組合效果

int  iCombo;

};

#include "GameState.h"

#include <iostream>

#include "Util.h"

using namespace std;

void  GameState::init( const Pos& stOrig, int iLimit, int iC, int iR,
int iDW, int iDH,  int iBW, int iBH )
{
stOrigPos = stOrig;
iBombLimit = iLimit;
iColumn = iC;
iRow = iR;

iMaxX = stOrigPos.iXPos + iColumn * iDW;
iMaxY = stOrigPos.iYPos + iRow * iDH;

//cout << "iMaxX  is " << iMaxX  << endl;

//cout << "iMaxY is " << iMaxY << endl;

iDropWidth = iDW;
iDropHeight = iDH;

iBombWidth = iBW;
iBombHeight = iBH;

}

void  GameState::getGridDrop( const Pos& stPos, int& iIndex )
{
int iXIndex =  ( stPos.iXPos - stOrigPos.iXPos ) / iDropWidth;

int iYIndex =  ( stPos.iYPos - stOrigPos.iYPos ) / iDropHeight;

iIndex = iColumn * iYIndex + iXIndex;

}

void GameState::printAll()
{
// 打印所有的雨滴

cout << "the rain drop are as follows "  << endl;

printGrid(   pGrid ,  iColumn * iRow  ,   iColumn   );

//打印所有的炸彈

list<Bomb>::iterator itr = bombList.begin();

cout << "the bomb are as follows : "  << endl;

for ( ; itr != bombList.end() ; ++itr )
{
cout << "( " <<  itr->stCenter.iXPos << " ,  "
<< itr->stCenter.iYPos   << " )  " << endl;
}

//打印所有的爆炸效果

list<Pos>::iterator itr1 = explodeList.begin();

cout << "the explodeList  are as follows : "  << endl;

for ( ; itr1 != explodeList.end() ; ++itr1 )
{
cout << "( " <<  itr1->iXPos << " ,  "
<< itr1->iYPos   << " )  " << endl;
}

explodeList.clear();

//打印所有的撞地效果

itr1 = hitGroundList.begin();

cout << "the hitGroundList  are as follows : "  << endl;

for ( ; itr1 != hitGroundList.end() ; ++itr1 )
{
cout << "( " <<  itr1->iXPos << " ,  "
<< itr1->iYPos   << " )  " << endl;
}

hitGroundList.clear();
}

void GameState::updateAll()
{
//更新炸彈列表所有的狀態

int iMoveResult = 0;

int iCurIndex = 0;

Bomb stCurBomb;

list<Bomb> bombNew;

list<Bomb>::iterator itr = bombList.begin();

//iDropWidth should lager than  iBombLimit  !!!!!!

int iMin = iDropHeight > iDropWidth ? iDropWidth : iDropHeight;

int iR = iMin / ( iBombLimit - 1 );

for ( ; itr != bombList.end() ;  )
{
iMoveResult = itr->move( iMaxX, iMaxY,
iBombWidth,  iBombHeight );

//檢查是否撞上了雨滴

if ( iMoveResult == 0 )
{
getGridDrop( itr->stCenter, iCurIndex  );

Drop &stCurDrop = pGrid[ iCurIndex ];

//cout << "iCurIndex is " << iCurIndex  <<  ", stCurBomb.stCenter.iXPos is "
// << stCurBomb.stCenter.iXPos  <<  ", stCurBomb.stCenter.iYPos is "
// << stCurBomb.stCenter.iYPos    << endl;

int iCurDropCount = stCurDrop.iDropCount;

//if (  iCurDropCount > 0
// && interRect( itr->stCenter, iBombWidth, iBombHeight,
// stCurDrop.stCenter,  iDropWidthScale *  iCurDropCount  ,
// iDropHeightScale   *  iCurDropCount )  )
if (  iCurDropCount > 0
&& interRectCircle( itr->stCenter, iBombWidth, iBombHeight,
stCurDrop.stCenter,  iR *  iCurDropCount / 2  )  )
{
// 撞上了，遞增之

//cout << "iCurIndex is " << iCurIndex  <<  ", stCurBomb.stCenter.iXPos is "
//<< itr->stCenter.iXPos  <<  ", stCurBomb.stCenter.iYPos is "
//<< itr->stCenter.iYPos   << ", iR is " <<  iR *  iCurDropCount / 2  << endl;

iCurDropCount +=  iBombDropCount;

//cout << "iCurDrop is " << iCurDrop
// << ", iBombLimit is " << iBombLimit   << endl;

bombList.erase(  itr++ );

if (  iCurDropCount < iBombLimit )
{
stCurDrop.iDropCount = iCurDropCount;

//炸彈被吸收
}
else
{
//cout << "bomb explode  iCurIndex  is " << iCurIndex
// << ", stCurDrop.stCenter's iXPos is " << stCurDrop.stCenter.iXPos
// << ", stCurDrop.stCenter's iYPos is " << stCurDrop.stCenter.iYPos
// << endl;

iCombo++;

stCurDrop.setDropCount( 0 );

//炸彈被吸收 產生4個炸彈

for ( int i =   Left; i <=  Down; ++i  )
{
stCurBomb.assign( stCurDrop.stCenter,  Direction( i ) );

bombNew.push_back( stCurBomb );
}
}
}
else // 沒有撞上雨滴，位置變化了
{
itr++;
}
}
else // if ( iMoveResult > 0  )
{
// //沒有裝上雨滴，撞地上了,展示撞地效果

//cout << "seq : " << itr->iBombId << " hit ground , iMoveResult is  "
// << iMoveResult << endl;

hitGroundList.push_back( itr->stCenter );

bombList.erase(  itr++ );

}
}

if ( !bombNew.empty() )
{
bombList.splice(  bombList.end(), bombNew );
}
}

int GameState::putOne( Drop * pCurGrid, int iIndex  )
{
pGrid = pCurGrid;

clearAll();

Drop stDrop = pCurGrid[ iIndex ];

Bomb stCurBomb;

if ( stDrop.iDropCount + iBombDropCount >= iBombLimit )
{
iCombo++ ;

pCurGrid[ iIndex ].setDropCount( 0 ) ;

for ( int i =  Left; i <=  Down; ++i  )
{
stCurBomb.assign( stDrop.stCenter,   Direction( i ) );

bombList.push_back( stCurBomb );
}
}

//printAll();

while (  !bombList.empty() )
{
//cout << "begin one loop " << endl;

updateAll();

//printAll();
}

//打印Combo等效果列表

int iCurCombo = iCombo;

cout << "iCombo is " << int( iCombo ) << endl;

iCombo  =  0;

return iCurCombo;
}

void GameState::printGrid( Drop * pInputGrid , int iTotal, int iColumnInput   )
{
for ( int i = 0; i < iTotal; ++i )
{
if ( (  i + 1 )  %  iColumnInput == 0 )
{
cout << pInputGrid[ i ].iDropCount   << endl;
}
else
{
cout << pInputGrid[ i ].iDropCount << " ";
}
}

cout << endl;
}

void GameState::clearAll()
{
bombList.clear();

//當前要展示的爆炸效果的位置列表

explodeList.clear();

//當前要展示的撞地效果的位置列表

hitGroundList.clear();

//組合效果

iCombo = 0;

}

#endif

#include <iostream>

#include "GameState.h"

using namespace std;

int iInputGrid [] = {
4, 4, 4, 3, 0, 0,
2, 2, 4, 3, 4, 2,
3, 2, 0, 0, 0, 3,
0, 1, 3, 2, 1, 3,
2, 2, 1, 4, 1, 4,
3, 2, 1, 3, 4, 0 };

void evaluateGrid( Drop * pGrid, int iTotal, int iTotalBomb, int iBombLimit,   int& iResult )
{
iResult =  iTotalBomb * 100;

int iDropCount = 0;

for ( int i = 0; i < iTotal; ++i  )
{
iDropCount = pGrid[ i ].iDropCount;

if ( iDropCount  == iBombLimit - 1 )
{
// 對於4滴的水，給分高一點

iResult += iDropCount * 2;
}
else
{
iResult += iDropCount;
}
}
}

int main( int argc, char **argv )
{

int iTotal = sizeof ( iInputGrid ) / sizeof ( int ) ;

Drop * pInitGrid = new Drop[ iTotal ];

int i = 0;

for (  ; i < iTotal ; ++i  )
{
pInitGrid[i].stCenter.iXPos = ( 2 * ( i  % iColumn )  + 1 ) *   iDropWidth / 2    ;

pInitGrid[i].stCenter.iYPos = ( 2 * ( i  /  iRow ) + 1 ) *  iDropHeight / 2      ;

pInitGrid[i].iDropCount = iInputGrid[ i ];

//pInitGrid[i].iHeight = iDropHeight;

//pInitGrid[i].iWidth = iDropWidth;

//cout << " i is " << i << ",  pInitGrid[i].stCenter.iXPos  is " <<  pInitGrid[i].stCenter.iXPos
// << ",  pInitGrid[i].stCenter.iYPos  is " <<  pInitGrid[i].stCenter.iYPos  << endl;

}

Drop * pGrid = new Drop[ iTotal ];

int iMaxResult = 0;

int iMaxPos = 0;

GameState stState;

stState.init(  Pos( iXStartPos, iYStartPos ), iBombLimit, iColumn, iRow, iDropWidth, iDropHeight,
iBombWidth, iBombHeight   );

i = 0;

int iResult = 0;

for (  ; i <  iTotal  ; ++i  )
{
memcpy( pGrid, pInitGrid,  iTotal * sizeof ( Drop )   );

if ( pGrid[ i ].iDropCount + iBombDropCount >= iBombLimit )
{
int iTotalBomb = stState.putOne( pGrid, i );

evaluateGrid( pGrid, iTotal, iTotalBomb, iBombLimit,  iResult );

cout <<  "evaluateGrid return : " <<  iResult << endl;

if ( iMaxResult < iResult )
{
iMaxResult = iResult;

iMaxPos = i;
}
}
}

cout << "iMaxPos is " << iMaxPos << ", iMaxResult is " << iMaxResult    << endl;

delete []pGrid;

delete []pInitGrid;

return 0;
}

inc.mk

CC= gcc
CXX = g++
CFLAGS = -Wall -g -DDEBUG_LOG_ARGS -Wno-deprecated

.%.d: %.cpp
@echo "update \$@ ..."; \
echo -en \$< | sed s/\.cpp/\.o:/ > \$@; \
\$(CC) \$(INCLUDE) -MM \$< | sed '1s/.*.://' >> \$@;

%.o: %.cpp
\$(CXX) \$(CFLAGS) \$(INCLUDE) -o \$@ -c \$<

.%.d: %.c
@echo "update \$@ ..."; \
echo -en \$< | sed s/\.c/\.o:/ > \$@; \
\$(CC) \$(INCLUDE) -MM \$< | sed '1s/.*.://' >> \$@;

%.o: %.c
\$(CC) \$(CFLAGS) \$(INCLUDE) -o \$@ -c \$<

#----------------------------------------------------------------------------------

makefile

include ./Inc.mk

EXE = ./a.out

all : \$(EXE)

INCLUDE := \$(INCLUDE)
LIBS   :=

CPPS    =  \$(wildcard *.cpp)
OBJS   :=  \$(patsubst %.cpp, %.o, \$(CPPS))
DEPS    =  \$(patsubst %.o, .%.d, \$(OBJS))

#####################################################################################

\$(EXE): \$(OBJS)
\$(CXX) \$(CFLAGS) -o \$@ \$^ \$(LIBS)

install:
echo "install. do nothing..."
echo \$(CPPS)
echo \$(OBJS)
echo \$(DEPS)

clean:
rm -vf *.o .*.d \$(EXE) \$(EXEX) \$(OBJS) \$(OBJSEX)

-include \$(DEPS)