📄 tetris.c
字号:
// HWRECTView.cpp : implementation of the CHWRECTView class
//
#include "games.h"
#include "osdwindows.h"
#include"PrSync.h"
#define IDC_GAMELEVEL 1
//下降,左移,右移宏定义
#define LEFT 0
#define RIGHT 1
#define UP 2
#define DOWN 3
typedef struct TetrisInfo{
int m_iCol;//小方块的大小,它会随着行与列的不同而不同,具体为:
int m_iRow; // 12行10列,30个象素的正方形 // 18行15列,20 // 24行20列,15 // 30行25列,12
int m_iLarge;
int m_iLevel;//当前的级别,换算成速度的算法为:1500 - m_iLevel*200
int m_iStartX;//游戏区域左上角的坐标
int m_iStartY;
int InterFace[74][4];//各种不同形状方块的接触面,接触面是指这样的小方块:它下面如果有另外的方块则表示
//此方块已到底。此数组记录了这些接触面在当前方块动态位置数组中的元素号
int m_currentRect;//当前的方块形状
int m_isBottom;
//用于标志方块状态的数组,大小由横格与竖格数据决定,为1表示该方块显示,或者不显示
//画形状只需要修改数组中相应元素的状态值即可
//由时钟控制,定时在OnPaint函数中根据数组画方块
int GameStatus[100][100];//用于保存当前方块的动态位置,4个小方块分别在大数组中的位置
//存放位置为先左后右,每一列又遵循先上后下的原则
int ActiveStatus[4][2];
int NextStatus[4][2]; //存入下一次要出来的方块的模样的数组
int m_icurrentStatus;//当前的样式与下一个将会出现的样式
int m_inextStatus;
int m_iPerformance;//游戏总成绩
int m_bGameEnd;//游戏是否已结束,为FALSE表示开始,否则为结束
}TETRISINFO;
int InitGameInfo(HWND hwnd)
{
int i,j;
TETRISINFO*gi;
gi->m_iPerformance = 0;//总分值清零
gi->m_iRow = 12;//测试值:为12行,10列
gi->m_iCol = 10;
gi->m_iStartX = 10;//左上角X,Y坐标
gi->m_iStartY = 10;
gi->m_iLevel = 2;//缺省级别为3级
gi->m_iLarge = 30;//缺省方块大小为m_iLarge个象素
gi->m_bGameEnd = 1;//TRUE;//缺省游戏是结束的
//赋初值
for (i=0;i<100;i++)
for (j=0;j<100;j++)
gi->GameStatus[i][j]=0;
//各种形状方块的接触面数据,参见设计书的接触面表格, 如果某种形状的方块没有4个接触面,则后面的数据填-1
for (i=0;i<74;i++)
for (j=0;j<4;j++)
gi->InterFace[i][j] = -1;
gi->InterFace[1][0] = 3; gi->InterFace[11][0] = 0;
gi->InterFace[11][1] = 1; gi->InterFace[11][2] = 2; gi->InterFace[11][3] = 3;
gi->InterFace[2][0] = 1; gi->InterFace[2][1] = 3;
gi->InterFace[3][0] = 0; gi->InterFace[3][1] = 2; gi->InterFace[3][2] = 3;
gi->InterFace[31][0] = 2; gi->InterFace[31][1] = 3;
gi->InterFace[32][0] = 0; gi->InterFace[32][1] = 2; gi->InterFace[32][2] = 3;
gi->InterFace[33][0] = 0; gi->InterFace[33][1] = 3;
gi->InterFace[4][0] = 1; gi->InterFace[4][1] = 3;
gi->InterFace[41][0] = 0; gi->InterFace[41][1] = 2; gi->InterFace[41][2] = 3;
gi->InterFace[5][0] = 1; gi->InterFace[5][1] = 3;
gi->InterFace[51][0] = 0; gi->InterFace[51][1] = 2; gi->InterFace[51][2] = 3;
gi->InterFace[6][0] = 0; gi->InterFace[6][1] = 3;
gi->InterFace[61][0] = 1; gi->InterFace[61][1] = 2; gi->InterFace[61][2] = 3;
gi->InterFace[62][0] = 2; gi->InterFace[62][1] = 3;
gi->InterFace[63][0] = 0; gi->InterFace[63][1] = 1; gi->InterFace[63][2] = 3;
gi->InterFace[7][0] = 2; gi->InterFace[7][1] = 3;
gi->InterFace[71][0] = 1; gi->InterFace[71][1] = 2; gi->InterFace[71][2] = 3;
gi->InterFace[72][0] = 0; gi->InterFace[72][1] = 3;
gi->InterFace[73][0] = 0; gi->InterFace[73][1] = 1; gi->InterFace[73][2] = 3;
return 1;
}
int Random(int MaxNumber)
{
int currentClock = PrTimeGetTicks();
srand(currentClock);
return (rand() % MaxNumber);
}
void InvalidateCurrent(HWND hwnd)
{
int i;
TETRISINFO*gi;
for (i=0;i<4;i++)
{
RECT rect;
SetRect(&rect,gi->m_iStartX+gi->ActiveStatus[i][1]*gi->m_iLarge,gi->m_iStartY+gi->ActiveStatus[i][0]*gi->m_iLarge,
gi->m_iStartX+(gi->ActiveStatus[i][1]+1)*gi->m_iLarge+5,gi->m_iStartY+(gi->ActiveStatus[i][0]+1)*gi->m_iLarge);
InvalidateRect(hwnd,&rect);
}
}
int LeftIsLimit(HWND hwnd)
{
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];
switch(gi->m_currentRect)
{
case 1:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1] ||
gi->GameStatus[x3][y3-1] || gi->GameStatus[x4][y4-1])
return 0;//FALSE;
break;
case 11:
if (gi->GameStatus[x1][y1-1])
return 0;//FALSE;
break;
case 2:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1])
return 0;//FALSE;
break;
case 3:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1])
return 0;//FALSE;
break;
case 31:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1] || gi->GameStatus[x3][y3-1])
return 0;//FALSE;
break;
case 32:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x3][y3-1])
return 0;//FALSE;
break;
case 33:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1] || gi->GameStatus[x4][y4-1])
return 0;//FALSE;
break;
case 4:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1] || gi->GameStatus[x4][y4-1])
return 0;//FALSE;
break;
case 41:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1])
return 0;//FALSE;
break;
case 5:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1] || gi->GameStatus[x3][y3-1])
return 0;//FALSE;
break;
case 51:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x3][y3-1])
return 0;//FALSE;
break;
case 6:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x3][y3-1] || gi->GameStatus[x4][y4-1])
return 0;//FALSE;
break;
case 61:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1])
return 0;//FALSE;
break;
case 62:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1] || gi->GameStatus[x3][y3-1])
return 0;//FALSE;
break;
case 63:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x3][y3-1])
return 0;//FALSE;
break;
case 7:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1] || gi->GameStatus[x3][y3-1])
return 0;//FALSE;
break;
case 71:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1])
return 0;//FALSE;
break;
case 72:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x2][y2-1] || gi->GameStatus[x3][y3-1])
return 0;//FALSE;
break;
case 73:
if (gi->GameStatus[x1][y1-1] || gi->GameStatus[x4][y4-1])
return 0;//FALSE;
break;
}
return 1;//TRUE;
}
/* * * * * * * * * * * * * * * * * * * * * *
* 内部函数:方块是否还可以右移
*
* 最后修改日期:1999.1.22
* * * * * * * * * * * * * * * * * * * * * */
int RightIsLimit()
{
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];
switch(gi->m_currentRect)
{
case 1:
if (gi->GameStatus[x1][y1+1] || gi->GameStatus[x2][y2+1] || gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 11:
if (gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 2:
if (gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 3:
if (gi->GameStatus[x2][y2+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 31:
if (gi->GameStatus[x1][y1+1] || gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 32:
if (gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 33:
if (gi->GameStatus[x2][y2+1] || gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 4:
if (gi->GameStatus[x1][y1+1] || gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 41:
if (gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 5:
if (gi->GameStatus[x2][y2+1] || gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 51:
if (gi->GameStatus[x2][y2+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 6:
if (gi->GameStatus[x2][y2+1] || gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 61:
if (gi->GameStatus[x2][y2+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 62:
if (gi->GameStatus[x1][y1+1] || gi->GameStatus[x2][y2+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 63:
if (gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 7:
if (gi->GameStatus[x2][y2+1] || gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 71:
if (gi->GameStatus[x1][y1+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 72:
if (gi->GameStatus[x2][y2+1] || gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
case 73:
if (gi->GameStatus[x3][y3+1] || gi->GameStatus[x4][y4+1])
return 0;//FALSE;
break;
}
return 1;//TRUE;
}
void ActiveIsBottom(HWND hwnd)
{
//到底有两种概念:1是已到底部,2是下面碰到了另外的方块
int x1,x2,x3,x4;
int x,xx,yy,i;
TETRISINFO*gi;
int m_bIsSucced;
int k,j;
int m_iMuch=0; //本次销掉的行数
x1 = gi->ActiveStatus[0][0]; x2 = gi->ActiveStatus[1][0];
x3 = gi->ActiveStatus[2][0]; x4 = gi->ActiveStatus[3][0];
//已到底
//如果下面碰到了另外的方块
//一个方块分为四个小方块,只有这样的小方块下面有另外的方块才算到底,这样的小方块满足条件如下:
//它的下面不再有本方块的另外的小方块
//用算法描述为:y坐标相等的一组小方块中的最下面的哪个小方块, 我称之为接触面
if (x1>=gi->m_iRow-1 || x2>=gi->m_iRow-1 || x3>=gi->m_iRow-1 || x4>=gi->m_iRow-1)
gi->m_isBottom = 1;//TRUE;
else{
for (i=0;i<4;i++)
{
if (gi->InterFace[gi->m_currentRect][i] > -1)
{
x=gi->InterFace[gi->m_currentRect][i];
xx=gi->ActiveStatus[x][0]+1;
yy=gi->ActiveStatus[x][1];
if (gi->GameStatus[xx][yy]==1)
gi->m_isBottom = 1;//TRUE;
}
}
}
//计分规则:一次销掉一行,加100分,一次销掉两行,加400分,三行,900分
//例如销掉x行,则分数为:x*(x*100)
if (gi->m_isBottom)
{
//判断是否已得分
for (i=0;i<gi->m_iRow;i++)
{
m_bIsSucced = 1;//TRUE;
for (j=0;j<gi->m_iCol;j++)
if (gi->GameStatus[i][j]==0)
m_bIsSucced = 0;//FALSE;
//如果得分,则销掉此行
if (m_bIsSucced){
for (k=i;k>0;k--)
for (j=0;j<gi->m_iCol;j++)
gi->GameStatus[k][j] = gi->GameStatus[k-1][j];
//第1行清零
for (j=0;j<gi->m_iCol;j++)
gi->GameStatus[0][j]=0;
m_iMuch += 1;
}
}
if (m_iMuch>0)
{
//刷新游戏区域
RECT rc2,rc1;
SetRect(&rc1,gi->m_iStartY, gi->m_iStartX, gi->m_iStartY+300, gi->m_iStartX+360);
gi->m_iPerformance += m_iMuch * m_iMuch * 100;
InvalidateRect(hwnd,&rc1);
//刷新分数区域
SetRect(&rc2,gi->m_iStartY+320, gi->m_iStartX+180, gi->m_iStartY+440, gi->m_iStartX+200);
InvalidateRect(hwnd,&rc2);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -