鱼C论坛

 找回密码
 立即注册
查看: 2475|回复: 18

卡在俄罗斯方块旋转上了,错在哪里了求指点,谢谢

[复制链接]
发表于 2014-11-15 12:09:11 | 显示全部楼层 |阅读模式
50鱼币
本帖最后由 漠水 于 2014-11-15 14:02 编辑
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-1))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;
}

}
}

最佳答案

查看完整内容

a[10][10]至于你说的旋转,我是这样认为的 比如 图中的 “土”字, 首先他们是1,我们就在数组里面循环把它的坐标换一下,如果换完后的坐标 a[10] 如果 i
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-11-15 12:09:12 | 显示全部楼层
a[10][10]至于你说的旋转,我是这样认为的 比如  图中的 “土”字, 首先他们是1,我们就在数组里面循环把它的坐标换一下,如果换完后的坐标 a[i][10]  如果 i<0 那么 就把4个方块的i坐标 +1  如果还有i<1 那么继续+1  如果 i>9那么久-1.不知道能听懂吗?   
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-11-15 13:58:45 | 显示全部楼层
全部代码如下,运行有bug ,旋转会直接卡到边界里面去了,而且有时旋转会失灵,求解释
#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();

}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2014-12-2 20:05:40 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-12-23 13:38:14 | 显示全部楼层
楼主 我看了你的问题我就写了个俄罗斯方块
Z]6F{NXSIL6~C`V1~[{G592.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-12-23 13:45:39 | 显示全部楼层
首先说下我的思路, 定义一个数组 初始化为0; 方块为1;落下后为2;
Z]6F{NXSIL6~C`V1~[{G592.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-12-23 16:18:28 | 显示全部楼层
735899422 发表于 2014-12-23 13:45
首先说下我的思路, 定义一个数组 初始化为0; 方块为1;落下后为2;

旋转的问题我已经解决了,还是有点其他的小毛病,这帖子感觉过去好久了,不过还是要谢谢你的解答。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-12-24 09:00:43 | 显示全部楼层
什么小毛病、
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-12-24 11:27:39 | 显示全部楼层
本帖最后由 漠水 于 2014-12-24 11:29 编辑

还是有点不懂,能不能把代码发一下,看看,谢谢哈
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-12-24 11:29:57 | 显示全部楼层

还是有点不懂,能不能把代码发一下,看看,谢谢哈
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-12-24 11:31:49 | 显示全部楼层
哪里不懂?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-12-24 11:32:53 | 显示全部楼层
我的代码只写了一半就不想写了 麻烦 你哪里不懂?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-12-24 11:36:59 | 显示全部楼层
漠水 发表于 2014-12-24 11:29
还是有点不懂,能不能把代码发一下,看看,谢谢哈

旋转越界不懂吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-12-24 11:39:38 | 显示全部楼层
735899422 发表于 2014-12-24 11:32
我的代码只写了一半就不想写了 麻烦 你哪里不懂?

就是一个反应的机制问题,是下降的时间的控制与按键操作的配合,主要就是一个时间差问题,比如我这个程序如果一直向右的话也会右下角而非右边。不过我已经不纠结这个了,还是非常感谢。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-12-24 11:41:49 | 显示全部楼层
本帖最后由 漠水 于 2014-12-24 11:44 编辑
735899422 发表于 2014-12-24 11:36
旋转越界不懂吗?


恩,我主要是看不出来程序中的旋转越界的操作错在了哪一个步骤上,哪一行,应该说我不怎么会试调,比较不是纯业余的。
具体点说就是:不知道在旋转的时候,判定条件按道理来说应该可以啊,怎么会越界出去呢?还是说存储空间的判定条件出错了?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-12-24 11:44:00 | 显示全部楼层
你用的是kbhit() 吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-12-24 11:44:39 | 显示全部楼层
漠水 发表于 2014-12-24 11:39
就是一个反应的机制问题,是下降的时间的控制与按键操作的配合,主要就是一个时间差问题,比如我这个程序 ...

你用的是kbhit() 吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-12-24 11:45:36 | 显示全部楼层
735899422 发表于 2014-12-24 11:44
你用的是kbhit() 吗?

呃,是啊,因为只会学到什么用什么,难道有什么问题吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-12-24 11:51:27 | 显示全部楼层
漠水 发表于 2014-12-24 11:45
呃,是啊,因为只会学到什么用什么,难道有什么问题吗?

没问题 我也是用的这个
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-18 11:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表