www.pudn.com > TetrisWang.zip > Game.cpp


// Game.cpp: implementation of the CGame class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "Tetris.h" 
#include "Game.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
int CGame::m_nGameType = CGame::TYPE_SINGLE;	//	游戏类型--单人 
BOOL CGame::m_bComputerCanFallDown = TRUE;		//	电脑可按“下” 
int CGame::m_nComputerIntelligence= 2; 
int  CGame::m_nTetrisColor = 0; 
 
CGame::CGame() 
{ 
	m_nScore = 0; 
	m_nLines = 0; 
	m_nSpeed = 0; 
	m_bWin = false; 
	m_bComputer = false; 
	m_nTetrisType = TETRIS_BASE; 
	m_nTetrisColor = COLOR_OWNE; 
	m_nStatus = STATUS_WAIT; 
	m_bActive = false; 
} 
 
CGame::CGame(CGame &g) 
{ 
	m_Body = g.m_Body; 
	m_Tetris = g.m_Tetris; 
	m_ptStart = g.m_ptStart; 
	m_nStatus = g.m_nStatus; 
	m_nScore = g.m_nScore; 
	m_nLines = g.m_nLines; 
	m_nSpeed = g.m_nSpeed; 
	m_pView = g.m_pView; 
	m_bWin = g.m_bWin; 
	m_bComputer = g.m_bComputer; 
	m_nTetrisType = g.m_nTetrisType; 
	m_bActive = g.m_bActive; 
	m_nIndex = g.m_nIndex; 
	for (int i=0; i<4; i++) 
		m_CtrlKeys[i] = g.m_CtrlKeys[i]; 
} 
 
CGame::~CGame() 
{ 
} 
 
CSize CGame::MatchKey(UINT nChar) 
{ 
	CSize sz = CSize(-1, -1); 
	int nIndex; 
	if (IsComputer()) return sz; 
	for (nIndex=0; nIndex<4; nIndex++) 
	{ 
		if (m_CtrlKeys[nIndex] == nChar)	break; 
		if (nChar > 64 && nChar < 91)			//	大写字母 
		{ 
			if (m_CtrlKeys[nIndex] == nChar+32)	break; 
		} 
		else if (nChar > 96 && nChar < 123)		//	小写字母 
		{ 
			if (m_CtrlKeys[nIndex] == nChar-32)	break; 
		} 
	} 
	switch (nIndex) 
	{ 
    case 0:		//	move left 
		sz = CSize(-1, 0); 
		break; 
    case 1:		//	move right 
		sz = CSize(1, 0); 
		break; 
    case 2:		//	roate 
		sz = CSize(0, 0); 
		break; 
    case 3:		//	fall down 
		sz = CSize(1, 1); 
		break; 
	default: 
		sz = CSize(-1, -1); 
	} 
	return sz;		 
} 
 
 
CSize CGame::GetTopSize(void) 
{ 
	return CSize(m_Body.GetWidth() * CBlock::GetCell() + 2, 5 * CBlock::GetCell()); 
} 
 
CSize CGame::GetBodySize(void) 
{ 
	return CSize(m_Body.GetWidth() * CBlock::GetCell() + 2, m_Body.GetHeight() * CBlock::GetCell() + 2); 
} 
 
CSize CGame::GetSize(void) 
{ 
	return CSize(m_Body.GetWidth() * CBlock::GetCell() + 2, (m_Body.GetHeight()+5) * CBlock::GetCell() + 2); 
} 
 
void CGame::Draw(CDC &dc) 
{ 
	if (m_nStatus == STATUS_WAIT) 
	{ 
		DrawGameWait(dc); 
		return; 
	} 
	DrawTop(dc); 
	m_Body.Draw(dc); 
	if (m_nStatus == STATUS_OVER)	DrawGameOver(dc); 
} 
 
