1. 花了几天时间,终于把俄罗斯方块实现的差不多了,还有一些功能还没有实现,程序也没有进行优化,以后慢慢改进。
#include <graphics.h>#include <time.h>
#include <conio.h>
#include <windows.h>
#include <stdlib.h>
#include <dos.h>
struct WorkStruct{
int u, d, l, r;
}work[4],temp[4];
char direction;//方块旋转的方向
char newBoxFlag;//产生新方块标志
char downFlag;//消行标志
int initL, initR, initU, initD;//旋转用到
int clearMax = -1;
int clearMin = 1000;
int gameScore; //游戏分值
int gameLevel; //游戏等级
int speed;
int nextBox; //下一个方块
int currentBox; //当前方块
int tempCurrentBox; //用于变换
char i[4][4][4] =
{
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
char j[4][4][4] =
{
0, 1, 0, 0,
0, 1, 0, 0,
1, 1, 0, 0,
0, 0, 0, 0,
1, 1, 1, 0,
0, 0, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0,
1, 1, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
char z[4][4][4] =
{
1, 1, 0, 0,
0, 1, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 1, 0, 0,
1, 1, 0, 0,
1, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
0, 1, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 1, 0, 0,
1, 1, 0, 0,
1, 0, 0, 0,
0, 0, 0, 0
};
char o[4][4][4] =
{
1, 1, 0, 0,
1, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
1, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
1, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
1, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
char y[4][4][4] =
{
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0
};
void init(char tmp[][4][4])
{
int j, k, l;
int cnt = 0;
j = direction;
for (k = 0; k < 4; k++)
{
for (l = 0; l < 4; l++)
{
if (tmp[j][k][l] == 1)
{
work[cnt].l = initL + l * 20;
work[cnt].u = initU + k * 20;
work[cnt].r = initR + l * 20;
work[cnt].d = initD + k * 20;
cnt++;
}
}
}
}
void block()
{
int k;
for (k = 0; k < 4; k++)
{
fillrectangle(work[k].l, work[k].u, work[k].r, work[k].d);
}
}
void preBlock()
{
int k;
for (k = 0; k < 4; k++)
{
fillrectangle(work[k].l + 240, work[k].u + 70, work[k].r + 240, work[k].d + 70);
}
}
void clearPreBlock()
{
clearrectangle(340, 110, 420, 190);
}
char isOut(int x, int y)
{
int k;
for (k = 0; k < 4; k++)
{
if (work[k].l < x && work[k].r > x && work[k].u < y && work[k].d > y)
{
return 0;
}
}
return 1;
}
void up()
{
int k;
direction++;//变换到下一个
if (direction == 4)
{
direction = 0;
}
for (k = 0; k < 4; k++)
{
clearrectangle(work[k].l, work[k].u, work[k].r, work[k].d);
}
switch (tempCurrentBox)
{
case 0:init(j); break;
case 1:init(z); break;
case 2:init(i); break;
case 3:init(o); break;
case 4:init(y); break;
default:break;
}
block();
}
void down()
{
int k;
COLORREF pixel;
for (k = 0; k < 4; k++)
{
if (isOut(work[k].l + 10, work[k].d + 10))
{
pixel = getpixel(work[k].l + 10, work[k].d + 10);
}
if (work[k].d == 440 || (GetRValue(pixel) == 255 && GetGValue(pixel) == 255 && GetBValue(pixel) == 255))
{
newBoxFlag = 1;
return;
}
}
for (k = 0; k < 4; k++)
{
clearrectangle(work[k].l, work[k].u, work[k].r, work[k].d);
}
for (k = 0; k < 4; k++)
{
work[k].u += 20;
work[k].d += 20;
}
initU += 20;
initD += 20;
block();
}
void left()
{
int k;
int pixel;
for (k = 0; k < 4; k++)
{
if (isOut(work[k].l - 10, work[k].d - 10))
{
pixel = getpixel(work[k].l - 10, work[k].d - 10);
}
if (work[k].l == 40 || (GetRValue(pixel) == 255 && GetGValue(pixel) == 255 && GetBValue(pixel) == 255))
{
return;
}
}
for (k = 0; k < 4; k++)
{
clearrectangle(work[k].l, work[k].u, work[k].r, work[k].d);
}
for (k = 0; k < 4; k++)
{
work[k].l -= 20;
work[k].r -= 20;
}
initL -= 20;
initR -= 20;
block();
}
void right()
{
int k;
int pixel;
for (k = 0; k < 4; k++)
{
if (isOut(work[k].r + 10, work[k].d - 10))
{
pixel = getpixel(work[k].r + 10, work[k].d - 10);
}
if (work[k].r == 240 || (GetRValue(pixel) == 255 && GetGValue(pixel) == 255 && GetBValue(pixel) == 255))
{
return;
}
}
for (k = 0; k < 4; k++)
{
clearrectangle(work[k].l, work[k].u, work[k].r, work[k].d);
}
for (k = 0; k < 4; k++)
{
work[k].l += 20;
work[k].r += 20;
}
initL += 20;
initR += 20;
block();
}
void backgroundArea()
{
line(39, 39, 241, 39);
line(39, 441, 241, 441);
line(39, 39, 39, 441);
line(241, 39, 241, 441);
}
void downBox()
{
COLORREF color;
int j, k, l;
k = clearMin - 10;
j = clearMax + 10;
for (; k >= 40; k--, j--)
{
for (l = 40; l <= 240; l++)
{
color = getpixel(l, k);
putpixel(l, j, color);
}
}
}
void clearBox()
{
int k, l;
int cnt = 0;
int pixel;
for (l = 430; l >= 50; l -= 20)
{
cnt = 0;
for (k = 50; k <= 230; k += 20)
{
pixel = getpixel(k, l);
if (GetRValue(pixel) == 255 && GetGValue(pixel) == 255 && GetBValue(pixel) == 255)//如果某一行某个点是白色,则计算器加1
{
cnt++;
}
else
{
break;
}
}
if (cnt == 10)
{
if (l > clearMax)
{
clearMax = l;//记录先消去的行
}
if (l < clearMin)
{
clearMin = l;//记录最后消去的行
}
clearrectangle(40, l - 10, 240, l + 10);
downFlag = 1;
gameScore += 100;
}
}
}
int makeNextBox(int index)
{
srand((unsigned int)time(0));
if (index == -1)
{
nextBox = rand() % 5;
index = nextBox;
}
currentBox = nextBox;
switch (index)
{
case 0:init(j); break;
case 1:init(z); break;
case 2:init(i); break;
case 3:init(o); break;
case 4:init(y); break;
default:break;
}
return rand() % 5;
}
void dispalyInfo()
{
TCHAR next[] = _T("下一个:");
outtextxy(300, 80, next);
TCHAR grade[] = _T("分数:");
outtextxy(300, 200, grade);
TCHAR score[] = _T("0");
outtextxy(360, 200, score);//分数的显示位置
TCHAR s[] = _T("分");
outtextxy(400, 200, s);
TCHAR level[] = _T("等级:");
outtextxy(300, 230, level);
TCHAR lev[] = _T("1");
outtextxy(360, 230, lev);//等级的显示位置
TCHAR s1[] = _T("级");
outtextxy(400, 230, s1);
}
void init()
{
// 初始化图形模式
initgraph(480, 540);
// 设置字体
settextstyle(16, 8, _T("Courier"));
gameLevel = 1;
gameScore = 0;
speed = 200;
// 设置颜色
setlinecolor(GREEN);
backgroundArea();
initL = 100;
initU = 40;
initR = 120;
initD = 60;
}
void main()
{
char key;
int nextFlag = 0;
init();
dispalyInfo();
nextBox = makeNextBox(-1);//显示正在工作的
block();
tempCurrentBox = currentBox;
int i;
for (i = 0; i < 4; i++)
{
temp[i].l = work[i].l;
temp[i].u = work[i].u;
temp[i].r = work[i].r;
temp[i].d = work[i].d;
}
makeNextBox(nextBox);//显示下一个
preBlock();
nextFlag = 1;
_getch();
while (1)
{
if (nextFlag)
{
for (i = 0; i < 4; i++)
{
work[i].l = temp[i].l;
work[i].u = temp[i].u;
work[i].r = temp[i].r;
work[i].d = temp[i].d;
}
nextFlag = 0;
}
if (_kbhit())
{
key = _getch();
}
else
{
key = 's';
}
switch (key)
{
case 'a': left(); break;
case 'd': right(); break;
case 's': down(); break;
case 'w': up(); break;
default: break;
}
Sleep(speed);
if (newBoxFlag)
{
clearBox();
newBoxFlag = 0;
direction = 0;
initL = 100;
initU = 40;
initR = 120;
initD = 60;
if (downFlag)
{
downBox();
TCHAR tmp[5];
_stprintf_s(tmp, _T("%d"), gameScore); // 高版本 VC 推荐使用 _stprintf_s 函数
clearrectangle(360, 200, 390, 220);
outtextxy(360, 200, tmp);
if (gameScore == 1000)
{
speed = 100;
gameLevel = 2;
_stprintf_s(tmp, _T("%d"), gameLevel); // 高版本 VC 推荐使用 _stprintf_s 函数
clearrectangle(360, 230, 390, 250);
outtextxy(360, 230, tmp);
}
else if (gameScore == 2000)
{
speed = 50;
gameLevel = 3;
_stprintf_s(tmp, _T("%d"), gameLevel); // 高版本 VC 推荐使用 _stprintf_s 函数
clearrectangle(360, 230, 390, 250);
outtextxy(360, 230, tmp);
}
}
nextBox = makeNextBox(currentBox);
block();
tempCurrentBox = currentBox;
for (i = 0; i < 4; i++)
{
temp[i].l = work[i].l;
temp[i].u = work[i].u;
temp[i].r = work[i].r;
temp[i].d = work[i].d;
}
clearPreBlock();
makeNextBox(nextBox);
preBlock();
downFlag = 0;
nextFlag = 1;
}
}
closegraph();
}
2. 至此,基本功能实现了,但还有一些bug,待参考完书上源代码后,再做改进。游戏截图如下:
3. 书上控制方块下坠是用定时器实现的,本来想把这部分程序搬到本程序中,但是发现有很多地方不兼容,编译通不过,暂时没办法实现按向下键快速坠落的功能,以后再想办法实现。
4. 添加了提示一个方块的功能,同时发现了一些bug,变换的时候没用做越界判断,导致变换后越出边界,消行还有问题。