#include<stdio.h>
#include<conio.h>
#include<malloc.h>
#include<graphics.h>
#define kuan 12
#define gao 20
typedef struct h //构建节点,a1,a2代表在矩阵中的坐标(a1,a2),x,y代表位移
{
int a1,a2,x,y;
struct h *next;
}h;
typedef struct space //定义空间
{
int a[kuan][gao];
}space;
space *creatspace() //创建初始化空间,a[30][15]=0
{
int x,y;
space *p;
p=(space *)malloc(sizeof(space));
for(x=0;x<kuan;x++)
for(y=0;y<gao;y++)
p->a[x][y]=0;
return p;
}
void out(space *p) //空间输出
{
int x,y;
for(x=0;x<kuan;x++)
for(y=0;y<gao;y++)
if(p->a[x][y]==1)
{
setcolor(YELLOW);
bar(x*10,y*10,x*10+10,y*10+10);
}
}
void outxiao(space *p) //空间输出
{
int x,y;
for(x=0;x<kuan;x++)
for(y=0;y<gao;y++)
if(p->a[x][y]==1)
{
setcolor(BLACK);
bar(x*10,y*10,x*10+10,y*10+10);
}
}
h *creat(int n)
{
h *head,*p1,*p2,*p3,*p4;
head=(h*)malloc(sizeof(h));
p2=(h*)malloc(sizeof(h));
p3=(h*)malloc(sizeof(h));
p4=(h*)malloc(sizeof(h));
p1=head;
p1->next=p2;
p2->next=p3;
p3->next=p4;
p4->next=NULL;
p1->x=p2->x=p3->x=p4->x=p1->y=p2->y=p3->y=p4->y=2;
if(n==0)
{
p1->a1=1;
p1->a2=1;
p2->a1=1;
p2->a2=2;
p3->a1=2;
p3->a2=1;
p4->a1=2;
p4->a2=2;
}
if(n==1)
{
p1->a1=0;
p1->a2=1;
p2->a1=1;
p2->a2=1;
p3->a1=2;
p3->a2=1;
p4->a1=3;
p4->a2=1;
}
if(n==2) //判定显示什么样的方块--|
{
p1->a1=0;
p1->a2=0;
p2->a1=0;
p2->a2=1;
p3->a1=0;
p3->a2=2;
p4->a1=1;
p4->a2=2;
}
if(n==3)
{
p1->a1=0;
p1->a2=1;
p2->a1=1;
p2->a2=1;
p3->a1=1;
p3->a2=2;
p4->a1=2;
p4->a2=1;
}
if(n==4)
{
p1->a1=0;
p1->a2=1;
p2->a1=1;
p2->a2=1;
p3->a1=1;
p3->a2=2;
p4->a1=2;
p4->a2=2;
}
return head;
}
void xian(h *head) //显示
{
h *p;
p=head;
while(p!=0)
{
setfillcolor(GREEN);
bar((p->a1+p->x)*10,(p->a2+p->y)*10,(p->a1+p->x)*10+10,(p->a2+p->y)*10+10);
p=p->next;
}
}
void xiao(h *head) //消失
{
h *p;
p=head;
while(p!=0)
{
setfillcolor(BLACK);
bar((p->a1+p->x)*1,(p->a2+p->y)*10,(p->a1+p->x)*10+10,(p->a2+p->y)*10+10);
p=p->next;
}
}
void xuan(int n,space *p,h *head)
/*
旋转
n是显示方块的形状 0为长条,1为正方形,2。。。。
space *p指向一个二维数组a[][]作为存储空间,储存已落地的方块,
h *head存储方块在矩阵中的位置,如何在矩阵中(a1,a2),控制位移x,y;
h *head 利用链表存储,遍历旋转
通过计算x+a1的坐标判定是否超越左边界,通过判定y+a2-1的坐标来判定是否超越右边界
通过判定旋转之后的坐标是否与当前存储空间的位置上冲突(判定当前空间p->a[x+a1][y+a2]是否为1)
是则反向旋转,令h *head 重新遍历,反向旋转,回到原位置。
*/
{
h*q; //定义一个指针,代替head指针遍历旋转
q=head;
int e=0; //判定指针,当需要回到原坐标时的判定
int a; //a用于数值对换 a=b,b=c,c=a
int max; //max 用于判定
if(n<=1)max=3; //显示长条或正方形时矩阵旋转需要a[4][4]
else max=2; //其他则为a[3][3]
while(q!=0) //开始旋转
{ a=q->a1;
q->a1=max-q->a2;
q->a2=a;
if(p->a[q->a1+q->x][q->a2+q->y]==1||(q->a1+q->x<0)||(q->a2+q->y>kuan))e++;
/*旋转判定,是否越界或者与存储空间重合,是则判定+1
边界宽度宏定义为kuan*/
q=q->next;
}
if(e!=0) //若显示上面的任意一项,则开始反向旋转
{ q=head; //重置
while(q!=0)
{
a=q->a1;
q->a1=q->a2;
q->a2=max-a;
q=q->next;
}
}
}
//方向开始
void left(space *p,h *head)
{
h *q;
int e=1;
q=head;
while(q!=NULL)
{
if((q->a1+q->x)<=0||p->a[q->a1+q->x-1][q->a2+q->y]==1) //判定是否碰到边界或本身就存在的方块
{ e=0;break; }
else q=q->next;
}
q=head;
while(e==1&&q!=NULL)
{
q->x=q->x-1;
q=q->next;
}
}
void right(space *p,h *head)
{
h *q;
int e=1; //e为判定条件
q=head;
while(q!=NULL)
{
if((q->a1+q->x)>=kuan-1||p->a[q->a1+q->x+1][q->a2+q->y]==1) //判定是否碰到边界或本身就存在的方块
{ e=0;break; }
else q=q->next;
}
q=head;
while(e==1&&q!=NULL)
{
q->x=q->x+1;
q=q->next;
}
}
void down(h *head)
{
h *p;
int e=0;
p=head;
while(p!=NULL)
{
p->y=p->y+1;
if(p->a2+p->y==gao)e++;
p=p->next;
}
if(e!=0)
{
while(p!=NULL)
{
p->y=p->y-1;
p=p->next;
}
}
}
//方向结束
int judge(space *p,h *head) //判定方块是否到底,交接存储,将方块的横纵坐标存入存储空间space中
{
int e=0,n=0;
h *q;
q=head;
while(q!=NULL)
{
if(p->a[q->a1+q->x][q->a2+(q->y)+1]==1||(q->a2+q->y)==gao-1) //直接y的下一个已经有值或者到底了
{
e=1;
if(q->a2+q->y==gao)n=1; //到底的话另外在判断
}
q=q->next;
}
if(e==1&&n==0) //碰边
{
q=head;
while(q!=NULL)
{
p->a[q->a1+q->x][q->a2+q->y]=1;
q=q->next;
}
}
if(e==1&&n==1) //到底
{
q=head;
while(q!=NULL)
{
p->a[q->a1+q->x][q->a2+q->y-1]=1;
q=q->next;
}
}
return e;
}
void man(space *p) //满层判定 函数p包含的是一个二维数组p[x][y],x表示宽度,y表示高度,当a[x][y]为1时,显示
{
int x,y,z,k; //z为计数器,k用于存储当前y值
z=0;
for(y=gao-1;y>=0;y--,z=0) //从底层开始判定,每次计数器清零,循环一次之后
{
for(x=0;x<kuan;x++) //每层判定,当前行为z=15时满值
{
if(p->a[x][y]==1)
{
z=z+1;
}
else break; //不为满值则直接跳出进行下一循环
}
if(z==kuan) //开始清除
{
for(k=y;k>0;k--)
{
for(x=0;x<kuan;x++)
p->a[x][k]=p->a[x][k-1];
}
y=y+1; //过后重新运行当前行,因为当前行已经改变
}
}
}
void main()
{
int e=0;
int n;
int time=0;
n=rand()%5;
n=rand()%5;
space *p;
p=creatspace();
h *head; //初始化开始
initgraph(kuan*10,gao*10); //建立图像
head=creat(n); // 创建新的方块
while(1)
{ xian(head);
out(p); //显示当前存储空间
Sleep(100);
xiao(head);
time++;
if(time==8)
{
down(head);
time=0;
}
if(!kbhit())
{
}
else
{
switch(getch()) //可以在这里直接增加判定,当向左或右或旋转时如果碰边则无效或返回前一个值
{ case 'w':xuan(n,p,head); break; //可以加个计时器,让旋转等操作与向下平行
case 'a':left(p,head);break;
case 'd':right(p,head);break;
case 's':down(head);break;
default :break;
}
}
e=judge(p,head);
if(e==1)
{
n=rand()%5;
head=creat(n);
e=0;
}
outxiao(p); //消除上一次的存储空间
man(p); //满层判定
} //while结束
closegraph();
}