📄 tetris.c
字号:
}
}
void RectChange(HWND hwnd)
{
//先预先变形,然后判断变形后的方块是否有空间,如有足够空间,则进行实际变形,否则不变
int xx1,xx2,xx3,xx4,yy1,yy2,yy3,yy4;
int m_lscurrentRect;
// CString lsStr;
TETRISINFO*gi;
int x1,x2,x3,x4,y1,y2,y3,y4;
x1 = gi->ActiveStatus[0][0]; x2 = gi->ActiveStatus[1][0];
x3 = gi->ActiveStatus[2][0]; x4 = gi->ActiveStatus[3][0];
y1 = gi->ActiveStatus[0][1]; y2 = gi->ActiveStatus[1][1];
y3 = gi->ActiveStatus[2][1]; y4 = gi->ActiveStatus[3][1];
//变形后位置在数组中的存放顺序仍需遵循先左后右,在同一列中先上后下
xx1=x1; xx2=x2; xx3=x3; xx4=x4; yy1=y1; yy2=y2; yy3=y3; yy4=y4;
switch(gi->m_currentRect)
{
case 1:
xx1=x1+1; yy1=y1-1; xx3=x3-1; yy3=y3+1; xx4=x4-2; yy4=y4+2;
m_lscurrentRect = 11; break;
case 11:
xx1=x1-1; yy1=y1+1; xx3=x3+1; yy3=y3-1; xx4=x4+2; yy4=y4-2;
m_lscurrentRect = 1; break;
case 2:
m_lscurrentRect=2; break;
case 3:
xx1=x1-2; yy1=y1+1; xx4=x4-1; yy4=y4;
m_lscurrentRect = 31; break;
case 31:
xx1=x1+1; yy1=y1-1;
m_lscurrentRect = 32; break;
case 32:
xx1=x1+1; yy1=y1; xx4=x4+2; yy4=y4-1;
m_lscurrentRect=33; break;
case 33:
xx4=x4-1; yy4=y4+1;
m_lscurrentRect=3; break;
case 4:
xx1=x1+2; yy1=y1-1; xx3=x3+1; yy3=y3-1; xx4=x4-1;
m_lscurrentRect = 41; break;
case 41:
xx1=x1-2; yy1=y1+1; xx3=x3-1; yy3=y3+1; xx4=x4+1;
m_lscurrentRect = 4; break;
case 5:
xx1=x1-1; xx2=x2-2; yy2=y2+1; xx3=x3+1; yy4=y4+1;
m_lscurrentRect = 51; break;
case 51:
xx1=x1+1; xx2=x2+2; yy2=y2-1; xx3=x3-1; yy4=y4-1;
m_lscurrentRect = 5; break;
case 6:
xx2=x1+1; yy2=y2-1; xx3=x3-1; xx4=x4-2; yy4 = yy4+1;
m_lscurrentRect = 61; break;
case 61:
xx3=x3+2; yy3=y3-1; xx4=x4+2; yy4=y4-1;
m_lscurrentRect = 62; break;
case 62:
xx1=x1+1; yy1=y1-1; xx3=x3-2; yy3=y3+1; xx4=x4-1;
m_lscurrentRect = 63; break;
case 63:
xx1=x1-2; yy1=y1+1; xx2=x2-2; yy2=y2+1;
m_lscurrentRect = 6; break;
case 7:
xx3=x3-1; yy3=y3+1; xx4=x4+1; yy4=y4+1;
m_lscurrentRect = 71; break;
case 71:
xx1=x1+2; xx2=x2-1; yy2=y2+1; xx4=x4+1; yy4=y4-1;
m_lscurrentRect = 72; break;
case 72:
xx1=x1-2; xx3=x3-1; yy3=y3+1; xx4=x4-1; yy4=y4+1;
m_lscurrentRect = 73; break;
case 73:
xx2=x2+1; yy2=y2-1; xx3=x3+2; yy3=y3-2; xx4=x4-1; yy4=y4-1;
m_lscurrentRect = 7; break;
}
//如果变形后所在的区域内无其他方块,则表示有足够空间,可以变形
//且不能超越边界
gi->GameStatus[x1][y1] = 0;
gi->GameStatus[x2][y2] = 0;
gi->GameStatus[x3][y3] = 0;
gi->GameStatus[x4][y4] = 0;
if (gi->GameStatus[xx1][yy1]==0 && gi->GameStatus[xx2][yy2]==0 && gi->GameStatus[xx3][yy3]==0 && gi->GameStatus[xx4][yy4]==0
&& yy1>=0 && yy4<=gi->m_iCol-1
&& !(xx1<0 || xx2<0 || xx3<0 || xx4<0)
&& !(xx1>gi->m_iRow-1 || xx2>gi->m_iRow-1 || xx3>gi->m_iRow-1 || xx4>gi->m_iRow-1) )
{
InvalidateCurrent(hwnd);
gi->ActiveStatus[0][0]=xx1; gi->ActiveStatus[1][0]=xx2;
gi->ActiveStatus[2][0]=xx3; gi->ActiveStatus[3][0]=xx4;
gi->ActiveStatus[0][1]=yy1; gi->ActiveStatus[1][1]=yy2;
gi->ActiveStatus[2][1]=yy3; gi->ActiveStatus[3][1]=yy4;
gi->GameStatus[xx1][yy1] = 1; gi->GameStatus[xx2][yy2] = 1;
gi->GameStatus[xx3][yy3] = 1; gi->GameStatus[xx4][yy4] = 1;
InvalidateCurrent(hwnd);
//改变形状代码
gi->m_currentRect = m_lscurrentRect;
}else{
gi->GameStatus[x1][y1] = 1; gi->GameStatus[x2][y2] = 1;
gi->GameStatus[x3][y3] = 1; gi->GameStatus[x4][y4] = 1;
}
ActiveIsBottom(hwnd);//判断是否已到底
}
void RectDown(HWND hwnd)
{
TETRISINFO*gi;
ActiveIsBottom(hwnd);
if (!gi->m_isBottom)
{
//清除以前的方块
int x1,x2,x3,x4,y1,y2,y3,y4;
x1 = gi->ActiveStatus[0][0]; x2 = gi->ActiveStatus[1][0];
x3 = gi->ActiveStatus[2][0]; x4 = gi->ActiveStatus[3][0];
y1 = gi->ActiveStatus[0][1]; y2 = gi->ActiveStatus[1][1];
y3 = gi->ActiveStatus[2][1]; y4 = gi->ActiveStatus[3][1];
gi->GameStatus[x1][y1]=0; gi->GameStatus[x2][y2]=0;
gi->GameStatus[x3][y3]=0; gi->GameStatus[x4][y4]=0;
InvalidateCurrent(hwnd);
//方块下落
gi->ActiveStatus[0][0] += 1; gi->ActiveStatus[1][0] += 1;
gi->ActiveStatus[2][0] += 1; gi->ActiveStatus[3][0] += 1;
gi->GameStatus[x1+1][y1]=1; gi->GameStatus[x2+1][y2]=1;
gi->GameStatus[x3+1][y3]=1; gi->GameStatus[x4+1][y4]=1;
InvalidateCurrent(hwnd);
}
}
/* * * * * * * * * * * * * * * * * * * * * *
* 内部函数:当前方块下降加速,左移,右移
*
* 最后修改日期:1999.1.22
* * * * * * * * * * * * * * * * * * * * * */
void RectArrow(HWND hwnd,int m_Type)
{
//清除以前的方块
int x1,x2,x3,x4,y1,y2,y3,y4;
TETRISINFO*gi;
x1 = gi->ActiveStatus[0][0]; x2 = gi->ActiveStatus[1][0];
x3 = gi->ActiveStatus[2][0]; x4 = gi->ActiveStatus[3][0];
y1 = gi->ActiveStatus[0][1]; y2 = gi->ActiveStatus[1][1];
y3 = gi->ActiveStatus[2][1]; y4 = gi->ActiveStatus[3][1];
//如果方块已到底则不能再移动
switch(m_Type)
{
case LEFT:
if ( (gi->ActiveStatus[0][1]>0) && LeftIsLimit(hwnd) && !gi->m_isBottom)
{
//清原来的方块
gi->GameStatus[x1][y1]=0; gi->GameStatus[x2][y2]=0;
gi->GameStatus[x3][y3]=0; gi->GameStatus[x4][y4]=0;
InvalidateCurrent(hwnd);
gi->ActiveStatus[0][1] -= 1; gi->ActiveStatus[1][1] -= 1;
gi->ActiveStatus[2][1] -= 1; gi->ActiveStatus[3][1] -= 1;
gi->GameStatus[x1][y1-1]=1; gi->GameStatus[x2][y2-1]=1;
gi->GameStatus[x3][y3-1]=1; gi->GameStatus[x4][y4-1]=1;
InvalidateCurrent(hwnd);
}
break;
case RIGHT:
if ( (gi->ActiveStatus[3][1]< gi->m_iCol-1) && RightIsLimit() && !gi->m_isBottom)
{
//清原来的方块
gi->GameStatus[x1][y1]=0; gi->GameStatus[x2][y2]=0;
gi->GameStatus[x3][y3]=0; gi->GameStatus[x4][y4]=0;
InvalidateCurrent(hwnd);
gi->ActiveStatus[0][1] += 1; gi->ActiveStatus[1][1] += 1;
gi->ActiveStatus[2][1] += 1; gi->ActiveStatus[3][1] += 1;
gi->GameStatus[x1][y1+1]=1; gi->GameStatus[x2][y2+1]=1;
gi->GameStatus[x3][y3+1]=1; gi->GameStatus[x4][y4+1]=1;
InvalidateCurrent(hwnd);
}
break;
case DOWN:
//顺序下降,每降一级判断是否已到底
RectDown(hwnd);
break;
}
}
void ActiveStatusToGameStatus()
{
TETRISINFO*gi;
int x1,x2,x3,x4,y1,y2,y3,y4;
x1 = gi->ActiveStatus[0][0]; x2 = gi->ActiveStatus[1][0];
x3 = gi->ActiveStatus[2][0]; x4 = gi->ActiveStatus[3][0];
y1 = gi->ActiveStatus[0][1]; y2 = gi->ActiveStatus[1][1];
y3 = gi->ActiveStatus[2][1]; y4 = gi->ActiveStatus[3][1];
gi->GameStatus[x1][y1]=1; gi->GameStatus[x2][y2]=1;
gi->GameStatus[x3][y3]=1; gi->GameStatus[x4][y4]=1;
}
void RectStatusToActiveStatus(int m_which)
{
TETRISINFO*gi;
switch(m_which)
{
case 1:
gi->ActiveStatus[0][0] = 0; gi->ActiveStatus[0][1] = 5; gi->ActiveStatus[1][0] = 1; gi->ActiveStatus[1][1] = 5;
gi->ActiveStatus[2][0] = 2; gi->ActiveStatus[2][1] = 5; gi->ActiveStatus[3][0] = 3; gi->ActiveStatus[3][1] = 5;
break;
case 2:
gi->ActiveStatus[0][0] = 0; gi->ActiveStatus[0][1] = 5; gi->ActiveStatus[1][0] = 1; gi->ActiveStatus[1][1] = 5;
gi->ActiveStatus[2][0] = 0; gi->ActiveStatus[2][1] = 6; gi->ActiveStatus[3][0] = 1; gi->ActiveStatus[3][1] = 6;
break;
case 3:
gi->ActiveStatus[0][0] = 1; gi->ActiveStatus[0][1] = 4; gi->ActiveStatus[1][0] = 0; gi->ActiveStatus[1][1] = 5;
gi->ActiveStatus[2][0] = 1; gi->ActiveStatus[2][1] = 5; gi->ActiveStatus[3][0] = 1; gi->ActiveStatus[3][1] = 6;
break;
case 4:
gi->ActiveStatus[0][0] = 0; gi->ActiveStatus[0][1] = 5; gi->ActiveStatus[1][0] = 1; gi->ActiveStatus[1][1] = 5;
gi->ActiveStatus[2][0] = 1; gi->ActiveStatus[2][1] = 6; gi->ActiveStatus[3][0] = 2; gi->ActiveStatus[3][1] = 6;
break;
case 5:
gi->ActiveStatus[0][0] = 1; gi->ActiveStatus[0][1] = 5; gi->ActiveStatus[1][0] = 2; gi->ActiveStatus[1][1] = 5;
gi->ActiveStatus[2][0] = 0; gi->ActiveStatus[2][1] = 6; gi->ActiveStatus[3][0] = 1; gi->ActiveStatus[3][1] = 6;
break;
case 6:
gi->ActiveStatus[0][0] = 0; gi->ActiveStatus[0][1] = 5; gi->ActiveStatus[1][0] = 0; gi->ActiveStatus[1][1] = 6;
gi->ActiveStatus[2][0] = 1; gi->ActiveStatus[2][1] = 6; gi->ActiveStatus[3][0] = 2; gi->ActiveStatus[3][1] = 6;
break;
case 7:
gi->ActiveStatus[0][0] = 0; gi->ActiveStatus[0][1] = 5; gi->ActiveStatus[1][0] = 1; gi->ActiveStatus[1][1] = 5;
gi->ActiveStatus[2][0] = 2; gi->ActiveStatus[2][1] = 5; gi->ActiveStatus[3][0] = 0; gi->ActiveStatus[3][1] = 6;
break;
}
}
/* * * * * * * * * * * * * * * * * * * * * *
* 内部函数:初始掉落时,将根据方块的样式决定下一次将要掉下来的动态数组的值
*
* 最后修改日期:1999.1.22
* * * * * * * * * * * * * * * * * * * * * */
void RectStatusToNextStatus(int m_which)
{
TETRISINFO*gi;
switch(m_which)
{
case 1:
gi->NextStatus[0][0] = 0; gi->NextStatus[0][1] = 1; gi->NextStatus[1][0] = 1; gi->NextStatus[1][1] = 1;
gi->NextStatus[2][0] = 2; gi->NextStatus[2][1] = 1; gi->NextStatus[3][0] = 3; gi->NextStatus[3][1] = 1;
break;
case 2:
gi->NextStatus[0][0] = 0; gi->NextStatus[0][1] = 1; gi->NextStatus[1][0] = 1; gi->NextStatus[1][1] = 1;
gi->NextStatus[2][0] = 0; gi->NextStatus[2][1] = 2; gi->NextStatus[3][0] = 1; gi->NextStatus[3][1] = 2;
break;
case 3:
gi->NextStatus[0][0] = 1; gi->NextStatus[0][1] = 0; gi->NextStatus[1][0] = 0; gi->NextStatus[1][1] = 1;
gi->NextStatus[2][0] = 1; gi->NextStatus[2][1] = 1; gi->NextStatus[3][0] = 1; gi->NextStatus[3][1] = 2;
break;
case 4:
gi->NextStatus[0][0] = 0; gi->NextStatus[0][1] = 1; gi->NextStatus[1][0] = 1; gi->NextStatus[1][1] = 1;
gi->NextStatus[2][0] = 1; gi->NextStatus[2][1] = 2; gi->NextStatus[3][0] = 2; gi->NextStatus[3][1] = 2;
break;
case 5:
gi->NextStatus[0][0] = 1; gi->NextStatus[0][1] = 1; gi->NextStatus[1][0] = 2; gi->NextStatus[1][1] = 1;
gi->NextStatus[2][0] = 0; gi->NextStatus[2][1] = 2; gi->NextStatus[3][0] = 1; gi->NextStatus[3][1] = 2;
break;
case 6:
gi->NextStatus[0][0] = 0; gi->NextStatus[0][1] = 1; gi->NextStatus[1][0] = 0; gi->NextStatus[1][1] = 2;
gi->NextStatus[2][0] = 1; gi->NextStatus[2][1] = 2; gi->NextStatus[3][0] = 2; gi->NextStatus[3][1] = 2;
break;
case 7:
gi->NextStatus[0][0] = 0; gi->NextStatus[0][1] = 1; gi->NextStatus[1][0] = 1; gi->NextStatus[1][1] = 1;
gi->NextStatus[2][0] = 2; gi->NextStatus[2][1] = 1; gi->NextStatus[3][0] = 0; gi->NextStatus[3][1] = 2;
break;
}
}
void OnTimer(HWND hwnd,unsigned int nIDEvent)
{
//如果原来的方块已到底或游戏刚开始,则掉下一个新的方块
int i,j,k;
TETRISINFO*gi;
if (gi->m_isBottom)
{
RECT rect;
gi->m_icurrentStatus =gi->m_inextStatus;
gi->m_inextStatus = Random(7); //得到下一次的方块样式
if (gi->m_inextStatus==0) gi->m_inextStatus++;
gi->m_currentRect = gi->m_icurrentStatus; //当前落下的方块的形状代码
RectStatusToActiveStatus( gi->m_icurrentStatus );
ActiveStatusToGameStatus();
gi->m_isBottom = 0;//FALSE;
ActiveIsBottom(hwnd);
InvalidateCurrent(hwnd);
//在屏幕右边显示下一次将会出来的方块的模样
RectStatusToNextStatus( gi->m_inextStatus );
SetRect(&rect,gi->m_iStartY+320, gi->m_iStartX, gi->m_iStartY+440, gi->m_iStartX+160);
InvalidateRect(hwnd,&rect);
//判断游戏是否已结束: 碰了底,且第1行有小方块
if (gi->m_isBottom)
for (i=0;i<gi->m_iCol;i++)
if (gi->GameStatus[0][i])
{
KillTimer(hwnd,1);
//AfxMessageBox("游戏已结束!");
for (j=0;j<gi->m_iRow;j++)
for (k=0;k<gi->m_iCol;k++)
gi->GameStatus[j][k]=0;
InvalidateRect(hwnd,NULL);
gi->m_bGameEnd =1;// TRUE;
break;
}
}else{ //当前方块下降
RectDown(hwnd);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
//=======================================================================================
static unsigned int GameProc(HWND hWnd,unsigned int msgID,unsigned wParam,unsigned int lParam)
{
switch(msgID){
case WM_KEYDOWN:
switch(wParam){
case VK_ESCAPE:DefaultWndProc(hWnd,msgID,wParam,lParam);break;
case VK_RETURN://OnStart(hWnd);break;
default:
DefaultWndProc(hWnd,msgID,wParam,lParam);
}
break;
case WM_PAINT: DefaultWndProc(hWnd,msgID,wParam,lParam);break;
case WM_TIMER:
OnTimer(hWnd,wParam);
break;
default:return DefaultWndProc(hWnd,msgID,wParam,lParam);
}
return 0;
}
HWND OCreateTetris(void)
{
HWND hlvl;
HWND hGameWnd=CreateWindow("WINDOW","Tetris Game",WS_VISIBLE,10,10,500,500,NULL,NULL);//,GameProc);
AddListItem(hlvl,"Level 1",0);
AddListItem(hlvl,"Level 2",0);
AddListItem(hlvl,"Level 3",0);
AddListItem(hlvl,"Level 4",0);
AddListItem(hlvl,"Level 5",0);
SetItemIndex(hlvl,0);
ShowWindow(hGameWnd,SW_SHOWNORMAL);
return hGameWnd;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -