用一个链表保存所有的炸弹水滴列表,
x 轴从左到右 递增; y轴从上到下递增;
每次刷新所有炸弹的状态,如果和水滴碰撞了,则该炸弹消失,出现4个新水滴炸弹,将新炸弹用新链表存储,和老的炸弹链表合并,
为什么要用新链表来保存,stl的list不支持在遍历的时候插入新项
利用矩形和圆形是否相交 判断来判断相撞,水滴看做纯圆形
利用组合的次数和当前剩余的4滴水的数目作为评价剩余水滴局面好坏的标准
#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)