void CGame::DrawTop(CDC &dc) 
{ 
	int nSaveDC = dc.SaveDC(); 
	dc.SelectStockObject(BLACK_PEN); 
	dc.SelectStockObject(WHITE_BRUSH); 
	dc.SetBkColor(RGB(255, 255, 255)); 
 
	dc.Rectangle(CRect(m_ptStart, GetTopSize())); 
	dc.Rectangle(CRect(m_ptStart+CSize(0, GetTopSize().cy), GetBodySize())); 
 
	CString strTitle; 
	CString strValue; 
 
	CFont font; 
	font.CreatePointFont(CBlock::GetCell()*6, "宋体"); 
	dc.SelectObject(&font); 
 
//	strTitle.LoadString(IDS_SCORE); 
	strTitle = GetLangueString("Score"); 
	strValue.Format("%8d", m_nScore); 
	dc.TextOut(m_ptStart.x + CBlock::GetCell() * 5, m_ptStart.y + CBlock::GetCell() / 2, LPCTSTR(strTitle)); 
	dc.TextOut(m_ptStart.x + CBlock::GetCell() * 6, m_ptStart.y + CBlock::GetCell() + CBlock::GetCell() / 2, LPCTSTR(strValue)); 
	 
//	strTitle.LoadString(IDS_LINES); 
	strTitle = GetLangueString("Lines"); 
	strValue.Format("%8d", m_nLines); 
	dc.TextOut(m_ptStart.x + CBlock::GetCell() * 6, m_ptStart.y + CBlock::GetCell() * 2 + CBlock::GetCell() / 2, LPCTSTR(strValue)); 
	dc.TextOut(m_ptStart.x + CBlock::GetCell() * 5, m_ptStart.y + CBlock::GetCell() * 2 + CBlock::GetCell() / 2, LPCTSTR(strTitle)); 
	 
//	strTitle.LoadString(IDS_SPEED); 
	strTitle = GetLangueString("Speed"); 
	strValue.Format("%8d", m_nSpeed); 
	dc.TextOut(m_ptStart.x + CBlock::GetCell() * 6, m_ptStart.y + CBlock::GetCell() * 3 + CBlock::GetCell() / 2, LPCTSTR(strValue)); 
	dc.TextOut(m_ptStart.x + CBlock::GetCell() * 5, m_ptStart.y + CBlock::GetCell() * 3 + CBlock::GetCell() / 2, LPCTSTR(strTitle)); 
 
	font.DeleteObject(); 
	m_Tetris.Draw(m_ptStart+CSize(CBlock::GetCell(), CBlock::GetCell()/2), dc); 
	dc.RestoreDC(nSaveDC); 
} 
 
void CGame::DrawGameOver(CDC& dc) 
{ 
	int nSaveDC = dc.SaveDC(); 
	dc.SetBkMode(TRANSPARENT); 
 
	CFont font; 
	font.CreatePointFont(CBlock::GetCell()*(CTetrisApp::m_nLangue == CTetrisApp::CHINESE ? 16 : 16), "宋体"); 
	dc.SelectObject(&font); 
 
	CString strOut; 
	if (!m_bWin) 
	{ 
//		strOut.LoadString(IDS_GAMEOVER); 
		dc.SetTextColor(RGB(0, 0, 255)); 
		strOut = GetLangueString("GameOver"); 
	} 
	else 
	{ 
//		strOut.LoadString(IDS_GAMEWIN); 
		strOut = GetLangueString("GameWin"); 
		dc.SetTextColor(RGB(255, 0, 0)); 
	} 
	dc.DrawText(strOut, CRect(m_ptStart, GetSize()), DT_VCENTER | DT_CENTER | DT_NOCLIP | DT_SINGLELINE); 
	font.DeleteObject(); 
	dc.RestoreDC(nSaveDC); 
} 
 
