没有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 > 1000
class IGame; //inteface of game ,one mean a player class IGameController; //inteface of game controller,control communication of players
typedef CTypedPtrList<CObList,IGame*> CGames; //all player in the game
class IGameController { //construction/destruction public: virtual ~IGameController(){};
//public interface public: virtual void OnEraseLines(IGame*,long) = 0 ; //when a player erase lines,call it virtual void OnGameOver(IGame*) = 0 ; //when a player dies ,call it };
//a block of a diamond struct CBlock { long m_x ; long m_y ; };
// class IGame:public CObject { //construction/destruction public: virtual ~IGame(){};
//public interface public: virtual void OnKey(long) = 0 ; //recieve key event virtual void Start() = 0 ; //recieve start event virtual 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/destruction public: virtual ~IDrawDrv(){};
//public interface public: virtual ShowBlocks(long x,long y,long xs,long ys)=0; //show blocks virtual HideBlocks(long x,long y,long xs,long ys)=0; //hide blocks };
//implement of IDrawDrv of Windows
class CDrawDrvWindowsImp :public IDrawDrv {
//construction/destruction public: 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);
//implements private: POINT m_OrgPoint ; COLORREF m_BlockColor; //block color COLORREF m_BgColor; // bg color long m_BlockSize; // pts of a block CDC* m_pDC;
CBrush m_BlockBrush; CBrush m_BorderBrush; CBrush m_BgBrush; };
// class CGameController:public IGameController {
//construction/destruction public : CGameController(); ~CGameController(); private:
CGameController(const CGameController&); void operator=(const CGameController&);
//public interface public: virtual void OnEraseLines(IGame*,long) ;//called by players ,when them erase lines virtual void OnGameOver(IGame*); //called by players,when them die
void Start(CDC*); //start game! void Pause(); //pause game,or restart game void End(); //end game
void OnDraw(); //paint event void 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/destruction public: 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/destruction public: static CDiamond* CreateAnInstance(long x,long y); //random create a diamond CDiamond(const CDiamond&); ~CDiamond(); private : CDiamond(); void operator=(const CDiamond&);
//public interface public: long GetBlockCount(); //get blocks count, to support other type diamonds CBlock* GetBlock(long); // get a block ,by index void Left(); // left a diamond void Right(); // right a diamond void Down(); //down a diamond void Next(); //retate a diamond void Draw(IDrawDrv*,bool); //draw a diamond long GetStartX(){return m_x;}; //get start x position long GetStartY(){return m_y;}; // get start y position
//implements private: long m_x ; long m_y ; long m_index; long m_Blocks; CBlock* m_pBlocks; };
//player of game class CGame:public IGame { //construction/destruction public: CGame(IGameController*,IDrawDrv*,CKeyController,long wBlocks,long hBlocks); virtual ~CGame(); private: CGame(const CGame&); void operator=(const CGame&);
//public interface public: virtual void OnKey(long); //recieve key event virtual void Start(); //recieve start event virtual bool IsOver(); //if is die? virtual void OnEraseLines(IGame* fromGame,long lines); void Draw();
//implements private:
void Init(); //init void 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 more bool IsValidDiamond(CDiamond*); //if the diamond is valid ? void Clean(); //resource clean void Show();//debug //debug use,to print data struct of the player void 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_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif
//block data CBlock 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};
//CDiamond CDiamond::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); } } }
//CGame CGame::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 clean m_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 lines for(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 panel long 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 panel long 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 check if((x+b->m_x)>=m_WidthBlocks) return false; //right check if((y+b->m_y)>=m_HeightBlocks) return false; //top check if((y+b->m_y)<0) return false; //bottom check if(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); //hide m_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); }
//CGameController CGameController::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 ;
//game0 BlockSize = 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);
//game1 BlockSize = 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); } } }
|
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
|