俄罗斯方块

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,变换的时候没用做越界判断,导致变换后越出边界,消行还有问题。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值