void CGame::DrawGameWait(CDC& dc) 
{ 
	int nSaveDC = dc.SaveDC(); 
	dc.SetBkMode(TRANSPARENT); 
 
	CFont font; 
	font.CreatePointFont(CBlock::GetCell()*(CTetrisApp::m_nLangue == CTetrisApp::CHINESE ? 14 : 22), "宋体"); 
	dc.SelectObject(&font); 
 
	CString strOut; 
//	strOut.LoadString(IDS_GAMEWAIT); 
	strOut = GetLangueString("GameWait"); 
	dc.SetTextColor(RGB(0, 0, 255)); 
 
	dc.DrawText(strOut, CRect(m_ptStart, GetBodySize()), DT_VCENTER | DT_CENTER | DT_NOCLIP | DT_SINGLELINE); 
	font.DeleteObject(); 
 
	CFont lfont; 
	lfont.CreatePointFont(CBlock::GetCell()*6, "宋体"); 
	dc.SelectObject(&lfont); 
 
	strOut.LoadString(IDS_COPYRIGHT); 
	dc.SetTextColor(RGB(0, 0, 255)); 
 
	dc.DrawText(strOut, CRect(m_ptStart, GetSize()), DT_VCENTER | DT_CENTER | DT_NOCLIP | DT_SINGLELINE); 
	lfont.DeleteObject(); 
	dc.RestoreDC(nSaveDC); 
} 
 
