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.

799 lines
22 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 // 游戏窗口左上角X坐标
#define FrameY 3 //游戏窗口左上角Y坐标
#define Frame_gao 20 //游戏窗口高度
#define Frame_kuan 18 //游戏窗口宽度
int i, j, temp, temp1, temp2; //定义全局变量, temp表示存储方块变量的值
int a[80][80] = {0}; //0表示无方块1表示有方块 2为边界
int b[4]; //四个方块值为01
struct fangkuai
{
int x, y; //横纵坐标值
int flag; //方块类型序号
int next; //下一个方块序号
int speed; // 方块速度
int number; //方块个数
int score; //分数
int level; //游戏等级
};
HANDLE hOut; //控制台控制
/********函数声明**********/
void gotoxy(int x, int y); //光标移动到指定位置
int color(int c); //控制台文字颜色
void DrawGameframe(); //绘制游戏边界
void Flag(struct fangkuai *); //产生随机数
void Makefangkuai(struct fangkuai *); //制作方块
void printfangkuai(struct fangkuai *); //打印~
void cleanfangkuai(struct fangkuai *); //清除~
int ifMove(struct fangkuai *); //判断是否可移动
void Del_fullline(struct fangkuai *); //判断是否满行,并删除满行方块
void Gamebegin(); //游戏开始
void welcome(); //欢迎菜单
void explation(); //规则说明
void Replay(struct fangkuai *); //重新游戏
void title(); //界面上方标题
void close(); //关闭游戏
/*****控制文字颜色*******/
int color(int c){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c); //只在windows上改变文字颜色
return 0;
} //0~15共16种颜色
/*用法:
coler数字
printf
*/
/*******文字显示位置********/
void gotoxy(int x, int y)
{
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
/*
用法:
gotoxy3010 横向空30个单位纵向空10个单位
printf
*/
/*****设置开始界面标题*****/
void title()
{
color(15);
gotoxy(30,3);
printf(" 俄 罗 斯 方 块");
color(11);
gotoxy(17,5);
printf("");
gotoxy(17,6);
printf("■■");
gotoxy(17,7);
printf("");
color(10);
gotoxy(25,5);
printf("■■");
gotoxy(25,6);
printf("■■");
color(13);
gotoxy(33,6);
printf("■■■■");
color(4);
gotoxy(45,5);
printf("■■");
gotoxy(45,6);
printf("");
gotoxy(45,7);
printf("");
color(12);
gotoxy(53,5);
printf("■■");
gotoxy(53,6);
printf(" ■■");
}
/*****设置菜单选项*****/
void welcome(){
int i = 1, j = 1;
int n;
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(33,17);
printf("3.退出游戏\n");
gotoxy(31,19);
printf("本游戏纯属内测");
gotoxy(28,22);
color(3);
printf("请选择[1 2 3]:{ }\b\b");
color(14);
scanf("%d", &n);
switch(n)
{
case 1:
{
system("cls"); //清屏
DrawGameframe();
Gamebegin();
break;
}
case 2:
explation();
break;
case 3:
close();
break;
}
}
/*****游戏窗口界面*****/
void DrawGameframe()
{
gotoxy((FrameX+Frame_kuan-7), FrameY-2);
color(11);
printf("俄罗斯方块");
color(12);
gotoxy(FrameX,FrameY);
printf("");
gotoxy(FrameX + 2*Frame_kuan-2,FrameY);
printf("");
gotoxy(FrameX,FrameY + Frame_gao);
printf("");
gotoxy(FrameX+ 2*Frame_kuan-2,FrameY + Frame_gao);
printf("");
a[FrameX+ 2*Frame_kuan-2][FrameY + Frame_gao] = 2;
/****上横框*****/
for(i = 2; i < 2 * Frame_kuan-2; i += 2){
gotoxy(FrameX + i, FrameY);
printf("");
}
/*****下横框*****/
for(i = 2; i < 2 * Frame_kuan-2; i += 2){
gotoxy(FrameX + i, FrameY + Frame_gao);
printf("");
a[FrameX + i][FrameY + Frame_gao] = 2;
}
/****竖框****/
for(i = 1; i < Frame_gao; i++){ //左
gotoxy(FrameX, FrameY+i);
printf("");
a[FrameX][FrameY + i] = 2;
}
for(i = 1; i < Frame_gao; i++){
gotoxy(FrameX + 2 * Frame_kuan-2, FrameY+i);
printf("");
a[FrameX + 2 * Frame_kuan-2][FrameY+i] = 2;
}
/****提示****/
color(2);
gotoxy(FrameX + 2* Frame_kuan + 3,FrameY + 7);
printf("**********");
gotoxy(FrameX + 2* Frame_kuan + 3,FrameY + 13);
printf("**********");
color(3);
gotoxy(FrameX + 2* Frame_kuan + 3,FrameY + 6);
printf("下一个方块:");
color(14);
gotoxy(FrameX + 2* Frame_kuan + 3,FrameY + 17);
printf("空格:暂停游戏");
gotoxy(FrameX + 2* Frame_kuan + 3,FrameY + 19);
printf("ESC退出游戏");
}
/****制作方块*****/
void Makefangkuai(struct fangkuai *tetris)
{
a[tetris->x][tetris->y] = b[0];
switch(tetris->flag)
{
case 1: //田字方块
{
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: //直线方块:----
{
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: //直线方块: |
{
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字方块
{
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: //T字顺时针转90度方块
{
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 6: //T字顺时针转180度方块
{
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: //T字顺时针转270度方块
{
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字方块
{
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 9: //Z字顺时针转90度方块
{
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字顺时针转180度方块
{
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字顺时针转270度方块
{
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字方块
{
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: //7字顺时针转90度方块
{
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: //7字顺时针转180度方块
{
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: //7字顺时针转270度方块
{
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 16: //倒7字方块
{
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: //倒7字顺指针转90度方块
{
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: //倒7字顺时针转180度方块
{
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: //倒7字顺时针转270度方块
{
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 Printfangkuai(struct fangkuai *tetris)
{
for(i = 0; i < 4; i++)
{
b[i] = 1;
}
Makefangkuai(tetris);
for(i = tetris->x-2; i <= tetris->x+4; i += 2){
for(j = tetris->y-2; j <= tetris->y+1; j++){
if(a[i][j] == 1 && j > FrameY){
gotoxy(i, j);
printf("");
}
}
}
/*****打印信息******/
gotoxy(FrameX + 2 * Frame_kuan+3,FrameY + 1);
color(4);
printf("等级: ");
color(12);
printf("%d", tetris->level);
gotoxy(FrameX + 2 * Frame_kuan+3,FrameY + 3);
color(4);
printf("分数: ");
color(12);
printf("%d", tetris->score);
gotoxy(FrameX + 2 * Frame_kuan+3,FrameY + 5);
color(4);
printf("速度: ");
color(12);
printf("%dms", tetris->speed);
}
/*****判断是否可移动*****/
int ifMove(struct fangkuai *tetris)
{
if(a[tetris->x][tetris->y] != 0){ //中心方块处不为空
return 0;
}
else
{
if(//当为田字方块且除中心方块位置外,其他"口"字方块位置上无图案时返回值为1即可移动
( tetris->flag==1 && ( a[tetris->x][tetris->y-1]==0 &&
a[tetris->x+2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
//或为直线方块且除中心方块位置外,其他"口"字方块位置上无图案时返回值为1即可移动
( 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 Cleanfangkuai(struct fangkuai *tetris)
{
for(i = 0; i < 4; i++){
b[i] = 0;
}
Makefangkuai(tetris);
for(i = tetris->x-2; i <= tetris->x+4; i += 2){
for(j = tetris->y-2; j <= tetris->y + 1; j++){
if(a[i][j] == 0 && j > FrameY){
gotoxy(i, j);
printf(" "); //将上一个方块的轨迹以空格代替
}
}
}
}
/******判断满行并删除******/
void Del_fullline(struct fangkuai *tetris)
{
int k, del_rows = 0;
for(j = FrameY+Frame_gao-1; j >= FrameY+1; j--){
k=0;
for(i = FrameX+2; i < FrameX + 2* Frame_kuan - 2; i += 2){ //从左下角开始向右上方遍历
if(a[i][j] == 1){
k++;
if(k == Frame_kuan - 2) //k代表i——横坐标
{
for(k = FrameX + 2; k < FrameX + 2 * Frame_kuan - 2; k += 2)
{
a[k][j] = 0;
gotoxy(k, j);
printf(" "); //删除整行
}
for(k = j-1; k > FrameY; k--) //k代表j——纵坐标
{
for(i = FrameX + 2; i < FrameX + 2 * Frame_kuan-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 fangkuai *tetris)
{
tetris->number++;
srand(time(NULL)); //初始化随机数
if(tetris->number == 1)
{
tetris->flag == rand()%19+1; //rand产生随机数除取余结果为0~18
}
tetris->next = rand()%19+1;
}
/*******开始游戏********/
void Gamebegin()
{
int n;
struct fangkuai t, *tetris = &t; //定义变量
char ch;
tetris->number = 0; //初始方块数为0
tetris->speed = 300; //初始化速度
tetris->score = 0; //初始得分
tetris->level = 1; //初始等级
while(1)
{
Flag(tetris);
temp = tetris->flag; //temp将下一个方块输入到游戏中
tetris->x = FrameX + 2 * Frame_kuan + 6;
tetris->y = FrameY +10;
tetris->flag = tetris->next;
Printfangkuai(tetris);
tetris->x = FrameX + Frame_kuan;
tetris->y = FrameY -1;
tetris->flag = temp;
//按键操作
while(1) //控制方块变化,直至不再下落
{
label:Printfangkuai(tetris); //打印方块
Sleep(tetris->speed); //延缓时间
Cleanfangkuai(tetris); //清除痕迹
temp1 = tetris->x; //标定中心方块横坐标的值
temp2 = tetris->flag; //记住当前俄罗斯方块的序号
if(kbhit()) //判断是否有键盘输入kbhit
{
ch = getch(); //用ch接收
if((ch == 75) || (ch == 'a' || ch == 'A'))
{
tetris->x-=2; //方向键左或A则向左移动中心横坐标减2
}
if((ch == 77) || (ch == 'd' || ch == 'D'))
{
tetris->x+=2; //方向键右或D则向右移动中心横坐标加2
}
if((ch == 0x28) || (ch == 's' || ch == 'S')) //下键或S则向下加速
{
if(ifMove(tetris) != 0)
{
tetris->y+=2;
}
if(ifMove(tetris) == 0)
{
tetris->y = FrameY + Frame_gao - 2;
}
}
if((ch == 72) || (ch == 'w' || ch == 'W')) //按上键和W改变方块形状
{
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;
}
if( tetris->flag>=8 && tetris->flag<=11 )
{
tetris->flag++;
tetris->flag%=4;
tetris->flag+=8;
}
if( tetris->flag>=12 && tetris->flag<=15 )
{
tetris->flag++;
tetris->flag%=4;
tetris->flag+=12;
}
if( tetris->flag>=16 && tetris->flag<=19 )
{
tetris->flag++;
tetris->flag%=4;
tetris->flag+=16;
}
}
if(ch == 32){ //空格,暂停
Printfangkuai(tetris);
while(1)
{
if(kbhit())
{
ch == getch(); //再按,继续游戏
if(ch == 32)
{
goto label;
}
}
}
}
if(ch == 27) //按ESC退出至菜单界面
{
system("cls");
memset(a,0,6400*sizeof(int)); //初始化BOX数据
welcome();
}
if(ifMove(tetris) == 0) //如果不可动,上述操作无效
{
tetris->x = temp1;
tetris->flag = temp2;
}
else
{
goto label;
}
}
tetris->y++; //若无操作指令,则方块自由下落
if(ifMove(tetris) == 0) //若方块不可移动,则方块放置于此
{
tetris->y--;
Printfangkuai(tetris);
Del_fullline(tetris);
break;
}
}
for(i = tetris->y; i < tetris->y+1; 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_kuan +6;
tetris->y = FrameY + 10;
Cleanfangkuai(tetris);
}
}
/******重新开始******/
void Replay(struct fangkuai *tetris)
{
system("cls");
memset(a,0,6400*sizeof(int)); //memset——初始化数组数组名数据数组个数*长度)
DrawGameframe();
Gamebegin();
}
/*******规则说明*******/
void explation()
{
int i, j = 1;
system("cls");
color(13);
gotoxy(32,3);
printf("按键说明");
color(2);
for(i == 6; i <= 16; i++) //y轴坐标值
{
for(j = 15; j <= 60; j++)
{
gotoxy(j,i);
if(i == 6 || i == 16)
{
printf("=");
}
else if(j == 15 || j == 59)
{
printf("||");
}
}
}
color(3);
gotoxy(18,7);
printf("tip1玩家可以通过A、D或左右方向键控制方向");
color(10);
gotoxy(18,9);
printf("tip2通过W或上方向键使方块逆时针旋转");
color(14);
gotoxy(18,11);
printf("tip3通过S或下方向键加速方块下落");
color(11);
gotoxy(18,13);
printf("tip4按空格暂停游戏再按空格继续");
color(4);
gotoxy(18,15);
printf("tip5按ESC退出游戏");
getch(); //按任意键返回主菜单
system("cls");
main();
}
/****退出游戏****/
void close()
{
exit(0);
}
int main(){
title();
welcome();
}