代码拷贝完,可以直接运行游戏哦
#include<stdio.h>
#include<graphics.h>
#include<Windows.h>
#include<time.h>
#include<conio.h>
int score = 0;//总分
int rank =0;//等级
int NextIndex=-1; //下一个要降落方块的种类
int BlockIndex =1; //本次降落方块的种类
#define BLOCK_COUNT 5
#define BLOCK_WIDTH 5
#define BLOCK_HEIGHT 5
#define START_X 130
#define START_Y 30
#define UNIT_SIZE 20
#define KEY_UP 72
#define KEY_RIGHT 77
#define KEY_LEFT 75
#define KEY_DOWN 80
#define KEY_SPACE 32
int speed=500;
int minX = 30;
int minY =30;
typedef enum{
BLOCK_UP,
BLOCK_RIGHT,
BLOCK_DOWN,
BLOCK_LEFT
}block_dir_t;
typedef enum{
MOVE_DOWN,
MOVE_LEFT,
MOVE_RIGHT
}move_dir_t;
int visit[30][15];
int markColor[30][15]; //对应的数组颜色
int color[BLOCK_COUNT]=
{GREEN ,CYAN ,MAGENTA ,BROWN ,YELLOW };
extern int block[BLOCK_COUNT * 4][BLOCK_HEIGHT][BLOCK_WIDTH];
int main(){
void welcome(); //欢迎界面
void initGameScene();//游戏大体框架
void clearBlock();//清除方块
void clearBlock(int x,int y,block_dir_t dir);
void drawBlock(int x,int y);//画方块
void drawBlock(int x,int y,int blockIndex,block_dir_t dir);
void nextblock();//下一个方块
int moveable(int x0,int y0,move_dir_t moveDir,block_dir_t blockDir);
//检查游戏是否结束
void failCheck(); //检查是否失败
void wait(int interval);
//判断当前位置是否可以转到指定方向
//注意现在这步并没有真正的转向,只是预览一下是否真的可以
int rotatable(int x,int y,block_dir_t dir);//查看是否能旋转
void mark(int x,int y,int BlockIndex,block_dir_t dir);//固定数组
void move(); //核心移动
void newblock();//新方块
void down(int x);//消除第x行的方块,并把上面的全部下移
void Showscore();//用于显示当前分数
void update();//等级更新
void check(); //检查是否满了一行的方块
/*以上为函数声明*/
welcome(); //欢迎界面
initGameScene(); //绘制游戏基本框架
nextblock(); //右上角下一个方块
Sleep(500);
memset(visit,0,sizeof(visit));//初始化访问数组
while(1){
newblock();
check();
}
system("pause");
closegraph();
return 0;
}
void welcome(){
initgraph(550,660);
//设置窗口标题
HWND hwnd = GetHWnd(); //获取窗口
SetWindowText(hwnd,_T("小猪猪的俄罗斯方块"));
//设置游戏标题
setfont(40,0,_T("雅黑"));
setcolor(WHITE);
outtextxy(205,200,_T("俄罗斯方块"));
setfont(22,0,_T("楷体"));
outtextxy(175,300,_T("请开始你的表演!"));
Sleep(3000);
}
void initGameScene(void){
//清除屏幕
char str [16];
cleardevice();
rectangle(27,27,336,635);
rectangle(29,29,334,633);
rectangle(370,50,515,195);
setfont(24,0,_T("楷体"));
setcolor(LIGHTGRAY);
outtextxy(405,215,_T("下一个"));
setcolor(RED);
outtextxy(405,280,_T("分数"));
sprintf(str,"%d",score); //将整形变量以字符形式写入字符串中
outtextxy(415,310,str);
outtextxy(405,375,_T("等级"));
sprintf(str,"%d",rank);
outtextxy(425,405,str);
//操作说明
setcolor(LIGHTBLUE);
outtextxy(390,475,"操作说明");
outtextxy(390,500,"↑:旋转");
outtextxy(390,525,"↓:下降");
outtextxy(390,550,"←:左移");
outtextxy(390,575,"→:右移");
outtextxy(390,600,"空格 暂停");
}
void clearBlock(){
setcolor(BLACK);
setfont(23,0,"楷体");
for(int i=0;i<BLOCK_HEIGHT;i++){
for(int j=0;j<BLOCK_WIDTH;j++){
int x = 391+j*UNIT_SIZE;
int y =71+i*UNIT_SIZE;
outtextxy(x,y,"■");
}
}
}
void clearBlock(int x,int y,block_dir_t dir){
int id = BlockIndex*4+dir;
y+=START_Y;
setcolor(BLACK);
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
if(block[id][i][j] == 1){
//擦除该方块的地i行的第j列
outtextxy(x+j*20,y+i*20,"■");
}
}
}
}
void drawBlock(int x,int y){
setcolor(color[NextIndex]);
setfont(23,0,"楷体");
for(int i=0;i<BLOCK_HEIGHT;i++){
for(int j=0;j<BLOCK_WIDTH;j++){
if(block[NextIndex *4][i][j] == 1){
outtextxy(x+j*UNIT_SIZE,y+i*UNIT_SIZE,"■");
}
}
}
}
void drawBlock(int x,int y,int blockIndex,block_dir_t dir){
setcolor(color[blockIndex]);
setfont(23,0,"楷体");
int id = blockIndex*4+dir;
for(int i=0;i<BLOCK_HEIGHT;i++){
for(int j=0;j<BLOCK_WIDTH;j++){
if(block[id][i][j] == 1){
outtextxy(x+j*UNIT_SIZE,y+i*UNIT_SIZE,"■");
}
}
}
}
void nextblock(){
int x = 391, y = 71;
clearBlock();
srand(time(NULL));
NextIndex = rand()%BLOCK_COUNT;
drawBlock(x,y);
}
//如果在指定位置可以向指定方向移动。就返回1,否则就返回0
int moveable(int x0,int y0,move_dir_t moveDir,block_dir_t blockDir){
int id = BlockIndex *4 +blockDir;
//计算当前方块的左上角在30 x 15的游戏去中的位置(第几行,第几列)
int x = (y0 - minY)/UNIT_SIZE;
int y = (x0-minX)/UNIT_SIZE;
int ret =1;
if(moveDir == MOVE_DOWN){
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
if(block[id][i][j] == 1&&
(x+i+1>=30||visit[x+i+1][y+j] == 1)){
ret = 0;
}
}
}
}else if(moveDir == MOVE_LEFT){
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
if(block[id][i][j] == 1&&
(y + j == 0||visit[x+i][y+j-1] == 1)){
ret = 0;
}
}
}
}else if(moveDir == MOVE_RIGHT){
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
if(block[id][i][j] == 1&&
(y + j +1 == 15||visit[x+i][y+j+1] == 1)){
ret = 0;
}
}
}
}
return ret;
}
//检查游戏是否结束
void failCheck(){
if(!moveable(START_X,START_Y,MOVE_DOWN,BLOCK_UP)){
setcolor(WHITE);
setfont(45,0,"隶体");
outtextxy(75,300,_T("GAME OVER!!!"));
Sleep(1000);
system("pause");
closegraph();
exit(0);
}
}
void wait(int interval){ //500
int count = interval/10;
for(int i=0;i<count;i++)
{
Sleep(10);
if(kbhit()){
return ;
}
}
}
//判断当前位置是否可以转到指定方向
//注意现在这步并没有真正的转向,只是预览一下是否真的可以
int rotatable(int x,int y,block_dir_t dir){
if(!moveable(x,y,MOVE_DOWN,dir)){
return 0;
}
int id= BlockIndex*4+dir;
int x2 = (y - minY)/UNIT_SIZE;
int y2 = (x-minX)/UNIT_SIZE;
for(int i = 0;i<5;i++){
for(int j = 0;j<5;j++){
if(block[id][i][j] == 1&&
(y2+j < 0||y2+j >= 15 ||visit[x2+i][y2+j] == 1)){
return 0;
}
}
}
return 1;
}
void mark(int x,int y,int BlockIndex,block_dir_t dir){
int x2 =(y-minY)/UNIT_SIZE;
int y2 = (x-minX)/UNIT_SIZE;
int id = BlockIndex*4+dir;
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
if(block[id][i][j] == 1){
visit[x2+i][y2+j] = 1;
markColor[x2+i][y2+j] = color[BlockIndex];
}
}
}
}
void move(){
int x = START_X;
int y = START_Y;
int k=0;
block_dir_t blockDir =BLOCK_UP;
int curSpeed = speed;
failCheck(); //检查游戏是否结束
//持续下降
while(1){
if(kbhit()){
int key = getch();
if(key == KEY_SPACE){
getch();
}
}
//清除当前方块
clearBlock(x,k,blockDir);
if(kbhit()){
int key = getch();
if(key == KEY_UP){
block_dir_t nextDir = (block_dir_t)((blockDir+1)%4);
if(rotatable(x,y+k,nextDir)){
blockDir = nextDir;
}
}else if(key == KEY_DOWN){
curSpeed =50;
}else if(key == KEY_LEFT){
if(moveable(x,y+k+20,MOVE_LEFT,blockDir)){
x-=20;
}
}else if(key == KEY_RIGHT){
if(moveable(x,y+k+20,MOVE_RIGHT,blockDir)){
x+=20;
}
}
}
k+=20;
//绘制当前方块
drawBlock(x,y+k,BlockIndex,blockDir);
//用户等待时间
wait(curSpeed);
//方块的“固化”处理
if(!moveable(x,y+k,MOVE_DOWN,blockDir)){
mark(x,y+k,BlockIndex,blockDir);
break;
}
}
}
void newblock(){
BlockIndex= NextIndex; //将右上角的方块种类赋值给要下落的方块
drawBlock(START_X,START_Y);//在主界面中绘制方块
Sleep(100);//让用户识别到
nextblock(); //下一个方块
move(); //方块下落
}
//消除第x行的方块,并把上面的全部下移
void down(int x){
for(int i=x;i>0;i--){
for(int j=0;j<15;j++){
if(visit[i-1][j]){
visit[i][j] = 1;
markColor[i][j] = markColor[i-1][j];
setcolor(markColor[i][j]);
outtextxy(minX+j*20,minY+i*20,"■");
}else{
visit[i][j] = 0;
setcolor(BLACK);
outtextxy(minX+j*20,minY+i*20,"■");
}
}
}
if(x == 0){
for(int j=0;j<15;j++){
visit[0][j]=0;
setcolor(BLACK);
outtextxy(minX+j*20,0,"■");
}
}
}
//用于显示当前分数
void Showscore(){
char str[32];
sprintf(str,"%d",score);
setcolor(RED);
outtextxy(415,310,str);
}
void update(){//本函数实现两个功能
//实现显示等级
rank = score/50;
char str[16];
sprintf(str,"%d",rank);
outtextxy(425,405,str);
//随着等级提升改变速度
speed = 500 - rank*100;
if(speed <=100){
speed=100;
}
}
void check(){ //检查是否一行全部占满
int i,j;
for(i=29;i>=0;i--){
//检查第i行有没有满
for(j=0;j<15&&visit[i][j];j++);
//此时有两种情况
//第一种:一行未满 即j<15
//第二种:一行全部占满j= = 15
if(j==15){
//此时已经满了,就需要消除第i行
down(i);//实现消除第i行,并把上面的行都下移
i++;//特别注意,因为最外层的循环 中有i--,
//所以我们必须在下次循环时再检查一遍这一行
score+=10;
//显示积分
Showscore();
//显示等级以及更新速度
update();
}
}
}
int block[BLOCK_COUNT * 4][BLOCK_HEIGHT][BLOCK_WIDTH] = {//方块的种类
// | 形方块
{ 0,0,0,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
// L 形方块
{ 0,0,0,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,1,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,1,0,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,1,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,0,0,1,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
// 田 形方块
{ 0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
// T 形方块
{ 0,0,0,0,0,
0,1,1,1,0,
0,0,1,0,0,
0,0,0,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,0,0,1,0,
0,0,1,1,0,
0,0,0,1,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,0,1,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,1,0,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0 },
// Z 形方块
{ 0,0,0,0,0,
0,1,1,0,0,
0,0,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,0,1,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,1,1,0,0,
0,0,1,1,0,
0,0,0,0,0,
0,0,0,0,0 },
{ 0,0,0,0,0,
0,0,1,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0 },
};