void CGame::StartGame(int nSpeed, int nLines, int nTetrisType,	UINT nCtrlKeys[MAX_CTRL_KEYS], int nColorType) 
{ 
	m_nStatus = STATUS_RUN; 
	m_bWin = false; 
	m_nSpeed = nSpeed; 
	m_nLines = 0; 
	m_nTetrisType = nTetrisType; 
	m_nTetrisColor = nColorType; 
 
	m_Body.SetPoint(m_ptStart+CSize(1, GetTopSize().cy+1)); 
	for (int i=0; iKillTimer(TimerIndex); 
	m_pView->SetTimer(TimerIndex, SpeedToTime(m_nSpeed), NULL); 
} 
 
void CGame::EndGame(BOOL bReDraw) 
{ 
	m_Body.CutLastTetris(); 
	m_nStatus = STATUS_OVER; 
 
	UINT TimerIndex; 
	if (GetIndex() != 0) 
		TimerIndex = TIMER_INDEX_2; 
	else 
		TimerIndex = TIMER_INDEX_1; 
	m_pView->KillTimer(TimerIndex); 
	if (IsComputer()) m_pView->KillTimer(TIMER_COMPUTER); 
 
	if (bReDraw) 
	{ 
		CClientDC dc(m_pView); 
		DrawGameOver(dc); 
		if (m_nGameType == TYPE_SITZKRIEG || m_nGameType == TYPE_COMPUTER) 
			m_pView->GameWin(m_nIndex); 
	} 
} 
 
void CGame::NewTetris(void) 
{ 
	int nTetris = rand() % m_nTetrisType; 
	int nColor; 
	switch (m_nTetrisColor) 
	{ 
		case COLOR_OWNE: 
			nColor = nTetris; 
			break; 
		case COLOR_SAME: 
			nColor = 0; 
			break; 
		case COLOR_RAND: 
			nColor = rand() % MAX_COLORS; 
			break; 
		default: 
			nColor = 0; 
	} 
	m_Tetris = CTetris(nTetris, nColor); 
} 
 
void CGame::NextTetris(void) 
{ 
	m_Body.SetTetris(m_Tetris); 
	m_Body.SetTetrisPoint(CPoint(2, 0)); 
	NewTetris(); 
} 
 
void CGame::TetrisMove(const CSize &sz) 
{ 
	CClientDC dc(m_pView); 
	if (sz == CSize(0, 1))		//	Tetris Down 
	{ 
		if (!m_Body.TetrisMove(dc, sz)) 
		{ 
			TetrisDown(dc); 
		} 
	} 
	else if (sz == CSize(1, 1))	//	Tetris Fall 
	{ 
		for (int i=1; ; i++) 
		{ 
			if (!m_Body.TetrisMove(dc, CSize(0, 1))) 
			{ 
				TetrisDown(dc); 
				break; 
			} 
		} 
	} 
	else if (sz == CSize(0, 0))	//	Tetris Roate 
	{ 
		m_Body.TetrisMove(dc, sz); 
	} 
	else if (sz == CSize(-1, 0) || sz == CSize(1, 0))	//	Tetris Move Left or Right 
	{ 
		m_Body.TetrisMove(dc, sz); 
	} 
} 
 
void CGame::TetrisDown(CDC& dc) 
{ 
	NextTetris(); 
	int nLines = m_Body.RemoveLines(); 
	if (nLines > 0) 
	{ 
		if (m_nLines / LINES_CHANGE_SPEED < (m_nLines + nLines) / LINES_CHANGE_SPEED) 
		{ 
			if (m_nSpeed < MAX_SPEED) 
			{ 
				m_nSpeed++; 
				SetGameTimer(); 
			} 
		} 
		m_nLines += nLines; 
		m_nScore += LinesToScore(nLines); 
		if (nLines > 1 && (m_nGameType == TYPE_SITZKRIEG || m_nGameType == TYPE_COMPUTER))	 
			m_pView->GameAddLines(GetIndex(), nLines); 
	} 
	if (!m_Body.IsTetrisFit(m_Body.GetTetrisPoint(), m_Body.GetTetris()))	 
	{ 
		EndGame(); 
	} 
	Draw(dc); 
	if ((GetType() == TYPE_COMPUTER || GetType() == TYPE_TEACH) && IsComputer() && GetStatus() == STATUS_RUN) 
		SetComputerCtrl(); 
} 
 
void CGame::AddLines(int nLines) 
{ 
	if (m_nStatus != STATUS_RUN) return; 
	if (nLines <= 0) return; 
	CClientDC dc(m_pView); 
	m_Body.AddLines(nLines, m_nTetrisType); 
	for (int i=0; im_nComputerIntelligence); 
	m_nCtrlRoate = nRoate; 
	m_nCtrlMove = nMove; 
	m_pView->SetTimer(TIMER_COMPUTER, SpeedToTime(9), NULL); 
} 
 
void CGame::ComputerCtrlTetris(void) 
{ 
	if (m_nCtrlRoate == 0 && m_nCtrlMove == 0) return; 
	if (m_nCtrlRoate > 0) 
	{ 
		TetrisMove(CSize(0, 0)); 
		m_nCtrlRoate--; 
	} 
	else if (m_nCtrlMove != 0) 
	{ 
		TetrisMove(CSize(m_nCtrlMove/abs(m_nCtrlMove), 0)); 
		m_nCtrlMove -= m_nCtrlMove/abs(m_nCtrlMove); 
		if (m_nCtrlMove == 0) m_pView->KillTimer(TIMER_COMPUTER); 
	} 
} 
 
UINT CGame::SpeedToTime(int nSpeed) 
{ 
	switch (nSpeed) 
	{ 
	case 0: 
		return(1000); 
	case 1: 
		return(900); 
	case 2: 
		return(800); 
	case 3: 
		return(700); 
	case 4: 
		return(600); 
	case 5: 
		return(500); 
	case 6: 
		return(400); 
	case 7: 
		return(300); 
	case 8: 
		return(200); 
	case 9: 
		return(150); 
	} 
	return(150); 
} 
 
int CGame::LinesToScore(int nLines) 
{ 
	int nScore; 
	switch (nLines) 
	{ 
	case 1: 
		nScore = 100; 
		break; 
	case 2: 
		nScore = 300; 
		break; 
	case 3: 
		nScore = 500; 
		break; 
	case 4: 
		nScore = 1000; 
		break; 
	} 
	return nScore; 
}