📄 blockview.cpp
字号:
// blockView.cpp : implementation of the CBlockView class
//
#include "stdafx.h"
#include "block.h"
#include "blockDoc.h"
#include "blockView.h"
#include "MainFrm.h"
#include <mmsystem.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//--------------------------------------------------------
#define START_X 5
#define TIMER_ID 1
#define API_TIMER 2
#define MAX_LINE 20
const UINT uInverval[9]=
{
500,400,350,300,250,200,150,100,50
};
UINT uAPI_Timer;
void CALLBACK TimeProc(UINT uID,UINT uMsg,DWORD dwUser,DWORD dw1,DWORD dw2);
//--------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
// CBlockView
IMPLEMENT_DYNCREATE(CBlockView, CView)
BEGIN_MESSAGE_MAP(CBlockView, CView)
//{{AFX_MSG_MAP(CBlockView)
ON_COMMAND(ID_START, OnStart)
ON_COMMAND(ID_STOP, OnStop)
ON_UPDATE_COMMAND_UI(ID_START, OnUpdateStart)
ON_UPDATE_COMMAND_UI(ID_STOP, OnUpdateStop)
ON_WM_ERASEBKGND()
ON_WM_TIMER()
ON_WM_KEYDOWN()
ON_COMMAND(ID_BKCOLOR, OnBkcolor)
ON_COMMAND(ID_BLOCKCOLOR, OnBlockcolor)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBlockView construction/destruction
CBlockView::CBlockView()
{
// TODO: add construction code here
}
CBlockView::~CBlockView()
{
}
BOOL CBlockView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CBlockView drawing
void CBlockView::OnDraw(CDC* pDC)
{
CBlockDoc* pDoc = GetDocument();
int i,j;
CRect rect;
CBrush brush;
brush.CreateSolidBrush(pDoc->m_clrBlock);
ASSERT_VALID(pDoc);
for(i=0;i<20;i++)
for(j=0;j<12;j++)
{
rect.SetRect(j*20,i*20,j*20+20,i*20+20);
if(pDoc->m_iMap[i][j]==1)
{
pDC->FillRect(&rect,&brush);
pDC->DrawEdge(&rect,EDGE_RAISED,BF_RECT);
}
}
ShowSquare();
if(!m_bAPITimerRunning)
{
::timeBeginPeriod(1);
uAPI_Timer=::timeSetEvent(1000,0,TimeProc,(DWORD)(this->m_hWnd),TIME_PERIODIC);
m_bAPITimerRunning=TRUE;
}
}
/////////////////////////////////////////////////////////////////////////////
// CBlockView diagnostics
#ifdef _DEBUG
void CBlockView::AssertValid() const
{
CView::AssertValid();
}
void CBlockView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CBlockDoc* CBlockView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CBlockDoc)));
return (CBlockDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CBlockView message handlers
//--------------------------------------------------------
void CBlockView::OnStart()
{
// TODO: Add your command handler code here
CBlockDoc *pDoc=GetDocument();
m_bRunning=TRUE;
ShowPreView();
SetTimer(TIMER_ID,uInverval[pDoc->m_iLevel],NULL);
}
void CBlockView::OnStop()
{
// TODO: Add your command handler code here
if(m_bRunning)
{
m_bRunning=FALSE;
KillTimer(TIMER_ID);
}
}
void CBlockView::OnInitialUpdate()
{
CView::OnInitialUpdate();
CBlockDoc *pDoc=GetDocument();
m_bAPITimerRunning=FALSE;
((CMainFrame *)AfxGetMainWnd())->ChangeLevelSel(pDoc->m_iLevel);
if(m_bRunning)
{
m_bRunning=FALSE;
KillTimer(TIMER_ID);
}
}
//--------------------------------------------------------
void CBlockView::OnUpdateStart(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(!m_bRunning);
}
void CBlockView::OnUpdateStop(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bRunning);
}
//--------------------------------------------------------
BOOL CBlockView::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
CRect rect;
int width,height;
CBlockDoc *pDoc=GetDocument();
GetClientRect(&rect);
width=rect.Width();
height=rect.Height();
rect.right=240;
CBrush brush(pDoc->m_clrBack);
pDC->FillRect(&rect,&brush);
rect.left=rect.right;
rect.right=width;
brush.DeleteObject();
brush.CreateSolidBrush(pDoc->m_clrBlock);
pDC->FillRect(&rect,&brush);
pDC->DrawEdge(&rect,EDGE_BUMP,BF_RECT);
rect.bottom=rect.top+30;
pDC->SetBkColor(pDoc->m_clrBlock);
pDC->SetTextColor(~pDoc->m_clrBlock);
pDC->DrawText(_T("下一个方块:"),&rect,DT_SINGLELINE|DT_VCENTER|DT_CENTER);
rect.top=rect.top+30;
rect.bottom=rect.Width();
rect.InflateRect(-2,-2);
pDC->DrawEdge(&rect,EDGE_SUNKEN,BF_RECT);
rect.top=rect.bottom;
rect.bottom+=30;
pDC->DrawText(_T("自述:"),&rect,DT_SINGLELINE|DT_VCENTER|DT_CENTER);
rect.top=rect.bottom;
rect.bottom=height-2;
pDC->DrawEdge(&rect,EDGE_SUNKEN,BF_RECT);
ShowPreView();
return TRUE;
}
void CBlockView::ShowSquare()
{
CBlockDoc *pDoc=GetDocument();
CRect rect;
CClientDC dc(this);
CBrush brush;
brush.CreateSolidBrush(pDoc->m_clrBlock);
for(int i=0;i<4;i++)
{
rect.SetRect(pDoc->m_ptCurrentPos[i].x*20,
pDoc->m_ptCurrentPos[i].y*20,
pDoc->m_ptCurrentPos[i].x*20+20,
pDoc->m_ptCurrentPos[i].y*20+20);
dc.FillRect(&rect,&brush);
dc.DrawEdge(&rect,EDGE_RAISED,BF_RECT);
}
}
void CBlockView::HideSquare()
{
CBlockDoc *pDoc=GetDocument();
CRect rect;
CClientDC dc(this);
CBrush brush;
brush.CreateSolidBrush(pDoc->m_clrBack);
for(int i=0;i<4;i++)
{
rect.SetRect(pDoc->m_ptCurrentPos[i].x*20,
pDoc->m_ptCurrentPos[i].y*20,
pDoc->m_ptCurrentPos[i].x*20+20,
pDoc->m_ptCurrentPos[i].y*20+20);
dc.FillRect(&rect,&brush);
}
}
void CBlockView::DeleteLine(int iIndex) //iIndex is 0 based
{
int i;
CRect rect;
CBlockDoc *pDoc=GetDocument();
for(i=iIndex;i>=1;i--)
memcpy(pDoc->m_iMap[i],pDoc->m_iMap[i-1],12*sizeof(int));
memset(pDoc->m_iMap,0,12*sizeof(int));
rect.SetRect(0,0,12*20,(iIndex+1)*20);
ScrollWindow(0,20,&rect,&rect);
}
//--------------------------------------------------------
void CBlockView::CreateSquare()
{
int i;
CBlockDoc *pDoc=GetDocument();
pDoc->m_iShape=pDoc->m_iNextShape;
pDoc->m_iNextShape=rand()%7;
pDoc->m_iState=0;
switch(pDoc->m_iShape)
{
case 0: // @@@@
for(i=0;i<4;i++)
{
pDoc->m_ptCurrentPos[i].x=START_X+i;
pDoc->m_ptCurrentPos[i].y=0;
}
break;
case 1: // @
// @@@
pDoc->m_ptCurrentPos[0].x=START_X;
pDoc->m_ptCurrentPos[0].y=0;
for(i=1;i<4;i++)
{
pDoc->m_ptCurrentPos[i].x=START_X+i-1;
pDoc->m_ptCurrentPos[i].y=1;
}
break;
case 2: // @
// @@@
pDoc->m_ptCurrentPos[0].x=START_X+2;
pDoc->m_ptCurrentPos[0].y=0;
for(i=1;i<4;i++)
{
pDoc->m_ptCurrentPos[i].x=START_X+i-1;
pDoc->m_ptCurrentPos[i].y=1;
}
break;
case 3: // @@
// @@
for(i=0;i<2;i++)
{
pDoc->m_ptCurrentPos[i].x=START_X+i;
pDoc->m_ptCurrentPos[i].y=0;
}
for(i=2;i<4;i++)
{
pDoc->m_ptCurrentPos[i].x=START_X+i-1;
pDoc->m_ptCurrentPos[i].y=1;
}
break;
case 4: // @@
// @@
for(i=0;i<2;i++)
{
pDoc->m_ptCurrentPos[i].x=START_X+i+1;
pDoc->m_ptCurrentPos[i].y=0;
}
for(i=2;i<4;i++)
{
pDoc->m_ptCurrentPos[i].x=START_X+i-2;
pDoc->m_ptCurrentPos[i].y=1;
}
break;
case 5: // @
// @@@
pDoc->m_ptCurrentPos[0].x=START_X+1;
pDoc->m_ptCurrentPos[0].y=0;
for(i=1;i<4;i++)
{
pDoc->m_ptCurrentPos[i].x=START_X+i-1;
pDoc->m_ptCurrentPos[i].y=1;
}
break;
default : // @@
// @@
for(i=0;i<4;i++)
{
pDoc->m_ptCurrentPos[i].x=START_X+i%2;
pDoc->m_ptCurrentPos[i].y=(i<=1)?0:1;
}
break;
}
}
//---------------------------------------------------------------
void CBlockView::OnTimer(UINT nIDEvent)
{
int i,j;
BOOL bAbleToDrop;
UINT uDeleteLineInfo=0;
UINT iLineNumInfo=0;
CBlockDoc *pDoc=GetDocument();
bAbleToDrop=TRUE;
for(i=0;i<4;i++) //verify if end game
{
if(pDoc->m_iMap[pDoc->m_ptCurrentPos[i].y][pDoc->m_ptCurrentPos[i].x]==1)
{
KillTimer(TIMER_ID);
MessageBox(_T("你已经失败!\n请重新建游戏并开始!"),_T("Warning!"),MB_ICONWARNING|MB_OK);
m_bRunning=FALSE;
return;
}
}
for(i=0;i<4;i++) //verify if able to drop
{
if((pDoc->m_iMap[pDoc->m_ptCurrentPos[i].y+1][pDoc->m_ptCurrentPos[i].x]==1)
||pDoc->m_ptCurrentPos[i].y==19)
{
bAbleToDrop=FALSE;
break;
}
}
if(bAbleToDrop)
{
HideSquare();
for(i=0;i<4;i++)
pDoc->m_ptCurrentPos[i].y++; //drop one line
ShowSquare();
}
else // not able to drop
{
for(i=0;i<4;i++)
pDoc->m_iMap[pDoc->m_ptCurrentPos[i].y][pDoc->m_ptCurrentPos[i].x]=1;
for(i=0;i<20;i++)
{
for(j=0;j<12;j++)
{
if(pDoc->m_iMap[i][j]==0)
break;
}
if(j==12) // has one line to delete
uDeleteLineInfo=uDeleteLineInfo|(1L<<i);
}
for(i=0;i<20;i++)
if( ( (uDeleteLineInfo>>i) & 1L)!=0)
iLineNumInfo++;
if(uDeleteLineInfo!=0) //need to delete line
{
for(i=0;i<20;i++)
{
if( ( (uDeleteLineInfo>>i) & 1L)!=0)
DeleteLine(i);
}
if(iLineNumInfo==1)
pDoc->m_uScore+=100;
else if(iLineNumInfo==2)
pDoc->m_uScore+=300;
else if(iLineNumInfo==3)
pDoc->m_uScore+=500;
else
pDoc->m_uScore+=1000;
if(pDoc->m_uScore%2000==0)
{
pDoc->m_iLevel=min(pDoc->m_iLevel+1,8);
((CMainFrame *)AfxGetMainWnd())->ChangeLevelSel(pDoc->m_iLevel);
}
}
CreateSquare();
ShowSquare();
ShowPreView();
}
CView::OnTimer(nIDEvent);
}
//-----------------------------------------------------------------
void CBlockView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
switch(nChar)
{
case VK_LEFT:
GoLeft();
break;
case VK_RIGHT:
GoRight();
break;
case VK_DOWN:
GoFastDown();
break;
case VK_UP:
ChangeState();
break;
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
//--------------------------------------------------------
void CBlockView::GoLeft()
{
int i;
CBlockDoc *pDoc=GetDocument();
for(i=0;i<4;i++)
{
if(pDoc->m_ptCurrentPos[i].x<=0)
return;
if(pDoc->m_iMap[pDoc->m_ptCurrentPos[i].y][pDoc->m_ptCurrentPos[i].x-1]==1)
return;
}
HideSquare();
for(i=0;i<4;i++)
pDoc->m_ptCurrentPos[i].x-=1;
ShowSquare();
}
void CBlockView::GoRight()
{
int i;
CBlockDoc *pDoc=GetDocument();
for(i=0;i<4;i++)
{
if(pDoc->m_ptCurrentPos[i].x>=11)
return ;
else if(pDoc->m_iMap[pDoc->m_ptCurrentPos[i].y][pDoc->m_ptCurrentPos[i].x+1]==1)
return;
}
HideSquare();
for(i=0;i<4;i++)
pDoc->m_ptCurrentPos[i].x+=1;
ShowSquare();
}
void CBlockView::GoFastDown()
{
int i;
CBlockDoc *pDoc=GetDocument();
if(!m_bRunning)
return;
for(i=0;i<4;i++)
{
if(pDoc->m_ptCurrentPos[i].y>=19)
return ;
else if(pDoc->m_iMap[pDoc->m_ptCurrentPos[i].y+1][pDoc->m_ptCurrentPos[i].x]==1)
return;
}
HideSquare();
for(i=0;i<4;i++)
pDoc->m_ptCurrentPos[i].y+=1;
ShowSquare();
}
//--------------------------------------------------------
void CBlockView::ChangeState()
{
int i;
CBlockDoc *pDoc=GetDocument();
switch(pDoc->m_iShape)
{
case 0:
if(pDoc->m_iState==0)
{
if(pDoc->m_ptCurrentPos[0].y<=0||pDoc->m_ptCurrentPos[0].y>=18)
return;
if((pDoc->m_iMap[pDoc->m_ptCurrentPos[1].y+1][pDoc->m_ptCurrentPos[1].x]==1)
||(pDoc->m_iMap[pDoc->m_ptCurrentPos[1].y+2][pDoc->m_ptCurrentPos[1].x]==1))
return;
HideSquare();
for(i=0;i<4;i++)
{
pDoc->m_ptCurrentPos[i].y=pDoc->m_ptCurrentPos[1].y+i-1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -