Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16502836
  • 博文数量: 5645
  • 博客积分: 9880
  • 博客等级: 中将
  • 技术积分: 68081
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 13:35
文章分类

全部博文(5645)

文章存档

2008年(5645)

我的朋友

分类:

2008-04-28 21:23:39

下载本文示例代码
  没有UI部分,要修改玩家人数,方块数,颜色,键盘配置请看CGameController的Start函数,  请大家提提意见,我想做成像上海热线的俄罗斯方块,支持网络对战。 //head file Diamond.h// Diamond.h: interface for the CDiamond class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_DIAMOND_H__1B1DE2E7_A3B8_4D43_9079_AF2AC021F899__INCLUDED_)#define AFX_DIAMOND_H__1B1DE2E7_A3B8_4D43_9079_AF2AC021F899__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000class IGame; //inteface of game ,one mean a playerclass IGameController; //inteface of game controller,control communication of playerstypedef CTypedPtrList<CObList,IGame*> CGames; //all player in the gameclass IGameController{//construction/destructionpublic:virtual ~IGameController(){};//public interfacepublic:virtual void OnEraseLines(IGame*,long) = 0 ; //when a player erase lines,call itvirtual void OnGameOver(IGame*) = 0 ; //when a player dies ,call it};//a block of a diamondstruct CBlock{long m_x ;long m_y ;};//class IGame:public CObject{//construction/destructionpublic:virtual ~IGame(){};//public interfacepublic:virtual void OnKey(long) = 0 ; //recieve key eventvirtual void Start() = 0 ; //recieve start eventvirtual bool IsOver()=0 ; //if the player die?virtual void OnEraseLines(IGame* fromGame,long lines)=0;/* called by the game controller when other player erase lines .*/virtual void Draw()=0; // draw self};//draw inteface class IDrawDrv{//construction/destructionpublic:virtual ~IDrawDrv(){};//public interfacepublic:virtual ShowBlocks(long x,long y,long xs,long ys)=0; //show blocksvirtual HideBlocks(long x,long y,long xs,long ys)=0; //hide blocks };//implement of IDrawDrv of Windowsclass CDrawDrvWindowsImp :public IDrawDrv{//construction/destructionpublic:CDrawDrvWindowsImp(POINT,COLORREF,COLORREF,long,CDC*);virtual ~CDrawDrvWindowsImp(){};private:CDrawDrvWindowsImp(const CDrawDrvWindowsImp&);void operator=(const CDrawDrvWindowsImp&);//public interface public:virtual ShowBlocks(long x,long y,long xs,long ys); virtual HideBlocks(long x,long y,long xs,long ys);//implementsprivate:POINT m_OrgPoint ; COLORREF m_BlockColor; //block colorCOLORREF m_BgColor; // bg colorlong m_BlockSize; // pts of a blockCDC* m_pDC; CBrush m_BlockBrush; CBrush m_BorderBrush;CBrush m_BgBrush;};//class CGameController:public IGameController{//construction/destructionpublic :CGameController();~CGameController();private:CGameController(const CGameController&);void operator=(const CGameController&);//public interfacepublic:virtual void OnEraseLines(IGame*,long) ;//called by players ,when them erase linesvirtual void OnGameOver(IGame*); //called by players,when them dievoid Start(CDC*); //start game!void Pause(); //pause game,or restart gamevoid End(); //end gamevoid OnDraw(); //paint eventvoid OnKey(long key); //key event//implements private:CGames m_Games;CDC* m_pDC;enum GamesStatus{STATUS_TO_START,STATUS_PLAYING,STATUS_PAUSE,STATUS_END};GamesStatus m_Status;void Clean();};class CKeyController //key config ,player can custome their key{//construction/destructionpublic:CKeyController(){};~CKeyController(){};private:void operator=(const CKeyController&);//public interface public:long RIGHT;long LEFT ;long DOWN;long NEXT;long DROP;long START;friend class CGame;friend class CGameController;//implements};//diamond class CDiamond{//construction/destructionpublic:static CDiamond* CreateAnInstance(long x,long y); //random create a diamondCDiamond(const CDiamond&); ~CDiamond();private :CDiamond();void operator=(const CDiamond&);//public interface public:long GetBlockCount(); //get blocks count, to support other type diamondsCBlock* GetBlock(long); // get a block ,by indexvoid Left(); // left a diamondvoid Right(); // right a diamondvoid Down(); //down a diamondvoid Next(); //retate a diamondvoid Draw(IDrawDrv*,bool); //draw a diamondlong GetStartX(){return m_x;}; //get start x positionlong GetStartY(){return m_y;}; // get start y position//implementsprivate:long m_x ;long m_y ;long m_index;long m_Blocks;CBlock* m_pBlocks;};//player of gameclass CGame:public IGame{//construction/destructionpublic:CGame(IGameController*,IDrawDrv*,CKeyController,long wBlocks,long hBlocks);virtual ~CGame();private:CGame(const CGame&);void operator=(const CGame&);//public interfacepublic:virtual void OnKey(long); //recieve key event virtual void Start(); //recieve start eventvirtual bool IsOver(); //if is die?virtual void OnEraseLines(IGame* fromGame,long lines);void Draw();//implements private: void Init(); //initvoid LeftDiamond(); void RightDiamond();bool CanDown();void DownDiamond();void NextDiamond();void DropDiamond();long EraseLines();long GetBlockInfo(long,long); //get block info of game ,1 mean is have block,0 mean no block,void SetBlockInfo(long x,long y,long v);void OnDownADiamond(); //called when a diamond can not down morebool IsValidDiamond(CDiamond*); //if the diamond is valid ?void Clean(); //resource cleanvoid Show();//debug //debug use,to print data struct of the playervoid OnGameOver(); private:long m_WidthBlocks ;long m_HeightBlocks ;long* m_pBlocks;CDiamond* m_pCurrDiamond; IGameController* m_pController;IDrawDrv* m_pDraw;CKeyController m_KeyCtl;enum GameStatus{STATUS_PLAYING,STATUS_GAMEOVER};GameStatus m_Status ;};#endif // !defined(AFX_DIAMOND_H__1B1DE2E7_A3B8_4D43_9079_AF2AC021F899__INCLUDED_)//implement Diamond.cpp// Diamond.cpp: implementation of the CDiamond class.////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "MDiamond.h"#include "Diamond.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif//block dataCBlock g_Blocks0[] = {{0,-1},{0,-2},{1,-1},{1,-2}};CBlock g_Blocks1[] = {{0,-1},{1,-1},{1,-2},{1,-3}};CBlock g_Blocks2[] = {{0,-2},{1,-2},{2,-2},{2,-1}};CBlock g_Blocks3[] = {{1,-1},{1,-2},{1,-3},{2,-3}};CBlock g_Blocks4[] = {{0,-1},{1,-1},{2,-1},{0,-2}};CBlock g_Blocks5[] = {{1,-1},{1,-2},{1,-3},{2,-1}};CBlock g_Blocks6[] = {{0,-1},{1,-1},{2,-1},{2,-2}};CBlock g_Blocks7[] = {{1,-1},{1,-2},{1,-3},{0,-3}};CBlock g_Blocks8[] = {{0,-1},{0,-2},{1,-2},{2,-2}};CBlock g_Blocks9[] = {{0,-1},{1,-1},{2,-1},{1,-2}};CBlock g_Blocks10[] = {{0,-2},{1,-1},{1,-2},{1,-3}};CBlock g_Blocks11[] = {{1,-1},{0,-2},{1,-2},{2,-2}};CBlock g_Blocks12[] = {{1,-1},{1,-2},{1,-3},{2,-2}};CBlock g_Blocks13[] = {{0,-1},{0,-2},{1,-2},{1,-3}};CBlock g_Blocks14[] = {{0,-2},{1,-2},{1,-1},{2,-1}};CBlock g_Blocks15[] = {{1,-1},{1,-2},{0,-2},{0,-3}};CBlock g_Blocks16[] = {{0,-1},{1,-1},{1,-2},{2,-2}};CBlock g_Blocks17[] = {{0,-1},{1,-1},{2,-1},{3,-1}};CBlock g_Blocks18[] = {{2,-1},{2,-2},{2,-3},{2,-4}};CBlock* g_Blocks[] = {g_Blocks0,g_Blocks1,g_Blocks2,g_Blocks3,g_Blocks4,g_Blocks5,g_Blocks6,g_Blocks7,g_Blocks8,g_Blocks9,g_Blocks10,g_Blocks11,g_Blocks12,g_Blocks13,g_Blocks14,g_Blocks15,g_Blocks16,g_Blocks17,g_Blocks18}; long g_BlockNexts[] = {0,2,3,4,1,6,7,8,5,10,11,12,9,14,13,16,15,18,17};//CDiamondCDiamond::CDiamond(){}CDiamond* CDiamond::CreateAnInstance(long x,long y){static int LastIndex = 0 ;CDiamond* d = new CDiamond();srand((unsigned)time(NULL) LastIndex);long index = rand() % 19 ;//long index = 17;d->m_Blocks = 4 ;d->m_index = index ;d->m_x = x;d->m_y = y;d->m_pBlocks = g_Blocks[index] ;LastIndex = index ;return d; }CDiamond::CDiamond(const CDiamond& d){m_x = d.m_x ;m_y = d.m_y ;m_index = d.m_index;m_Blocks = d.m_Blocks ;m_pBlocks = d.m_pBlocks ;}CDiamond::~CDiamond(){}long CDiamond::GetBlockCount(){return m_Blocks ;}CBlock* CDiamond::GetBlock(long i){return &m_pBlocks[i];}void CDiamond::Left(){m_x -- ;}void CDiamond::Right(){m_x ; }void CDiamond::Next(){m_index = g_BlockNexts[m_index];m_pBlocks = g_Blocks[m_index];}void CDiamond::Down(){m_y -- ;}void CDiamond::Draw(IDrawDrv* d,bool bShow=true){long count = GetBlockCount();for(int i=0;i<count;i ){CBlock* b = GetBlock(i);if(bShow){d->ShowBlocks(m_x b->m_x,m_y b->m_y,1,1);}else{d->HideBlocks(m_x b->m_x,m_y b->m_y,1,1); }}}//CGameCGame::CGame(IGameController* p,IDrawDrv* d,CKeyController key,long wBlocks,long hBlocks): m_WidthBlocks(wBlocks),m_HeightBlocks(hBlocks),m_KeyCtl(key){m_pController = p ;//pointers,need to be cleanm_pBlocks = NULL;m_pCurrDiamond = NULL;m_pDraw = d ;Init();}void CGame::OnKey(long keycode){if(keycode==-1) //-1 mean down {DownDiamond();}if(keycode==m_KeyCtl.LEFT){LeftDiamond();}if(keycode==m_KeyCtl.RIGHT){RightDiamond();}if(keycode==m_KeyCtl.DOWN){DownDiamond();}if(keycode==m_KeyCtl.NEXT){NextDiamond(); }if(keycode==m_KeyCtl.DROP){DropDiamond();}}CGame::~CGame(){Clean();}void CGame::Init(){if(NULL==m_pBlocks){long count = m_WidthBlocks * m_HeightBlocks ;m_pBlocks = new long[count];for(int i=0 ;i<count;i ){m_pBlocks[i] = 0;}}if(NULL==m_pCurrDiamond){m_pCurrDiamond = CDiamond::CreateAnInstance(m_WidthBlocks/2,m_HeightBlocks);}}void CGame::Clean(){if(m_pCurrDiamond!=NULL) delete m_pCurrDiamond;if(m_pBlocks!=NULL) delete [] m_pBlocks;if(m_pDraw!=NULL) delete m_pDraw ;}void CGame::Start(){Init();m_Status = STATUS_PLAYING; }bool CGame::IsOver(){return (STATUS_GAMEOVER==m_Status) ;}void CGame::OnGameOver(){m_Status = STATUS_GAMEOVER;}void CGame::OnEraseLines(IGame* fromGame,long lines){static int seed = 0 ;int i ;int j ;int AddLines = lines - 1;//random add lines to self//check if die for(i=0;i<m_WidthBlocks;i ){for(j=(m_HeightBlocks-AddLines);j<m_HeightBlocks;j ){if(1==GetBlockInfo(i,j)) {OnGameOver();return ;}}}//add linesfor(i=0;i<m_WidthBlocks;i ){for(j=m_HeightBlocks-1;j>=AddLines;j--){SetBlockInfo(i,j,GetBlockInfo(i,j-AddLines));}}for(i=0;i<m_WidthBlocks;i ){srand((unsigned)time(NULL) seed);long v = rand() % 2 ;for(j=0;j<AddLines;j ){SetBlockInfo(i,j,v);}seed ;}//fixed for(i=0;i<AddLines;i ){srand((unsigned)time(NULL) seed);int x = rand() % m_WidthBlocks ;SetBlockInfo(x,i,1);seed ;x = m_WidthBlocks - 1 - x ;SetBlockInfo(x,i,0);}Draw();}long CGame::GetBlockInfo(long x,long y){if(y>=m_HeightBlocks) return -1 ; //out of game panellong pos = y * m_WidthBlocks x ;return m_pBlocks[pos] ;}void CGame::SetBlockInfo(long x,long y,long v){if(x>=m_WidthBlocks || y>=m_HeightBlocks) return ; //out of game panellong pos = y * m_WidthBlocks x ;m_pBlocks[pos] = v ;}bool CGame::IsValidDiamond(CDiamond* d){long x = d->GetStartX();long y = d->GetStartY();CBlock* b;for(int i=0;i<d->GetBlockCount();i ){b = d->GetBlock(i);if((x b->m_x)<0) return false; //left checkif((x b->m_x)>=m_WidthBlocks) return false; //right checkif((y b->m_y)>=m_HeightBlocks) return false; //top checkif((y b->m_y)<0) return false; //bottom checkif(1==GetBlockInfo(x b->m_x,y b->m_y)) return false; //block check }return true;}void CGame::LeftDiamond(){CDiamond t(*m_pCurrDiamond);t.Left();if(IsValidDiamond(&t)){m_pCurrDiamond->Draw(m_pDraw,false); m_pCurrDiamond->Left();m_pCurrDiamond->Draw(m_pDraw); }}void CGame::RightDiamond(){CDiamond t(*m_pCurrDiamond);t.Right();if(IsValidDiamond(&t)){m_pCurrDiamond->Draw(m_pDraw,false); //hidem_pCurrDiamond->Right();m_pCurrDiamond->Draw(m_pDraw);}}void CGame::NextDiamond(){CDiamond t(*m_pCurrDiamond);t.Next();if(IsValidDiamond(&t)){m_pCurrDiamond->Draw(m_pDraw,false); //m_pCurrDiamond->Next(); m_pCurrDiamond->Draw(m_pDraw); }}bool CGame::CanDown(){CDiamond t(*m_pCurrDiamond);t.Down();return IsValidDiamond(&t);}void CGame::DropDiamond(){m_pCurrDiamond->Draw(m_pDraw,false);while(CanDown()){m_pCurrDiamond->Down();}OnDownADiamond();}void CGame::DownDiamond(){if(!CanDown()){OnDownADiamond();}else{m_pCurrDiamond->Draw(m_pDraw,false);m_pCurrDiamond->Down(); m_pCurrDiamond->Draw(m_pDraw); } }void CGame::OnDownADiamond(){CBlock* b ;for(int i=0;i<m_pCurrDiamond->GetBlockCount();i ){b = m_pCurrDiamond->GetBlock(i);SetBlockInfo(m_pCurrDiamond->GetStartX() b->m_x,m_pCurrDiamond->GetStartY() b->m_y,1);}long lines = EraseLines();if(lines>0) {m_pController->OnEraseLines(this,lines); }delete m_pCurrDiamond;m_pCurrDiamond = CDiamond::CreateAnInstance(m_WidthBlocks/2,m_HeightBlocks);if(!IsValidDiamond(m_pCurrDiamond)){OnGameOver(); return ;}Draw();}long CGame::EraseLines(){long count = m_WidthBlocks * m_HeightBlocks ;long* pNewBlocks = new long[count];for(int ii=0 ;ii<count;ii ){pNewBlocks[ii] = 0;}bool bErase ;int lines = 0 ;int fillLines = 0 ; for(int i=0 ;i<m_HeightBlocks;i ){bErase = true ;for(int j=0;j<m_WidthBlocks;j ){if(0==GetBlockInfo(j,i)) {bErase = false;break;}}if(bErase){lines ;}else{memcpy(&pNewBlocks[m_WidthBlocks*fillLines],&m_pBlocks[m_WidthBlocks*i],sizeof(long)*m_WidthBlocks);fillLines ;}}delete []m_pBlocks ;m_pBlocks = pNewBlocks ;return lines ;}void CGame::Show(){CString s = "" ;CString a ;for(int i=0;i<m_HeightBlocks;i ){for(int j=0;j<m_WidthBlocks;j ){if(1==GetBlockInfo(j,i)){s = "1," ;}else{s = "0," ;}}s = "\n" ;}AfxMessageBox(s);}void CGame::Draw(){for(int i=0;i<m_HeightBlocks;i ){for(int j=0;j<m_WidthBlocks;j ){if(GetBlockInfo(j,i)==1){m_pDraw->ShowBlocks(j,i,1,1);}else{m_pDraw->HideBlocks(j,i,1,1);}}}m_pCurrDiamond->Draw(m_pDraw); }//=class:CDrawDrvWindowsImp=//CDrawDrvWindowsImp::CDrawDrvWindowsImp(POINT p,COLORREF block_color,COLORREF bg_color,long block_size,CDC* pDC):m_OrgPoint(p),m_BlockColor(block_color),m_BgColor(bg_color),m_BlockSize(block_size),m_BlockBrush(block_color),m_BgBrush(bg_color),m_BorderBrush(RGB(255,255,255)) {m_pDC = pDC;}CDrawDrvWindowsImp::ShowBlocks(long x,long y,long xs,long ys){RECT rect;rect.left = m_OrgPoint.x x * m_BlockSize; rect.top = m_OrgPoint.y - ( y 1) * m_BlockSize ; rect.right = rect.left xs * m_BlockSize ;rect.bottom = rect.top ys * m_BlockSize ;m_pDC->FillRect(&rect,&m_BorderBrush);rect.left ;rect.top ;m_pDC->FillRect(&rect,&m_BlockBrush);}CDrawDrvWindowsImp::HideBlocks(long x,long y,long xs,long ys){RECT rect;rect.left = m_OrgPoint.x x * m_BlockSize; rect.top = m_OrgPoint.y - ( y 1) * m_BlockSize ; rect.right = rect.left xs * m_BlockSize ;rect.bottom = rect.top ys * m_BlockSize ;m_pDC->FillRect(&rect,&m_BgBrush);}//CGameControllerCGameController::CGameController(){m_Status = STATUS_TO_START;}CGameController::~CGameController(){Clean();}void CGameController::Clean(){POSITION pos ;pos = m_Games.GetHeadPosition();IGame* p;while(pos){p = m_Games.GetNext(pos);delete p ;}}void CGameController::OnEraseLines(IGame* pFromGame,long lines) {if(lines<2){return ;}POSITION pos ;pos = m_Games.GetHeadPosition();IGame* p;while(pos){p = m_Games.GetNext(pos);if(p!=pFromGame){if(!p->IsOver()) {p->OnEraseLines(pFromGame,lines); }}}}void CGameController::OnGameOver(IGame* pGame) {POSITION pos ;pos = m_Games.GetHeadPosition();IGame* p;bool bEnd = true;while(pos){p = m_Games.GetNext(pos);if(p->IsOver()) {bEnd = false; }}if(bEnd){End();}}void CGameController::Start(CDC* pDC){IGame* pGame;IDrawDrv* pDraw;long BlockSize;long WidthBlocks;long HeightBlocks;COLORREF BlockColor;COLORREF BgColor;POINT StartPos ;CKeyController key ;//game0BlockSize = 18 ;WidthBlocks = 14;HeightBlocks = 20 ;BlockColor = RGB(255,0,0);BgColor = RGB(160,0,0);StartPos.x = 10 ;StartPos.y = 60 BlockSize * HeightBlocks ; key.DOWN = 'S' ; key.LEFT = 'A' ;key.RIGHT ='D';key.NEXT = 'W';key.DROP = 'G' ;pDraw = new CDrawDrvWindowsImp(StartPos,BlockColor,BgColor,BlockSize,pDC); pGame = new CGame(this,pDraw,key,WidthBlocks,HeightBlocks);m_Games.AddTail(pGame);//game1BlockSize = 18 ;WidthBlocks = 14;HeightBlocks = 20 ;BlockColor = RGB(255,0,0);BgColor = RGB(160,0,0);StartPos.x = 350 ;StartPos.y = 60 BlockSize * HeightBlocks ; key.DOWN = 40 ; key.LEFT = 37 ;key.RIGHT = 39;key.NEXT = 38;key.DROP = 'L' ;pDraw = new CDrawDrvWindowsImp(StartPos,BlockColor,BgColor,BlockSize,pDC); pGame = new CGame(this,pDraw,key,WidthBlocks,HeightBlocks);m_Games.AddTail(pGame);m_Status = STATUS_PLAYING;}void CGameController::Pause(){if(m_Status == STATUS_PAUSE){m_Status = STATUS_PLAYING;}else{m_Status = STATUS_PAUSE;}} void CGameController::End(){m_Status = STATUS_END;Clean();}void CGameController::OnDraw(){POSITION pos ;pos = m_Games.GetHeadPosition();IGame* p;while(pos){p = m_Games.GetNext(pos);if(!p->IsOver()) {p->Draw(); }}}void CGameController::OnKey(long keycode){if(m_Status!=STATUS_PLAYING) return ;POSITION pos ;pos = m_Games.GetHeadPosition();IGame* p;while(pos){p = m_Games.GetNext(pos);if(!p->IsOver()) {p->OnKey(keycode); }}}   没有UI部分,要修改玩家人数,方块数,颜色,键盘配置请看CGameController的Start函数,  请大家提提意见,我想做成像上海热线的俄罗斯方块,支持网络对战。 //head file Diamond.h// Diamond.h: interface for the CDiamond class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_DIAMOND_H__1B1DE2E7_A3B8_4D43_9079_AF2AC021F899__INCLUDED_)#define AFX_DIAMOND_H__1B1DE2E7_A3B8_4D43_9079_AF2AC021F899__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000class IGame; //inteface of game ,one mean a playerclass IGameController; //inteface of game controller,control communication of playerstypedef CTypedPtrList<CObList,IGame*> CGames; //all player in the gameclass IGameController{//construction/destructionpublic:virtual ~IGameController(){};//public interfacepublic:virtual void OnEraseLines(IGame*,long) = 0 ; //when a player erase lines,call itvirtual void OnGameOver(IGame*) = 0 ; //when a player dies ,call it};//a block of a diamondstruct CBlock{long m_x ;long m_y ;};//class IGame:public CObject{//construction/destructionpublic:virtual ~IGame(){};//public interfacepublic:virtual void OnKey(long) = 0 ; //recieve key eventvirtual void Start() = 0 ; //recieve start eventvirtual bool IsOver()=0 ; //if the player die?virtual void OnEraseLines(IGame* fromGame,long lines)=0;/* called by the game controller when other player erase lines .*/virtual void Draw()=0; // draw self};//draw inteface class IDrawDrv{//construction/destructionpublic:virtual ~IDrawDrv(){};//public interfacepublic:virtual ShowBlocks(long x,long y,long xs,long ys)=0; //show blocksvirtual HideBlocks(long x,long y,long xs,long ys)=0; //hide blocks };//implement of IDrawDrv of Windowsclass CDrawDrvWindowsImp :public IDrawDrv{//construction/destructionpublic:CDrawDrvWindowsImp(POINT,COLORREF,COLORREF,long,CDC*);virtual ~CDrawDrvWindowsImp(){};private:CDrawDrvWindowsImp(const CDrawDrvWindowsImp&);void operator=(const CDrawDrvWindowsImp&);//public interface public:virtual ShowBlocks(long x,long y,long xs,long ys); virtual HideBlocks(long x,long y,long xs,long ys);//implementsprivate:POINT m_OrgPoint ; COLORREF m_BlockColor; //block colorCOLORREF m_BgColor; // bg colorlong m_BlockSize; // pts of a blockCDC* m_pDC; CBrush m_BlockBrush; CBrush m_BorderBrush;CBrush m_BgBrush;};//class CGameController:public IGameController{//construction/destructionpublic :CGameController();~CGameController();private:CGameController(const CGameController&);void operator=(const CGameController&);//public interfacepublic:virtual void OnEraseLines(IGame*,long) ;//called by players ,when them erase linesvirtual void OnGameOver(IGame*); //called by players,when them dievoid Start(CDC*); //start game!void Pause(); //pause game,or restart gamevoid End(); //end gamevoid OnDraw(); //paint eventvoid OnKey(long key); //key event//implements private:CGames m_Games;CDC* m_pDC;enum GamesStatus{STATUS_TO_START,STATUS_PLAYING,STATUS_PAUSE,STATUS_END};GamesStatus m_Status;void Clean();};class CKeyController //key config ,player can custome their key{//construction/destructionpublic:CKeyController(){};~CKeyController(){};private:void operator=(const CKeyController&);//public interface public:long RIGHT;long LEFT ;long DOWN;long NEXT;long DROP;long START;friend class CGame;friend class CGameController;//implements};//diamond class CDiamond{//construction/destructionpublic:static CDiamond* CreateAnInstance(long x,long y); //random create a diamondCDiamond(const CDiamond&); ~CDiamond();private :CDiamond();void operator=(const CDiamond&);//public interface public:long GetBlockCount(); //get blocks count, to support other type diamondsCBlock* GetBlock(long); // get a block ,by indexvoid Left(); // left a diamondvoid Right(); // right a diamondvoid Down(); //down a diamondvoid Next(); //retate a diamondvoid Draw(IDrawDrv*,bool); //draw a diamondlong GetStartX(){return m_x;}; //get start x positionlong GetStartY(){return m_y;}; // get start y position//implementsprivate:long m_x ;long m_y ;long m_index;long m_Blocks;CBlock* m_pBlocks;};//player of gameclass CGame:public IGame{//construction/destructionpublic:CGame(IGameController*,IDrawDrv*,CKeyController,long wBlocks,long hBlocks);virtual ~CGame();private:CGame(const CGame&);void operator=(const CGame&);//public interfacepublic:virtual void OnKey(long); //recieve key event virtual void Start(); //recieve start eventvirtual bool IsOver(); //if is die?virtual void OnEraseLines(IGame* fromGame,long lines);void Draw();//implements private: void Init(); //initvoid LeftDiamond(); void RightDiamond();bool CanDown();void DownDiamond();void NextDiamond();void DropDiamond();long EraseLines();long GetBlockInfo(long,long); //get block info of game ,1 mean is have block,0 mean no block,void SetBlockInfo(long x,long y,long v);void OnDownADiamond(); //called when a diamond can not down morebool IsValidDiamond(CDiamond*); //if the diamond is valid ?void Clean(); //resource cleanvoid Show();//debug //debug use,to print data struct of the playervoid OnGameOver(); private:long m_WidthBlocks ;long m_HeightBlocks ;long* m_pBlocks;CDiamond* m_pCurrDiamond; IGameController* m_pController;IDrawDrv* m_pDraw;CKeyController m_KeyCtl;enum GameStatus{STATUS_PLAYING,STATUS_GAMEOVER};GameStatus m_Status ;};#endif // !defined(AFX_DIAMOND_H__1B1DE2E7_A3B8_4D43_9079_AF2AC021F899__INCLUDED_)//implement Diamond.cpp// Diamond.cpp: implementation of the CDiamond class.////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "MDiamond.h"#include "Diamond.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif//block dataCBlock g_Blocks0[] = {{0,-1},{0,-2},{1,-1},{1,-2}};CBlock g_Blocks1[] = {{0,-1},{1,-1},{1,-2},{1,-3}};CBlock g_Blocks2[] = {{0,-2},{1,-2},{2,-2},{2,-1}};CBlock g_Blocks3[] = {{1,-1},{1,-2},{1,-3},{2,-3}};CBlock g_Blocks4[] = {{0,-1},{1,-1},{2,-1},{0,-2}};CBlock g_Blocks5[] = {{1,-1},{1,-2},{1,-3},{2,-1}};CBlock g_Blocks6[] = {{0,-1},{1,-1},{2,-1},{2,-2}};CBlock g_Blocks7[] = {{1,-1},{1,-2},{1,-3},{0,-3}};CBlock g_Blocks8[] = {{0,-1},{0,-2},{1,-2},{2,-2}};CBlock g_Blocks9[] = {{0,-1},{1,-1},{2,-1},{1,-2}};CBlock g_Blocks10[] = {{0,-2},{1,-1},{1,-2},{1,-3}};CBlock g_Blocks11[] = {{1,-1},{0,-2},{1,-2},{2,-2}};CBlock g_Blocks12[] = {{1,-1},{1,-2},{1,-3},{2,-2}};CBlock g_Blocks13[] = {{0,-1},{0,-2},{1,-2},{1,-3}};CBlock g_Blocks14[] = {{0,-2},{1,-2},{1,-1},{2,-1}};CBlock g_Blocks15[] = {{1,-1},{1,-2},{0,-2},{0,-3}};CBlock g_Blocks16[] = {{0,-1},{1,-1},{1,-2},{2,-2}};CBlock g_Blocks17[] = {{0,-1},{1,-1},{2,-1},{3,-1}};CBlock g_Blocks18[] = {{2,-1},{2,-2},{2,-3},{2,-4}};CBlock* g_Blocks[] = {g_Blocks0,g_Blocks1,g_Blocks2,g_Blocks3,g_Blocks4,g_Blocks5,g_Blocks6,g_Blocks7,g_Blocks8,g_Blocks9,g_Blocks10,g_Blocks11,g_Blocks12,g_Blocks13,g_Blocks14,g_Blocks15,g_Blocks16,g_Blocks17,g_Blocks18}; long g_BlockNexts[] = {0,2,3,4,1,6,7,8,5,10,11,12,9,14,13,16,15,18,17};//CDiamondCDiamond::CDiamond(){}CDiamond* CDiamond::CreateAnInstance(long x,long y){static int LastIndex = 0 ;CDiamond* d = new CDiamond();srand((unsigned)time(NULL) LastIndex);long index = rand() % 19 ;//long index = 17;d->m_Blocks = 4 ;d->m_index = index ;d->m_x = x;d->m_y = y;d->m_pBlocks = g_Blocks[index] ;LastIndex = index ;return d; }CDiamond::CDiamond(const CDiamond& d){m_x = d.m_x ;m_y = d.m_y ;m_index = d.m_index;m_Blocks = d.m_Blocks ;m_pBlocks = d.m_pBlocks ;}CDiamond::~CDiamond(){}long CDiamond::GetBlockCount(){return m_Blocks ;}CBlock* CDiamond::GetBlock(long i){return &m_pBlocks[i];}void CDiamond::Left(){m_x -- ;}void CDiamond::Right(){m_x ; }void CDiamond::Next(){m_index = g_BlockNexts[m_index];m_pBlocks = g_Blocks[m_index];}void CDiamond::Down(){m_y -- ;}void CDiamond::Draw(IDrawDrv* d,bool bShow=true){long count = GetBlockCount();for(int i=0;i<count;i ){CBlock* b = GetBlock(i);if(bShow){d->ShowBlocks(m_x b->m_x,m_y b->m_y,1,1);}else{d->HideBlocks(m_x b->m_x,m_y b->m_y,1,1); }}}//CGameCGame::CGame(IGameController* p,IDrawDrv* d,CKeyController key,long wBlocks,long hBlocks): m_WidthBlocks(wBlocks),m_HeightBlocks(hBlocks),m_KeyCtl(key){m_pController = p ;//pointers,need to be cleanm_pBlocks = NULL;m_pCurrDiamond = NULL;m_pDraw = d ;Init();}void CGame::OnKey(long keycode){if(keycode==-1) //-1 mean down {DownDiamond();}if(keycode==m_KeyCtl.LEFT){LeftDiamond();}if(keycode==m_KeyCtl.RIGHT){RightDiamond();}if(keycode==m_KeyCtl.DOWN){DownDiamond();}if(keycode==m_KeyCtl.NEXT){NextDiamond(); }if(keycode==m_KeyCtl.DROP){DropDiamond();}}CGame::~CGame(){Clean();}void CGame::Init(){if(NULL==m_pBlocks){long count = m_WidthBlocks * m_HeightBlocks ;m_pBlocks = new long[count];for(int i=0 ;i<count;i ){m_pBlocks[i] = 0;}}if(NULL==m_pCurrDiamond){m_pCurrDiamond = CDiamond::CreateAnInstance(m_WidthBlocks/2,m_HeightBlocks);}}void CGame::Clean(){if(m_pCurrDiamond!=NULL) delete m_pCurrDiamond;if(m_pBlocks!=NULL) delete [] m_pBlocks;if(m_pDraw!=NULL) delete m_pDraw ;}void CGame::Start(){Init();m_Status = STATUS_PLAYING; }bool CGame::IsOver(){return (STATUS_GAMEOVER==m_Status) ;}void CGame::OnGameOver(){m_Status = STATUS_GAMEOVER;}void CGame::OnEraseLines(IGame* fromGame,long lines){static int seed = 0 ;int i ;int j ;int AddLines = lines - 1;//random add lines to self//check if die for(i=0;i<m_WidthBlocks;i ){for(j=(m_HeightBlocks-AddLines);j<m_HeightBlocks;j ){if(1==GetBlockInfo(i,j)) {OnGameOver();return ;}}}//add linesfor(i=0;i<m_WidthBlocks;i ){for(j=m_HeightBlocks-1;j>=AddLines;j--){SetBlockInfo(i,j,GetBlockInfo(i,j-AddLines));}}for(i=0;i<m_WidthBlocks;i ){srand((unsigned)time(NULL) seed);long v = rand() % 2 ;for(j=0;j<AddLines;j ){SetBlockInfo(i,j,v);}seed ;}//fixed for(i=0;i<AddLines;i ){srand((unsigned)time(NULL) seed);int x = rand() % m_WidthBlocks ;SetBlockInfo(x,i,1);seed ;x = m_WidthBlocks - 1 - x ;SetBlockInfo(x,i,0);}Draw();}long CGame::GetBlockInfo(long x,long y){if(y>=m_HeightBlocks) return -1 ; //out of game panellong pos = y * m_WidthBlocks x ;return m_pBlocks[pos] ;}void CGame::SetBlockInfo(long x,long y,long v){if(x>=m_WidthBlocks || y>=m_HeightBlocks) return ; //out of game panellong pos = y * m_WidthBlocks x ;m_pBlocks[pos] = v ;}bool CGame::IsValidDiamond(CDiamond* d){long x = d->GetStartX();long y = d->GetStartY();CBlock* b;for(int i=0;i<d->GetBlockCount();i ){b = d->GetBlock(i);if((x b->m_x)<0) return false; //left checkif((x b->m_x)>=m_WidthBlocks) return false; //right checkif((y b->m_y)>=m_HeightBlocks) return false; //top checkif((y b->m_y)<0) return false; //bottom checkif(1==GetBlockInfo(x b->m_x,y b->m_y)) return false; //block check }return true;}void CGame::LeftDiamond(){CDiamond t(*m_pCurrDiamond);t.Left();if(IsValidDiamond(&t)){m_pCurrDiamond->Draw(m_pDraw,false); m_pCurrDiamond->Left();m_pCurrDiamond->Draw(m_pDraw); }}void CGame::RightDiamond(){CDiamond t(*m_pCurrDiamond);t.Right();if(IsValidDiamond(&t)){m_pCurrDiamond->Draw(m_pDraw,false); //hidem_pCurrDiamond->Right();m_pCurrDiamond->Draw(m_pDraw);}}void CGame::NextDiamond(){CDiamond t(*m_pCurrDiamond);t.Next();if(IsValidDiamond(&t)){m_pCurrDiamond->Draw(m_pDraw,false); //m_pCurrDiamond->Next(); m_pCurrDiamond->Draw(m_pDraw); }}bool CGame::CanDown(){CDiamond t(*m_pCurrDiamond);t.Down();return IsValidDiamond(&t);}void CGame::DropDiamond(){m_pCurrDiamond->Draw(m_pDraw,false);while(CanDown()){m_pCurrDiamond->Down();}OnDownADiamond();}void CGame::DownDiamond(){if(!CanDown()){OnDownADiamond();}else{m_pCurrDiamond->Draw(m_pDraw,false);m_pCurrDiamond->Down(); m_pCurrDiamond->Draw(m_pDraw); } }void CGame::OnDownADiamond(){CBlock* b ;for(int i=0;i<m_pCurrDiamond->GetBlockCount();i ){b = m_pCurrDiamond->GetBlock(i);SetBlockInfo(m_pCurrDiamond->GetStartX() b->m_x,m_pCurrDiamond->GetStartY() b->m_y,1);}long lines = EraseLines();if(lines>0) {m_pController->OnEraseLines(this,lines); }delete m_pCurrDiamond;m_pCurrDiamond = CDiamond::CreateAnInstance(m_WidthBlocks/2,m_HeightBlocks);if(!IsValidDiamond(m_pCurrDiamond)){OnGameOver(); return ;}Draw();}long CGame::EraseLines(){long count = m_WidthBlocks * m_HeightBlocks ;long* pNewBlocks = new long[count];for(int ii=0 ;ii<count;ii ){pNewBlocks[ii] = 0;}bool bErase ;int lines = 0 ;int fillLines = 0 ; for(int i=0 ;i<m_HeightBlocks;i ){bErase = true ;for(int j=0;j<m_WidthBlocks;j ){if(0==GetBlockInfo(j,i)) {bErase = false;break;}}if(bErase){lines ;}else{memcpy(&pNewBlocks[m_WidthBlocks*fillLines],&m_pBlocks[m_WidthBlocks*i],sizeof(long)*m_WidthBlocks);fillLines ;}}delete []m_pBlocks ;m_pBlocks = pNewBlocks ;return lines ;}void CGame::Show(){CString s = "" ;CString a ;for(int i=0;i<m_HeightBlocks;i ){for(int j=0;j<m_WidthBlocks;j ){if(1==GetBlockInfo(j,i)){s = "1," ;}else{s = "0," ;}}s = "\n" ;}AfxMessageBox(s);}void CGame::Draw(){for(int i=0;i<m_HeightBlocks;i ){for(int j=0;j<m_WidthBlocks;j ){if(GetBlockInfo(j,i)==1){m_pDraw->ShowBlocks(j,i,1,1);}else{m_pDraw->HideBlocks(j,i,1,1);}}}m_pCurrDiamond->Draw(m_pDraw); }//=class:CDrawDrvWindowsImp=//CDrawDrvWindowsImp::CDrawDrvWindowsImp(POINT p,COLORREF block_color,COLORREF bg_color,long block_size,CDC* pDC):m_OrgPoint(p),m_BlockColor(block_color),m_BgColor(bg_color),m_BlockSize(block_size),m_BlockBrush(block_color),m_BgBrush(bg_color),m_BorderBrush(RGB(255,255,255)) {m_pDC = pDC;}CDrawDrvWindowsImp::ShowBlocks(long x,long y,long xs,long ys){RECT rect;rect.left = m_OrgPoint.x x * m_BlockSize; rect.top = m_OrgPoint.y - ( y 1) * m_BlockSize ; rect.right = rect.left xs * m_BlockSize ;rect.bottom = rect.top ys * m_BlockSize ;m_pDC->FillRect(&rect,&m_BorderBrush);rect.left ;rect.top ;m_pDC->FillRect(&rect,&m_BlockBrush);}CDrawDrvWindowsImp::HideBlocks(long x,long y,long xs,long ys){RECT rect;rect.left = m_OrgPoint.x x * m_BlockSize; rect.top = m_OrgPoint.y - ( y 1) * m_BlockSize ; rect.right = rect.left xs * m_BlockSize ;rect.bottom = rect.top ys * m_BlockSize ;m_pDC->FillRect(&rect,&m_BgBrush);}//CGameControllerCGameController::CGameController(){m_Status = STATUS_TO_START;}CGameController::~CGameController(){Clean();}void CGameController::Clean(){POSITION pos ;pos = m_Games.GetHeadPosition();IGame* p;while(pos){p = m_Games.GetNext(pos);delete p ;}}void CGameController::OnEraseLines(IGame* pFromGame,long lines) {if(lines<2){return ;}POSITION pos ;pos = m_Games.GetHeadPosition();IGame* p;while(pos){p = m_Games.GetNext(pos);if(p!=pFromGame){if(!p->IsOver()) {p->OnEraseLines(pFromGame,lines); }}}}void CGameController::OnGameOver(IGame* pGame) {POSITION pos ;pos = m_Games.GetHeadPosition();IGame* p;bool bEnd = true;while(pos){p = m_Games.GetNext(pos);if(p->IsOver()) {bEnd = false; }}if(bEnd){End();}}void CGameController::Start(CDC* pDC){IGame* pGame;IDrawDrv* pDraw;long BlockSize;long WidthBlocks;long HeightBlocks;COLORREF BlockColor;COLORREF BgColor;POINT StartPos ;CKeyController key ;//game0BlockSize = 18 ;WidthBlocks = 14;HeightBlocks = 20 ;BlockColor = RGB(255,0,0);BgColor = RGB(160,0,0);StartPos.x = 10 ;StartPos.y = 60 BlockSize * HeightBlocks ; key.DOWN = 'S' ; key.LEFT = 'A' ;key.RIGHT ='D';key.NEXT = 'W';key.DROP = 'G' ;pDraw = new CDrawDrvWindowsImp(StartPos,BlockColor,BgColor,BlockSize,pDC); pGame = new CGame(this,pDraw,key,WidthBlocks,HeightBlocks);m_Games.AddTail(pGame);//game1BlockSize = 18 ;WidthBlocks = 14;HeightBlocks = 20 ;BlockColor = RGB(255,0,0);BgColor = RGB(160,0,0);StartPos.x = 350 ;StartPos.y = 60 BlockSize * HeightBlocks ; key.DOWN = 40 ; key.LEFT = 37 ;key.RIGHT = 39;key.NEXT = 38;key.DROP = 'L' ;pDraw = new CDrawDrvWindowsImp(StartPos,BlockColor,BgColor,BlockSize,pDC); pGame = new CGame(this,pDraw,key,WidthBlocks,HeightBlocks);m_Games.AddTail(pGame);m_Status = STATUS_PLAYING;}void CGameController::Pause(){if(m_Status == STATUS_PAUSE){m_Status = STATUS_PLAYING;}else{m_Status = STATUS_PAUSE;}} void CGameController::End(){m_Status = STATUS_END;Clean();}void CGameController::OnDraw(){POSITION pos ;pos = m_Games.GetHeadPosition();IGame* p;while(pos){p = m_Games.GetNext(pos);if(!p->IsOver()) {p->Draw(); }}}void CGameController::OnKey(long keycode){if(m_Status!=STATUS_PLAYING) return ;POSITION pos ;pos = m_Games.GetHeadPosition();IGame* p;while(pos){p = m_Games.GetNext(pos);if(!p->IsOver()) {p->OnKey(keycode); }}} 下载本文示例代码


俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码俄罗斯方块源代码
阅读(104) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~