大一作品,留念
#include<stdio.h>
#include<time.h>
#include<conio.h>//kbhit
#include<stdlib.h>//rand,srand
#include<windows.h>
#define wide 15
#define hight 18
#define period 500
typedef struct point
{
int h;
int w;
}point;
/*
1 ■■■■ 1*4 -> 4*1
■ ■
2■■■ 3 ■■■ 2*3 -> 3*2
■■ ■■ 2*3 -> 3*2
4 ■■ 5 ■■
■■ ■
6 ■■ 2*2 7 ■■■ 2*3->3*2
最大面积为4*4
1234 ■■■■
1234 ■■■■
1234 ■■■■
1234 ■■■■
按W键旋转九十度
*/
char map[hight][wide]={0};//1:□ 2:■ 其余的都是空格 char类型节约空间
char stay[hight][wide]={0};//残留方块
struct point size;//活动方块的大小 前一个代表 高度 后一个代表 宽度 ,主要用于触碰处理
char sqr[4][4];//活动方块数组
struct point posi={1,wide/2-2};//方块顶点坐标
char situ=0;//旋转状况0 正常 1 顺时针90度 2:180 3:270
int grade=0,line=0;
//char sqr[4][4];
//point newspr={1,wide/2};
//------------函数声明
void showmap();
void setmap();
int keypre(char k);//按下某键
int getrand(int,int);//取一个范围内的随机数
int setini(int type);//初始化方块,类型,看表吧
void turn90();
int isagain();//判断活动区是否与stay区重复
int exsqr(char row);//判断stay区某一行是否存在方块,存在返回1,不存在返回0
void judge();//层满处理
int main()
{
int last=0,t;
int i;
srand(time(NULL));
//随机图形
setini(getrand(1,7));
//屏幕渲染
do
{
t=clock();
if(t-last>=period)
{
//周期性刷新
last=t;
system("cls");
if(keypre('s')==0)
break;
setmap();
printf("-----------当前分数:%d,已消除行:%d-----------\n",grade,line);
showmap();
}
if(kbhit()==1)
{
system("cls");
if(keypre(getch())==0)
break;
setmap();
printf("-----------当前分数:%d,已消除行:%d-----------\n",grade,line);
showmap();
}
}while(1);
system("cls");
printf("----------------得分:%d 消除:%d-------------------\n",grade,line);
setmap();
showmap();
printf("----------------游戏结束!谢谢玩耍!----------------\n");
printf("按回车键退出!\n");
while(getchar()!='\n');
return 0;
}
int keypre(char k)//按下某键
{
int i,j,real=0;
char top[wide];
if(k=='s')
{
posi.h++;
if(isagain())//下一步是否会重合
real=1;//那么下一步不能走了
//留在当前位置
if(real)
{
grade+=18;//留步加分
posi.h--;//留在上一步
for(i=0;i<size.h ;i++)//就留下来了
{
for(j=0;j<size.w;j++)
{
if(sqr[i][j]==2)//只记录实体
stay[i+posi.h][j+posi.w ]=2;
}
}
//出新的
judge();//层满判断
return (setini(getrand(1,7)));
}
}
else if(k=='a'||k=='A')
{
posi.w --;
if(isagain())
posi.w ++;//移动取消
}
else if(k=='d'||k=='D')
{
posi.w ++;
if(isagain())
posi.w --;//移动取消
}
else if(k=='w'||k=='W')
turn90();
else if(k=='s'||k=='S')
{
posi.h++;
if(isagain())
posi.h --;//移动取消
}
//左右分界判断
if(posi.w+size.w>wide-1)
posi.w=wide-1-size.w;
if(posi.w <1)
posi.w=1;
return 1;
}
void setmap()//初始化地图,并置
{
int i,j;
//画地图区域
for(i=0;i<hight;i++)
{
for(j=0;j<wide;j++)
{
if(i==0||i==hight-1||j==0||j==wide-1)
map[i][j]=1;//边界
else
map[i][j]=0;//空白
}
}
//画活动方块
for(i=0;i<size.h ;i++)
{
for(j=0;j<size.w ;j++)
{
map[posi.h+i][posi.w+j]=sqr[i][j];
}
}
//画残留
for(i=0;i<hight;i++)
{
for(j=0;j<wide;j++)
{
if(stay[i][j]==2)
map[i][j]=2;
}
}
}
//将数组转换为图形
void showmap()
{
int i,j;
for(i=0;i<hight;i++)
{
for(j=0;j<wide;j++)
{
if(map[i][j]==1)
printf("□");
else if(map[i][j]==2)
printf("■");
else
printf(" ");
}
printf("\n");
}
}
int getrand(int min,int max)//取一个范围内的随机数
{
return (min+rand()%(max-min+1));
}
void turn90()//活动方块顺时针旋转九十度
{
int i,j;
char a[4][4];//临时变量
char temp[4][4];
//方块备份
for(i=0;i<4;i++)
for(j=0;j<4;j++)
temp[i][j]=sqr[i][j];
for(i=0;i<4;i++)
for(j=0;j<4;j++)
a[j][i]=sqr[i][j];//斜线对称
//左右对称,即是转动九十度
i=size.h ;
size.h =size.w;
size.w =i;
for(i=0;i<size.h ;i++)
for(j=0;j<size.w ;j++)
sqr[i][size.w-1-j]=a[i][j];
if(isagain())
for(i=0;i<4;i++)
for(j=0;j<4;j++)
sqr[i][j]=temp[i][j];
}
int setini(int type)//初始化方块,类型,看表吧
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
sqr[i][j]=0;//归零
switch(type)
{
case 1:
size.h =1;
size.w =4;
sqr[0][0]=2;
sqr[0][1]=2;
sqr[0][2]=2;
sqr[0][3]=2;
break;
case 2:
size.h =2;
size.w =3;
sqr[0][0]=2;
sqr[1][0]=2;
sqr[1][1]=2;
sqr[1][2]=2;
break;
case 3:
size.h =2;
size.w =3;
sqr[0][2]=2;
sqr[1][0]=2;
sqr[1][1]=2;
sqr[1][2]=2;
break;
case 4:
size.h =2;
size.w =3;
sqr[0][1]=2;
sqr[0][2]=2;
sqr[1][0]=2;
sqr[1][1]=2;
break;
case 5:
size.h =2;
size.w =3;
sqr[0][0]=2;
sqr[0][1]=2;
sqr[1][1]=2;
sqr[1][2]=2;
break;
case 6:
size.h =2;
size.w =2;
sqr[0][0]=2;
sqr[0][1]=2;
sqr[1][0]=2;
sqr[1][1]=2;
break;
case 7:
size.h =2;
size.w =3;
sqr[0][1]=2;
sqr[1][0]=2;
sqr[1][1]=2;
sqr[1][2]=2;
break;
}
posi.h =1;
posi.w =(wide-size.w )/2;
if(isagain())//刚刚初始化你就重合了,你说你是不是挂了?
return 0;
return 1;
/* 1 ■■■■ 1*4 -> 4*1
■ ■
2■■■ 3 ■■■ 2*3 -> 3*2
■■ ■■ 2*3 -> 3*2
4 ■■ 5 ■■
■■ ■
6 ■■ 2*2 7 ■■■ 2*3->3*2
*/
}
void judge()//层满处理
{
int i,j,full,k,esqr;
for(i=1;i<hight-1;i++)//除掉边界
{
full=1;
for(j=1;j<wide-1;j++)//除掉边界
{
if(stay[i][j]!=2)//存在不为方块的
full=0;//假空
}
if(full)//真空
{
line++;//已消除
grade+=90;//消除加五倍分数
for(j=1;j<wide-1;j++)//除掉边界
stay[i][j]=0;//置零
}
}
//全部除完之后
for(i=hight-2;i>=2;i--)
{
int s=i;
if(exsqr(i)==0)//本层为空
{
//上层下移
while(s>=1 && exsqr(--s)==0)
//该层不存在方块
//继续向上寻找
;
for(j=1;j<wide-1;j++)
{
stay[i][j]=stay[s][j];//上层下移
stay[s][j]=0;//上层清空
}
}
}
}
int isagain()//判断活动区是否与stay区重复
{
int i,j;
for(i=0;i<size.h ;i++)
{
for(j=0;j<size.w ;j++)
{
if(sqr[i][j]==2)//是实体,i,j是框内代号
{
if(posi.h +i >hight-2)
return 1;
else if(stay[posi.h +i][posi.w +j]==2)//框内位置转换为map位置
return 1;
}
}
}
return 0;//未重复
}
int exsqr(char row)//判断stay区某一行是否存在方块,存在返回1,不存在返回0
{
int j;
for(j=1;j<wide-1;j++)//出掉边界
if(stay[row][j]==2)
return 1;
return 0;
}