You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
elsfk/俄罗斯方块.c

635 lines
15 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/********头文件*********/
#include<stdio.h>
#include<windows.h>
#include<conio.h>
#include<time.h>
/********宏定义********/
#define FrameX 13
#define FrameY 3
#define Frame_height 20 //定义游戏窗口高度
#define Frame_width 18//定义游戏窗口宽度
/********全局变量*********/
int i,j,Temp,Temp1,Temp2;
int a[80][80]={0};//a数组中2,1,0分别代表边框方块和无图案
int b[4];//每种方块都由四个█组成b数组用来标记四个█的位置以构造图形
struct Tetris
{
int x; //中心方块的x轴坐标
int y; //中心方块的y轴坐标
int flag;//标记方块类型的序号
int next;//下一个方块类型的序号
int speed;//俄罗斯方块产生的速度
int number;//产生俄罗斯方块的个数
int score;//游戏分数
int level;//游戏等级
};
HANDLE hOut;//控制台句柄
/******函数声明*******/
int color(int c);
static void gotoxy(int x, int y);//移动光标位置
void DrawGameframe(); //绘制游戏边框
void Flag(struct Tetris * );//随机产生俄罗斯方块序号
void MakeTetris(struct Tetris *);//制作俄罗斯方块
void PrintTetris(struct Tetris *);//打印俄罗斯方块
void CleanTetris(struct Tetris *);//清除俄罗斯方块的痕迹
int ifMove(struct Tetris *);//判断能否移动
void Del_Fullline(struct Tetris *);//判断是否满行
void GamePlay();//开始游戏
void regulation();//游戏规则
void explation();//按键说明
void welcome();//欢迎界面
void Replay(struct Tetris *);//重新开始游戏
void title();//欢迎界面上方标题
void close();//关闭游戏
/*****文字颜色函数******/
int color(int c){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c);//更改文字颜色
return 0;
}
/*****获取屏幕光标位置*******/
static void gotoxy(int x, int y){
COORD point = { x, y };//光标要设置的位置x,y
HANDLE HOutput = GetStdHandle(STD_OUTPUT_HANDLE);//使用GetStdHandle(STD_OUTPUT_HANDLE)来获取标准输出的句柄
SetConsoleCursorPosition(HOutput, point);//设置光标位置
}
/*****欢迎界面标题********/
void title(){
color(15);
gotoxy(30,3);
printf("趣味俄罗斯方块\n");
//标题
color(11);
gotoxy(18,5);
printf("");
gotoxy(18,6);
printf("██");
gotoxy(18,7);
printf("");
//T字方块
color(14);
gotoxy(26,6);
printf("██");
gotoxy(28,7);
printf("██");
//Z字方块
color(10);
gotoxy(36,6);
printf("██");
gotoxy(36,7);
printf("██");
//田字方块
color(13);
gotoxy(45,5);
printf("");
gotoxy(45,6);
printf("");
gotoxy(45,7);
printf("");
gotoxy(45,8);
printf("");
//直线方块
color(12);
gotoxy(56,6);
printf("");
gotoxy(52,7);
printf("███\n");
//7字方块
}
/*******菜单选项边框*******/
void welcome()
{
int n;
int i,j=1;
color(14);
for(i=9;i<=20;i++){
for(j=15;j<=60;j++){
gotoxy(j,i);
if(i==9||i==20) printf("=");
else if(j==15||j==59) printf("::");
}
}
/*******菜单选项的文字********/
color(12);
gotoxy(25,12);
printf("1.开始游戏");
gotoxy(40,12);
printf("2.按键说明");
gotoxy(25,17);
printf("3.游戏规则");
gotoxy(40,17);
printf("4.退出");
gotoxy(21,22);
printf("请选择[1,2,3,4]:[ ]\b\b");
scanf("%d",&n);
switch(n){
case 1:
system("cls");
DrawGameframe();
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
}
/*******游戏窗口*******/
void DrawGameframe()
{
/***********游戏名称***********/
gotoxy(FrameX+Frame_width-7,FrameY-2);
color(11);
printf("趣味俄罗斯方块");
/**********下一个出现方块********/
gotoxy(FrameX+2*Frame_width+3,FrameY+7);
color(2);
printf("**********");
gotoxy(FrameX+2*Frame_width+13,FrameY+7);
color(3);
printf("下一个出现方块");
gotoxy(FrameX+2*Frame_width+3,FrameY+13);
color(2);
printf("**********");
/**********按键说明***********/
gotoxy(FrameX+2*Frame_width+3,FrameY+17);
color(14);
printf("↑键:旋转");
gotoxy(FrameX+2*Frame_width+3,FrameY+19);
printf("空格:暂停游戏");
gotoxy(FrameX+2*Frame_width+3,FrameY+15);
printf("Esc:退出游戏");
/*********游戏边框***********/
gotoxy(FrameX,FrameY);
color(12);
printf("");
gotoxy(FrameX+2*Frame_width-2,FrameY);
printf("");
gotoxy(FrameX,FrameY+Frame_height);
printf("");
gotoxy(FrameX+2*Frame_width-2,FrameY+Frame_height);
printf("");
a[FrameX][FrameY+Frame_height]=2;
a[FrameX+2*Frame_width-2][FrameY+Frame_height]=2;//防止方块出界
for(i=2;i<2*Frame_width-2;i+=2){
gotoxy(FrameX+i,FrameY);
printf("");
}
for(i=2;i<Frame_width-2;i+=2){
gotoxy(FrameX+i,FrameY+Frame_height);
printf("");
a[FrameX+i][FrameY+Frame_height]=2;
}
for(i=1;i<Frame_height;i++){
gotoxy(FrameX,FrameY+i);
printf("");
a[FrameX][FrameY+i]=2;
}
for(i=1;i<Frame_height;i++){
gotoxy(FrameX+2*Frame_width-2,FrameY+i);
printf("");
a[FrameX+2*Frame_width-2][FrameY+i]=2;
}
}
/********制作俄罗斯方块*********/
void MakeTetris(struct Tetris *tetris){
a[tetris->x][tetris->y]=b[0];//中心方块的图形状态
switch(tetris->flag){
case 1: //田字方块
color(10);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x+2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
case 2: //横直线方块
color(13);
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y]=b[2];
a[tetris->x+4][tetris->y]=b[3];
break;
case 3: //竖直线方块
color(13);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y-2]=b[2];
a[tetris->x][tetris->y+1]=b[3];
break;
case 4: //T字方块
color(11);
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y]=b[2];
a[tetris->x][tetris->y-1]=b[3];
break;
case 5: //顺时针90°T字方块
color(11);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x-2][tetris->y]=b[2];
a[tetris->x][tetris->y+1]=b[3];
break;
case 6: //顺时针180°T字方块
color(11);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x-2][tetris->y]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
case 7: //顺时针270°T字方块
color(11);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
case 8: //Z字方块
color(14);
a[tetris->x+2][tetris->y+1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x-2][tetris->y]=b[3];
break;
case 9: //顺时针Z字方块
color(14);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x-2][tetris->y]=b[2];
a[tetris->x-2][tetris->y+1]=b[3];
break;
case 10: //反Z字方块
color(14);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x-2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
case 11: //顺时针反Z字方块
color(14);
a[tetris->x][tetris->y+1]=b[1];
a[tetris->x-2][tetris->y-1]=b[2];
a[tetris->x-2][tetris->y]=b[3];
break;
case 12: //7字方块
color(12);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x-2][tetris->y-1]=b[3];
break;
case 13: //顺时针90°7字方块
color(12);
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
case 14: //顺时针180°7字方块
color(12);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y+1]=b[3];
break;
case 15: //顺时针270°7字方块
color(12);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
case 16: //反7字方块
color(12);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y-1]=b[3];
break;
case 17: //顺时针90°反7字方块
color(12);
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x+2][tetris->y+1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
case 18: //顺时针180°反7字方块
color(12);
a[tetris->x][tetris->y-1]=b[1];
a[tetris->x][tetris->y+1]=b[2];
a[tetris->x-2][tetris->y+1]=b[3];
break;
case 19: //顺时针270°反7字方块
color(12);
a[tetris->x-2][tetris->y]=b[1];
a[tetris->x-2][tetris->y-1]=b[2];
a[tetris->x+2][tetris->y]=b[3];
break;
}
}
/******打印俄罗斯方块*******/
void PrintTetris(struct Tetris *tetris){
for(i=0;i<4;i++) b[i]=1;
MakeTetris(tetris);
for(i=tetris->x-2;i<=tetris->x+4;i+=2){
for(j=tetris->y-1;j<=tetris->y+1;j++){
if(a[i][j]==1&&j>FrameY){
gotoxy(i,j);
printf("");
}
}
}
//打印菜单信息
gotoxy(FrameX+2*Frame_width+3,FrameY+1);
color(4);
printf("level:");
color(12);
printf("%d",tetris->level);
gotoxy(FrameX+2*Frame_width+3,FrameY+3);
color(4);
printf("score:");
color(12);
printf("%d",tetris->score);
gotoxy(FrameX+2*Frame_width+3,FrameY+3);
color(4);
printf("speed");
color(12);
printf("%dms",tetris->speed);
}
/******判断方块能否移动******/
int ifMove(struct Tetris *tetris)
{
if(a[tetris->x][tetris->y]!=0){
return 0;
}
else{
if(
(tetris->flag==1&&(a[tetris->x][tetris->y-1]==0&&
a[tetris->x][tetris->y-1]==0&&a[tetris->x+2][tetris->y]==0))||
(tetris->flag==2&&(a[tetris->x-2][tetris->y]==0&&
a[tetris->x+2][tetris->y]==0&&a[tetris->x+4][tetris->y]==0))||
(tetris->flag==3&&(a[tetris->x][tetris->y-1]==0&&
a[tetris->x][tetris->y-2]==0&&a[tetris->x][tetris->y+1]==0))||
(tetris->flag==4&&(a[tetris->x-2][tetris->y]==0&&
a[tetris->x+2][tetris->y]==0&&a[tetris->x][tetris->y+1]==0))||
(tetris->flag==5&&(a[tetris->x][tetris->y-1]==0&&
a[tetris->x][tetris->y+1]==0&&a[tetris->x-2][tetris->y]==0))||
(tetris->flag==6&&(a[tetris->x][tetris->y-1]==0&&
a[tetris->x-2][tetris->y]==0&&a[tetris->x+2][tetris->y]==0))||
(tetris->flag==7&&(a[tetris->x][tetris->y-1]==0&&
a[tetris->x][tetris->y+1]==0&&a[tetris->x+2][tetris->y]==0))||
(tetris->flag==8&&(a[tetris->x][tetris->y+1]==0&&
a[tetris->x-2][tetris->y]==0&&a[tetris->x+2][tetris->y+1]==0))||
(tetris->flag==9&&(a[tetris->x][tetris->y-1]==0&&
a[tetris->x-2][tetris->y]==0&&a[tetris->x-2][tetris->y+1]==0))||
(tetris->flag==10&&(a[tetris->x][tetris->y-1]==0&&
a[tetris->x-2][tetris->y-1]==0&&a[tetris->x+2][tetris->y]==0))||
(tetris->flag==11&&(a[tetris->x][tetris->y+1]==0&&
a[tetris->x-2][tetris->y-1]==0&&a[tetris->x-2][tetris->y]==0))||
(tetris->flag==12&&(a[tetris->x][tetris->y-1]==0&&
a[tetris->x][tetris->y+1]==0&&a[tetris->x-2][tetris->y-1]==0))||
(tetris->flag==13&&(a[tetris->x-2][tetris->y]==0&&
a[tetris->x+2][tetris->y-1]==0&&a[tetris->x+2][tetris->y]==0))||
(tetris->flag==14&&(a[tetris->x][tetris->y-1]==0&&
a[tetris->x][tetris->y+1]==0&&a[tetris->x+2][tetris->y+1]==0))||
(tetris->flag==15&&(a[tetris->x-2][tetris->y]==0&&
a[tetris->x-2][tetris->y+1]==0&&a[tetris->x+2][tetris->y]==0))||
(tetris->flag==16&&(a[tetris->x][tetris->y+1]==0&&
a[tetris->x][tetris->y-1]==0&&a[tetris->x+2][tetris->y-1]==0))||
(tetris->flag==17&&(a[tetris->x-2][tetris->y]==0&&
a[tetris->x+2][tetris->y+1]==0&&a[tetris->x+2][tetris->y]==0))||
(tetris->flag==18&&(a[tetris->x][tetris->y-1]==0&&
a[tetris->x][tetris->y+1]==0&&a[tetris->x-2][tetris->y+1]==0))||
(tetris->flag==19&&(a[tetris->x-2][tetris->y]==0&&
a[tetris->x-2][tetris->y-1]==0&&a[tetris->x+2][tetris->y]==0)))
{
return 1;
}
}
return 0;
}
/*******清除俄罗斯方块的痕迹********/
void CleanTetris(struct Tetris *tetris){
for(i=0;i<4;i++){
b[i]=0;
}
MakeTetris(tetris);
for(i=tetris->x-2;i<=tetris->x+4;i+=2){
for(tetris->y-2;i<=tetris->y+1;j++){
if(a[i][j]==0&&j>FrameY){
gotoxy(i,j);
printf(" ");
}
}
}
}
/*******判断是否满行********/
void Del_Fullline(struct Tetris *tetris){
int k,del_rows=0;
for(j=FrameY+Frame_height-1;j>=FrameY+1;j--){
k=0;
for(i=FrameX+2;i<FrameX+2*Frame_width-2;i+=2){
if(a[i][j]==1){
k++;
if(k==Frame_width-2){
for(k=FrameX+2;k<FrameX+2*Frame_width-2;k+=2){
a[k][j]=0;
gotoxy(k,j);
printf("");
}
for(k=j-1;k>FrameY;k--){
for(i=FrameX+2;i<FrameX+2*Frame_width-2;i+=2){
if(a[i][k]==1){
a[i][k]=0;
gotoxy(i,k);
printf(" ");
a[i][k+1]=1;
gotoxy(i,k+1);
printf("");
}
}
}
j++;
del_rows++;
}
}
}
}
tetris->score+=100*del_rows;
if(del_rows>0&&(tetris->score%1000==0||tetris->score/1000>tetris->level-1)){
tetris->speed-+20;
tetris->level++;
}
}
/******随机产生俄罗斯方块类型的序号*******/
void Flag(struct Tetris *tetris){
tetris->number++;
srand(time(NULL));
if(tetris->number==1){
tetris->flag=rand()%19+1;
}
tetris->next=rand()%19+1;
}
/*******开始游戏*******/
void Gameplay(){
int n;
struct Tetris t,*tetris=&t;
char ch;
tetris->number=0;
tetris->speed=300;
tetris->score=0;
tetris->level=1;
while(1){
Flag(tetris);
Temp=tetris->flag;
tetris->x=FrameX+2*Frame_width+6;
tetris->y=FrameY+10;
tetris->flag=tetris->next;
PrintTetris(tetris);
tetris->x=FrameX+Frame_width;
tetris->y=FrameY-1;
tetris->flag=Temp;
/******获取键盘按键*******/
while(1){
label:PrintTetris(tetris);
Sleep(tetris->speed);//控制时间
CleanTetris(tetris);
Temp1=tetris->x;
Temp2+tetris->flag;
if(kbhit()){
ch=getch();
if(ch==75){
tetris->x-=2; //←键左移
}
if(ch==77) tetris->x+=2;//→键右移
if(ch==80){ //↓键加速下落
if(ifMove(tetris)!=0) tetris->y+=2;
else tetris->y=FrameY+Frame_height-2;
}
if(ch==72){
if(tetris->flag>=2&&tetris->flag<=3){
tetris->flag++;
tetris->flag%=2;
tetris->flag+=2;
}//直线方块
if(tetris->flag>=4&&tetris->flag<=7){
tetris->flag++;
tetris->flag%=4;
tetris->flag+=4;
}//T字方块
if(tetris->flag>=8&&tetris->flag<=11){
tetris->flag++;
tetris->flag%=4;
tetris->flag+=8;
}//Z字方块
if(tetris->flag>=12&&tetris->flag<=15){
tetris->flag++;
tetris->flag%=4;
tetris->flag+=12;
}// 7字方块
if(tetris->flag>=16&&tetris->flag<=19){
tetris->flag++;
tetris->flag%=4;
tetris->flag+=16;
}//反7字方块
}
if(ch==32) //空格暂停
{
PrintTetris(tetris);
while(1){
if(kbhit()){
ch=getch();
if(ch==32) goto label;
}
}
}
if(ch==27){ //ESC退出游戏
system("cls");
memset(a,0,6400*sizeof(int));//初始化数组
welcome();
}
if(ifMove(tetris)==0){
tetris->x=Temp1;
tetris->flag=Temp2;
}
else{
goto label;
}
}
tetris->y++;
if(ifMove(tetris)==0){
tetris->y--;
PrintTetris(tetris);
Del_Fullline(tetris);
break;
}
}
//游戏结束
for(i=tetris->y-2;i<tetris->y+2;i++){
if(i==FrameY){
system("cls");
gotoxy(29,7);
printf(" \n");
color(12);
printf("\t\t\t████ █ █ ██ \n");
printf("\t\t\t█ ██ █ █ █ \n");
printf("\t\t\t███ █ █ █ █ █ \n");
printf("\t\t\t█ █ ██ █ █ \n");
printf("\t\t\t████ █ █ ██ \n");
gotoxy(17,18);
color(14);
printf("我要重新玩一局---------1");
gotoxy(44,18);
printf("不玩了,退出-----------2\n");
int n;
gotoxy(32,20);
printf("选择【1/2】");
color(11);
scanf("%d",&n);
switch(n){
case 1:
system("cls");
Replay(tetris);
break;
case 2:
exit(0);
break;
}
}
}
tetris->flag=tetris->next;
tetris->x=FrameX+2*Frame_width+6;
tetris->y=FrameY+10;
CleanTetris(tetris);
}
}
/*******主函数*******/
int main(){
title();
welcome();
return 0;
}