俄罗斯方块旋转问题

动感地带世界风 2014-05-03 09:11:48
如果把几种旋转情况和旋转后是否有重叠都建立模型,这样是不是麻烦了
...全文
504 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
unituniverse2 2014-05-04
  • 打赏
  • 举报
回复
引用 12 楼 u012852836 的回复:
明白了,自己做了下图,你写的4楼的好像适合第一象限
因为可以带正负号,所以并不限于哪个象限
  • 打赏
  • 举报
回复
引用 11 楼 unituniverse2 的回复:
[quote=引用 10 楼 u012852836 的回复:] [quote=引用 4 楼 unituniverse2 的回复:] [quote=引用 楼主 u012852836 的回复:] 如果把几种旋转情况和旋转后是否有重叠都建立模型,这样是不是麻烦了
引用 3 楼 u012852836 的回复:
旋转函数需要自己写吗?还是有专门的旋转函数?
高中数学问题。。。 选定旋转中心点以后,对某个方块计算出相对于中心点的偏移量[dx,dy],因为游戏里只用到了90度的旋转,这种最简单,就是把[dx,dy]变成[±dy,±dx]。至于取正还是负取决于你旋转的方向了(别弄错了否则变换后的图形不正常),然后再加回到中心点的坐标就得到了旋转一次后的新坐标 比如以前的老液晶方块游戏机,10*n那种,高度不记得具体多少了,假设左下角为原点[0,0],如果你选定当前的旋转中心为[4,20]对[5,22]这个点向逆时针方向转一次,那就是 [dx,dy]= [5-4,22-20]=[1,2] 然后[-dy,dx]=[-2,1]相对中心转了90度 最后加回中心去就是[-2+4,1+20]=[2,21] 如果再转就是[-dy,dx]=[-1,-2],再转就是[-dy,dx]=[-(-2),-1]=[2,-1],再转就是[-dy,dx]=[-(-1),2]=[1,2],这样就转了一圈回来了; 至于是不是重叠什么的,你直接按计算后的坐标来看那个位置有没有被占用就好,如果被占了就不让旋转。为了防止出现部分旋转的情况,你应该在计算一次完成后再开始真正的旋转,而不要计算一个就马上转一个。 [/quote] (-dy,dx)是怎么来的?[/quote] 看来5楼的回复被你无视了。。。[/quote] 明白了,自己做了下图,你写的4楼的好像适合第一象限
赵4老师 2014-05-04
  • 打赏
  • 举报
回复
//接上帖
void main()
{
    int GameOver=0;
    int key,nextbox;
    int Currentaction=0;/*标记当前动作状态*/
    int gd=VGA,gm=VGAHI,errorcode;

    initgraph(&gd,&gm,"D:\\BC\\BGI");
    errorcode = graphresult();
    if (errorcode != grOk)
    {
        printf("\nNotice:Graphics error: %s\n", grapherrormsg(errorcode));
        printf("Press any key to quit!");
        getchar();
        exit(1);
    }
    setbkcolor(BgColor);
    setcolor(FgColor);
    randomize();    //初始化随机数生成器
    SetTimer(newtimer);

    initialize(Sys_x,Sys_y,Horizontal_boxs,Vertical_boxs);/*初始化*/


    nextbox=MkNextBox(-1);

    show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color);
    show_box(LeftWin_x,Curbox_y+200,nextbox,shapes[nextbox].color);
    show_intro(Sys_x,Curbox_y+320);
    getchar();  //按任意键开始游戏
    while(1)
    {
        /* Currentaction=0;
        flag_newbox=false;
        检测是否有按键*/
        if (bioskey(1)){key=bioskey(0);     }
        else            {           key=0;      }

        switch(key)
        {
            case VK_LEFT:
                if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveLeft))
                {EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_x-=BSIZE;Currentaction=MoveLeft;}
                break;
            case VK_RIGHT:
                if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveRight))
                {EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_x+=BSIZE;Currentaction=MoveRight;}
                break;
            case VK_DOWN:
                if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveDown))
                {EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_y+=BSIZE;Currentaction=MoveDown;}
                else flag_newbox=true;
                break;
            case VK_UP:/*旋转方块*/
                if(MoveAble(Curbox_x,Curbox_y,shapes[current_box_numb].next,MoveRoll))
                {EraseBox(Curbox_x,Curbox_y,current_box_numb);current_box_numb=shapes[current_box_numb].next;
                    Currentaction=MoveRoll;
                }
                break;

            case VK_ESC:
                GameOver=1;
                break;
            default:
                break;
        }

        if(Currentaction)
        {   /*表示当前有动作,移动或转动*/
            show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color);
            Currentaction=0;
        }

            /*按了往下键,但不能下移,就产生新方块*/
        if(flag_newbox)
        {
            /*这时相当于方块到底部了,把其中出现点满一行的清去,置0*/
            ErasePreBox(LeftWin_x,Sys_y+200,nextbox);
            nextbox=MkNextBox(nextbox);
            show_box(LeftWin_x,Curbox_y+200,nextbox,shapes[nextbox].color);
            if(!MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveDown))/*刚一开始,游戏结束*/
            {
                show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color);
                GameOver=1;
            }
            else
            {
                flag_newbox=false;
            }
            Currentaction=0;
        }
        else    /*自由下落*/
        {
            if (Currentaction==MoveDown || TimerCounter> (20-speed*2))
            {
                if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveDown))
                {
                    EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_y+=BSIZE;
                    show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color);
                }
                TimerCounter=0;
            }
        }

        if(GameOver )/*|| flag_newbox==-1*/
        {
            printf("game over,thank you! your score is %d",score);
            getchar();
            break;
        }
    }
    getchar();  //按任意键退出界面
    KillTimer();
    closegraph();
}
赵4老师 2014-05-04
  • 打赏
  • 举报
回复
//接上帖
/*
 * 将新形状的方块放置在游戏板上,并返回此方块号
 */
int MkNextBox(int box_numb)
{

    int mask=128,t_boardx,t_boardy,n,m;
    t_boardx=(Curbox_x-Sys_x)/BSIZE;
    t_boardy=(Curbox_y-Sys_y)/BSIZE;
    for(n=0;n<4;n++)
    {
        for(m=0;m<4;m++)
        {
            if( ((shapes[current_box_numb].box[n/2]) & mask) )
            {
                Table_board[t_boardy+n][t_boardx+m].var=1;/*这里设置游戏板*/
                Table_board[t_boardy+n][t_boardx+m].color=shapes[current_box_numb].color;/*这里设置游戏板*/
            }
            mask=mask/(2);
            if(mask==0)mask=128;
        }
    }
    setFullRow(t_boardy);
    Curbox_x=Sys_x+Begin_boxs_x*BSIZE,Curbox_y=Sys_y;/*再次初始化座标*/
    if(box_numb==-1) box_numb=rand()%MAX_BOX;
    current_box_numb=box_numb;
    flag_newbox=false;
    return(rand()%MAX_BOX);
}

/*
 *  擦除(x,y)位置开始的编号为box_numb的box.
 */
void EraseBox(int x,int y,int box_numb)
{
    int mask=128,t_boardx,t_boardy,n,m;
    setfillstyle(SOLID_FILL,BgColor);
    for(n=0;n<4;n++)
    {
        for(m=0;m<4;m++)    /*看最左边四个单元*/
        {
            if( ((shapes[box_numb].box[n/2]) & mask) )/*最左边有方块并且当前游戏板也有方块*/
            {
                bar(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE);
                line(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE);
                line(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE,y+n*BSIZE+BSIZE);
                line(x+m*BSIZE,y+n*BSIZE+BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE);
                line(x+m*BSIZE+BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE);
            }
            mask=mask/(2);
            if(mask==0)mask=128;
        }
    }

}



 void ErasePreBox(int x,int y,int box_numb)
{
    int mask=128,t_boardx,t_boardy,n,m;
    setfillstyle(SOLID_FILL,BgColor);
    for(n=0;n<4;n++)
    {
        for(m=0;m<4;m++)    /*看最左边四个单元*/
        {
            if( ((shapes[box_numb].box[n/2]) & mask) )/*最左边有方块并且当前游戏板也有方块*/
            {
                bar(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE);

            }
            mask=mask/(2);
            if(mask==0)mask=128;
        }
    }

}

/* 判断是否可以移动
 * x,y为当前方块位置
 * box_numb为方块号
 * direction 方向标志
 *  返回true 和false
 #define MoveLeft -1
 #define MoveRight 1
 #define MoveDown 0
 */
int MoveAble(int x,int y,int box_numb,int direction)
{
    int n,m,t_boardx,t_boardy;          /*t_boardx 当前方块最左边在游戏板的位置*/
    int mask = 128;
    if(direction==MoveLeft)             /*如果向左移*/
    {
        //mask=128;
        x-=BSIZE;
        t_boardx=(x-Sys_x)/BSIZE;
        t_boardy=(y-Sys_y)/BSIZE;
        for(n=0;n<4;n++)
        {
            for(m=0;m<4;m++)    /*看最左边四个单元*/
            {
                if((shapes[box_numb].box[n/2]) & mask)/*最左边有方块并且当前游戏板也有方块*/
                {
                    if((x+BSIZE*m)<Sys_x)return(false);/*碰到最左边了*/
                    else if(Table_board[t_boardy+n][t_boardx+m].var) /*左移一个方块后,此4*4的区域与游戏板有冲突*/
                    {
                        return(false);
                    }
                }
                mask=mask/(2);
                if(mask==0)mask=128;
            }
        }
        return(true);
    }
    else if(direction==MoveRight)       /*如果向右移*/
    {
        x+=BSIZE;
        t_boardx=(x-Sys_x)/BSIZE;
        t_boardy=(y-Sys_y)/BSIZE;
        //mask=128;
        for(n=0;n<4;n++)
        {
            for(m=0;m<4;m++)    /*看最右边四个单元*/
            {
                if((shapes[box_numb].box[n/2]) & mask)/*最右边有方块并且当前游戏板也有方块*/
                {
                    if((x+BSIZE*m)>=(Sys_x+BSIZE*Horizontal_boxs) )return(false);/*碰到最右边了*/
                    else if( Table_board[t_boardy+n][t_boardx+m].var)
                    {
                        return(false);
                    }
                }
                mask=mask/(2);
                if(mask==0)mask=128;
            }
        }
        return(true);
    }
    else if(direction==MoveDown)        /*如果向下移*/
    {
        y+=BSIZE;
        t_boardx=(x-Sys_x)/BSIZE;
        t_boardy=(y-Sys_y)/BSIZE;
        //mask=128;
        for(n=0;n<4;n++)
        {
            for(m=0;m<4;m++)    /*看最下边四个单元*/
            {
                if((shapes[box_numb].box[n/2]) & mask)/*最下边有方块并且当前游戏板也有方块*/
                {
                    if((y+BSIZE*n)>=(Sys_y+BSIZE*Vertical_boxs) ||  Table_board[t_boardy+n][t_boardx+m].var)
                    {
                        flag_newbox=true;
                        break;
                    }
                }
                mask=mask/(2);
                /*mask依次为:10000000,01000000,00100000,00010000
                             00001000,00000100,00000010/00000001
                 */
                if(mask==0)mask=128;
            }
        }
        if(flag_newbox)
        {
            return(false);
        }
        else
            return(true);
    }
    else if(direction==MoveRoll)        /*转动*/
    {
        t_boardx=(x-Sys_x)/BSIZE;
        t_boardy=(y-Sys_y)/BSIZE;
        //mask=128;
        for(n=0;n<4;n++)
        {
            for(m=0;m<4;m++)    /*看最下边四个单元*/
            {
                if((shapes[box_numb].box[n/2]) & mask)/*最下边有方块并且当前游戏板也有方块*/
                {
                    if((y+BSIZE*n)>=(Sys_y+BSIZE*Vertical_boxs) )return(false);/*碰到最下边了*/
                    if((x+BSIZE*n)>=(Sys_x+BSIZE*Horizontal_boxs) )return(false);/*碰到最左边了*/
                    if((x+BSIZE*m)>=(Sys_x+BSIZE*Horizontal_boxs) )return(false);/*碰到最右边了*/

                    else if( Table_board[t_boardy+n][t_boardx+m].var)
                    {
                        return(false);
                    }
                }
                mask=mask/(2);
                if(mask==0)mask=128;
            }
        }
        return(true);
    }
    else
    {
        return(false);
    }

}

/*
 *显示指定的方块
 */
void show_box(int x,int y,int box_numb,int color)
{
    int i,ii,ls_x=x;
    if(box_numb<0 || box_numb>=MAX_BOX)/*指定的方块不存在*/
        box_numb=MAX_BOX/2;
    setfillstyle(SOLID_FILL,color);
/*********************************
 *   移位来判断第哪一位是1
 *   方块是每1行用半个字节来表示
 *   128d=1000 0000b
 *********************************/
    for(ii=0;ii<2;ii++)
    {
        int mask=128;
        for(i=0;i<8;i++)
        {
            if(i%4==0 && i!=0)              /*表示转到方块的下一行了*/
            {
                y+=BSIZE;
                x=ls_x;
            }
                       if((shapes[box_numb].box[ii])&mask)
            {
                bar(x,y,x+BSIZE,y+BSIZE);
                line(x,y,x+BSIZE,y);
                line(x,y,x,y+BSIZE);
                line(x,y+BSIZE,x+BSIZE,y+BSIZE);
                line(x+BSIZE,y,x+BSIZE,y+BSIZE);
            }
            x+=BSIZE;
            mask/=2;
        }
        y+=BSIZE;
        x=ls_x;
    }
}
//未完待续
赵4老师 2014-05-04
  • 打赏
  • 举报
回复
/*
 *俄罗斯方块源程序
 */
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <graphics.h>
#include <bios.h>

#ifdef __cplusplus
    #define __CPPARGS ...
#else
    #define __CPPARGS
#endif

/*定义按键码*/
#define VK_LEFT  0x4b00
#define VK_RIGHT 0x4d00
#define VK_DOWN  0x5000
#define VK_UP    0x4800
#define VK_ESC   0x011b

/*设置中断号*/
#define TIMER 0x1c

/*定义常量*/
#define MAX_BOX 19          /*总共有19种各形态的方块*/
#define BSIZE 20            /*方块的边长是20个象素*/
#define Sys_x 160           /*显示方块界面的左上角x座标*/
#define Sys_y 25            /*显示方块界面的左上角y座标*/
#define Horizontal_boxs 10  /*水平的方向以方块为单位的长度*/
#define Vertical_boxs 15    /*垂直的方向以方块为单位的长度,也就说长是15个方块*/
#define Begin_boxs_x Horizontal_boxs/2  /*产生第一个方块时出现的起始位置*/

#define FgColor CYAN    //前景色
#define BgColor BLACK   //背景颜色

#define LeftWin_x Sys_x+Horizontal_boxs*BSIZE+46        /*右边状态栏的x座标*/

#define false 0
#define true 1

/*移动的方向*/
#define MoveLeft 1
#define MoveRight 2
#define MoveDown 3
#define MoveRoll 4

/*以后坐标的每个方块可以看作是像素点是BSIZE*BSIZE的正方形*/
/*定义全局变量*/
int current_box_numb;   /*保存当前方块编号*/
int Curbox_x=Sys_x+Begin_boxs_x*BSIZE,Curbox_y=Sys_y;/*x,y是保存方块的当前坐标的*/
int flag_newbox=false;  /*是否要产生新方块的标记0*/
int speed=0;            /*下落速度*/
int score=0;            /*总分*/
int speed_step=30;       /*每等级所需要分数*/
void interrupt (*oldtimer)(__CPPARGS);/* 指向原来时钟中断处理过程入口的中断处理函数指针 */

struct BOARD            /*游戏底板结构,表示每个点所具有的属性*/
{
    int var;            /*当前状态 只有0和1,1表示此点已被占用*/
    int color;          /*颜色,游戏底板的每个点可以拥有不同的颜色.增强美观*/
}Table_board[Vertical_boxs][Horizontal_boxs];

/*方块结构*/
struct SHAPE
{
    char box[2];            /*一个字节等于8位,每4位来表示一个方块的一行
                              如:box[0]="0x88",box[1]="0xc0"表示的是:
                              1000
                              1000
                              1100
                              0000*/
    int color;              /*每个方块的颜色*/
    int next;               /*下个方块的编号*/
};


/*初始化方块内容.即定义MAX_BOX个SHAPE类型的结构数组,并初始化*/
struct SHAPE shapes[MAX_BOX]=
{
/*
 *   口     口口口   口口      口
 *   口     口         口  口口口
 *   口口              口
 */
    {0x88,  0xc0,   CYAN,   1},
    {0xe8,  0x0,    CYAN,   2},
    {0xc4,  0x40,   CYAN,   3},
    {0x2e,  0x0,    CYAN,   0},

/*
 *   口        口口 口口口
 *   口 口     口       口
 * 口口 口口口 口
 */
    {0x44,  0xc0,   MAGENTA,  5},
    {0x8e,  0x0,    MAGENTA,  6},
    {0xc8,  0x80,   MAGENTA,  7},
    {0xe2,  0x0,    MAGENTA,  4},

/*
 *   口
 *   口口         口口
 *     口       口口
 */
    {0x8c,  0x40,   YELLOW, 9},
    {0x6c,  0x0,    YELLOW, 8},

/*
 *   口        口口
 * 口口          口口
 * 口
 */
    {0x4c,  0x80,   BROWN,  11},
    {0xc6,  0x0,    BROWN,  10},

/*
 *   口       口                口
 * 口口口     口口   口口口   口口
 *            口       口       口
 */
    {0x4e,  0x0,    WHITE,  13},
    {0x8c,  0x80,   WHITE,  14},
    {0xe4,  0x0,    WHITE,  15},
    {0x4c,  0x40,   WHITE,  12},

/* 口
 * 口
 * 口       口口口口
 * 口
 */
    {0x88,  0x88,   RED,    17},
    {0xf0,  0x0,    RED,    16},

/*
 * 口口
 * 口口
 */
    {0xcc,  0x0,    BLUE,   18}
};


unsigned int TimerCounter=0;  /*定时计数器变量*/

/* 新的时钟中断处理函数 */
void interrupt newtimer(__CPPARGS)
{
    (*oldtimer)();   /* call the old routine */
    TimerCounter++;/* increase the global counter */
}

//时钟中断处理
void SetTimer(void interrupt(*IntProc)(__CPPARGS))
{
    oldtimer=getvect(TIMER);    //获取中断号为TIMER的中断处理函数的入口地址
    disable();  //关中断,以屏蔽其他中断
    setvect(TIMER,IntProc); //设置中断向量,调用中断处理函数
    enable();  //开中断,以响应其他中断
}


/* 恢复原有的时钟中断处理过程 */
void KillTimer()
{
    disable();
    setvect(TIMER,oldtimer);
    enable();
}


//显示帮助信息
void show_intro(int xs,int ys)
{
 char stemp[50];
 setcolor (WHITE);  //设置边框为白色
 rectangle(xs,ys,xs+239,ys+100);
 sprintf(stemp," -Roll  -Downwards");
 stemp[0]=24;   //↑
 stemp[8]=25;  //↓
 setcolor(YELLOW);  //设置文本颜色为黄色
 outtextxy(xs+40,ys+30,stemp);

 sprintf(stemp," -Turn Left   -Turn Right");
 stemp[0]=27;   //←
 stemp[13]=26;  //→

 outtextxy(xs+40,ys+45,stemp);
 outtextxy(xs+40,ys+60,"Esc-Exit ");
 setcolor(FgColor);
}

//显示分数
void ShowScore(int score)
{
    int x,y;
    char score_str[5];/*保存游戏得分*/
    setfillstyle(SOLID_FILL,BgColor);
    x=LeftWin_x;
    y=100;
    bar(x-BSIZE,y,x+BSIZE*3,y+BSIZE*3);
    sprintf(score_str,"%3d",score);
    outtextxy(x,y,"SCORE");
    outtextxy(x,y+10,score_str);
}

//显示级别
void ShowLevel(int speed)
{
    int x,y;
    char speed_str[5];/*保存速度值*/
    setfillstyle(SOLID_FILL,BgColor);
    x=LeftWin_x;
    y=150;
    bar(x-BSIZE,y,x+BSIZE*3,y+BSIZE*3);
    /*确定一个以(x1,y1)为左上角,(x2,y2)为右下角的矩形窗口, 再按规定图模和颜色填充。*/
    sprintf(speed_str,"%3d",speed+1);
    outtextxy(x,y,"Level");
    outtextxy(x,y+10,speed_str);
    /*输出字符串指针speed_str所指的文本在规定的(x, y)位置*/
    outtextxy(x,y+50,"Nextbox");
}


/**********初始化界面*******
 *参数说明:
 *      x,y为左上角坐标
 *      m,n对应于Vertical_boxs,Horizontal_boxs
 *      分别表示纵横方向上方块的个数(以方块为单位)
 *      BSIZE Sys_x Sys_y
 **********************************/
void initialize(int x,int y,int m,int n)
{

    int i,j,oldx;
    oldx=x;
    for(j=0;j<n;j++)
    {
        for(i=0;i<m;i++)
        {

            Table_board[j][i].var=0;
            Table_board[j][i].color=BgColor;
            line(x,y,x+BSIZE,y);
            line(x,y,x,y+BSIZE);
            line(x,y+BSIZE,x+BSIZE,y+BSIZE);
            line(x+BSIZE,y,x+BSIZE,y+BSIZE);
            x+=BSIZE;
        }
        y+=BSIZE;
        x=oldx;
    }
    Curbox_x=x;
    Curbox_y=y;/*x,y是保存方块的当前坐标的*/
    flag_newbox=false;  /*是否要产生新方块的标记0*/
    speed=0;            /*下落速度*/
    score=0;            /*总分*/
    ShowScore(score);
    ShowLevel(speed);

}


/*   删除一行满的情况
 *   这里的y为具体哪一行为满
 */
int DelFullRow(int y)
{
    /*该行游戏板往下移一行*/
    int n,top=0;                /*top保存的是当前最高点,出现一行全空就表示为最点了,移动是到最高点结束*/
    register m,totoal;
    for(n=y;n>=0;n--)/*从当前行往上看*/
    {
        totoal=0;
        for(m=0;m<Horizontal_boxs;m++)
        {
            if(!Table_board[n][m].var)totoal++;             /*没占有方格+1*/
            if(Table_board[n][m].var!=Table_board[n-1][m].var)  /*上行不等于下行就把上行传给下行 xor关系*/
            {
                Table_board[n][m].var=Table_board[n-1][m].var;
                Table_board[n][m].color=Table_board[n-1][m].color;
            }
        }
        if(totoal==Horizontal_boxs)                     /*发现上面有连续的空行提前结束*/
        {
            top=n;
            break;
        }
    }
    return(top);                /*返回最高点*/
}


/*找到一行满的情况*/
void setFullRow(int t_boardy)
{
    int n,full_numb=0,top=0;            /*top保存的是当前方块的最高点*/
    register m;
/*
t_boardy 口       5
         口       6
   口口口口口口   7
n  口口口口口口   8
 */
    for(n=t_boardy+3;n>=t_boardy;n--)
    {
        if(n<0 || n>=Vertical_boxs ){continue;} /*超过低线了*/
        for(m=0;m<Horizontal_boxs;m++)          /*水平的方向*/
        {
            if(!Table_board[n+full_numb][m].var)break;      /*发现有一个是空就跳过该行*/
        }
        if(m==Horizontal_boxs)                  /*找到满行了*/
        {
            if(n==t_boardy+3)                   /*第一次献给了n,最高的*/
                top=DelFullRow(n+full_numb);        /*清除游戏板里的该行,并下移数据*/
            else
                DelFullRow(n+full_numb);
            full_numb++;                        /*统计找到的行数*/

        }
    }
    if(full_numb)
    {
        int oldx,x=Sys_x,y=BSIZE*top+Sys_y;
        oldx=x;
        score=score+full_numb*10;              /*加分数*/
        /*这里相当于重显调色板*/
        for(n=top;n<t_boardy+4;n++)
        {
            if(n>=Vertical_boxs)continue;   /*超过低线了*/
            for(m=0;m<Horizontal_boxs;m++)  /*水平的方向*/
            {
                if(Table_board[n][m].var)
                    setfillstyle(SOLID_FILL,Table_board[n][m].color);/*Table_board[n][m].color*/
                else
                    setfillstyle(SOLID_FILL,BgColor);

                bar(x,y,x+BSIZE,y+BSIZE);
                line(x,y,x+BSIZE,y);
                line(x,y,x,y+BSIZE);
                line(x,y+BSIZE,x+BSIZE,y+BSIZE);
                line(x+BSIZE,y,x+BSIZE,y+BSIZE);
                x+=BSIZE;
            }
            y+=BSIZE;
            x=oldx;
        }
        ShowScore(score);
        if(speed!=score/speed_step)
          {speed=score/speed_step; ShowLevel(speed);}
        else
          {ShowLevel(speed);}
    }
}
//未完待续
Falleyes 2014-05-04
  • 打赏
  • 举报
回复
引用 3 楼 u012852836 的回复:
旋转函数需要自己写吗?还是有专门的旋转函数?
哦~~~楼上连公式都给出来了。
unituniverse2 2014-05-04
  • 打赏
  • 举报
回复
引用 10 楼 u012852836 的回复:
[quote=引用 4 楼 unituniverse2 的回复:] [quote=引用 楼主 u012852836 的回复:] 如果把几种旋转情况和旋转后是否有重叠都建立模型,这样是不是麻烦了
引用 3 楼 u012852836 的回复:
旋转函数需要自己写吗?还是有专门的旋转函数?
高中数学问题。。。 选定旋转中心点以后,对某个方块计算出相对于中心点的偏移量[dx,dy],因为游戏里只用到了90度的旋转,这种最简单,就是把[dx,dy]变成[±dy,±dx]。至于取正还是负取决于你旋转的方向了(别弄错了否则变换后的图形不正常),然后再加回到中心点的坐标就得到了旋转一次后的新坐标 比如以前的老液晶方块游戏机,10*n那种,高度不记得具体多少了,假设左下角为原点[0,0],如果你选定当前的旋转中心为[4,20]对[5,22]这个点向逆时针方向转一次,那就是 [dx,dy]= [5-4,22-20]=[1,2] 然后[-dy,dx]=[-2,1]相对中心转了90度 最后加回中心去就是[-2+4,1+20]=[2,21] 如果再转就是[-dy,dx]=[-1,-2],再转就是[-dy,dx]=[-(-2),-1]=[2,-1],再转就是[-dy,dx]=[-(-1),2]=[1,2],这样就转了一圈回来了; 至于是不是重叠什么的,你直接按计算后的坐标来看那个位置有没有被占用就好,如果被占了就不让旋转。为了防止出现部分旋转的情况,你应该在计算一次完成后再开始真正的旋转,而不要计算一个就马上转一个。 [/quote] (-dy,dx)是怎么来的?[/quote] 看来5楼的回复被你无视了。。。
unituniverse2 2014-05-04
  • 打赏
  • 举报
回复
旋转任意角度 确实有公式(其实根本不用记)。 比如我想相对于原点(0,0)旋转角度a(可正可负)假设原来的坐标为(x,y),表示为极坐标就是(r,θ),对应关系就是(别问我怎么来的,这是三角函数的定义公式): {x = r cos(θ); y = r sin(θ)} 所以旋转后的新坐标就是 {x2 = r cos(θ+a); y2 = r sin(θ+a)} 根据三角函数的分解公式,上式等于 {x2 = r cos(θ+a) = r(cos(θ)cos(a)-sin(θ)sin(a)) = r cos(θ) cos(a) - r sin(θ) sin(a); y2 = r sin(θ+a) = r(sin(θ)cos(a)+cos(θ)sin(a)) = r sin(θ) cos(a) + r cos(θ) sin(a)} 注意看原来的按极坐标表示的直角坐标公式,上式就等于 {x2 = x cos(a) - y sin(a); y2 = x sin(a) + y cos(a) } 如果旋转90度逆时针,那么cos(π/2)=0,sin(π/2)=1,所以此时x2=-y, y2=x; 如果旋转90度顺时针,那么cos(-π/2)=0,sin(-π/2)=-1,所以此时x2=y, y2=-x。 当然你也可以把顺时针旋转看作是逆时针旋转的逆变换(反之亦然): 顺时针就是x=-y2, y=x2,也就是x2=y, y2=-x 然后如果旋转中心不在原点,就需要减去原点坐标再转,转完了再加回来
unituniverse2 2014-05-04
  • 打赏
  • 举报
回复
引用 楼主 u012852836 的回复:
如果把几种旋转情况和旋转后是否有重叠都建立模型,这样是不是麻烦了
引用 3 楼 u012852836 的回复:
旋转函数需要自己写吗?还是有专门的旋转函数?
高中数学问题。。。 选定旋转中心点以后,对某个方块计算出相对于中心点的偏移量[dx,dy],因为游戏里只用到了90度的旋转,这种最简单,就是把[dx,dy]变成[±dy,±dx]。至于取正还是负取决于你旋转的方向了(别弄错了否则变换后的图形不正常),然后再加回到中心点的坐标就得到了旋转一次后的新坐标 比如以前的老液晶方块游戏机,10*n那种,高度不记得具体多少了,假设左下角为原点[0,0],如果你选定当前的旋转中心为[4,20]对[5,22]这个点向逆时针方向转一次,那就是 [dx,dy]= [5-4,22-20]=[1,2] 然后[-dy,dx]=[-2,1]相对中心转了90度 最后加回中心去就是[-2+4,1+20]=[2,21] 如果再转就是[-dy,dx]=[-1,-2],再转就是[-dy,dx]=[-(-2),-1]=[2,-1],再转就是[-dy,dx]=[-(-1),2]=[1,2],这样就转了一圈回来了; 至于是不是重叠什么的,你直接按计算后的坐标来看那个位置有没有被占用就好,如果被占了就不让旋转。为了防止出现部分旋转的情况,你应该在计算一次完成后再开始真正的旋转,而不要计算一个就马上转一个。
  • 打赏
  • 举报
回复
引用 4 楼 unituniverse2 的回复:
[quote=引用 楼主 u012852836 的回复:] 如果把几种旋转情况和旋转后是否有重叠都建立模型,这样是不是麻烦了
引用 3 楼 u012852836 的回复:
旋转函数需要自己写吗?还是有专门的旋转函数?
高中数学问题。。。 选定旋转中心点以后,对某个方块计算出相对于中心点的偏移量[dx,dy],因为游戏里只用到了90度的旋转,这种最简单,就是把[dx,dy]变成[±dy,±dx]。至于取正还是负取决于你旋转的方向了(别弄错了否则变换后的图形不正常),然后再加回到中心点的坐标就得到了旋转一次后的新坐标 比如以前的老液晶方块游戏机,10*n那种,高度不记得具体多少了,假设左下角为原点[0,0],如果你选定当前的旋转中心为[4,20]对[5,22]这个点向逆时针方向转一次,那就是 [dx,dy]= [5-4,22-20]=[1,2] 然后[-dy,dx]=[-2,1]相对中心转了90度 最后加回中心去就是[-2+4,1+20]=[2,21] 如果再转就是[-dy,dx]=[-1,-2],再转就是[-dy,dx]=[-(-2),-1]=[2,-1],再转就是[-dy,dx]=[-(-1),2]=[1,2],这样就转了一圈回来了; 至于是不是重叠什么的,你直接按计算后的坐标来看那个位置有没有被占用就好,如果被占了就不让旋转。为了防止出现部分旋转的情况,你应该在计算一次完成后再开始真正的旋转,而不要计算一个就马上转一个。 [/quote] (-dy,dx)是怎么来的?
  • 打赏
  • 举报
回复
旋转函数需要自己写吗?还是有专门的旋转函数?
Falleyes 2014-05-03
  • 打赏
  • 举报
回复
不明白楼主的是否有重叠建立模型是什么意思,俄罗斯方块,不论什么样的小块,至多4种旋转形态,但只有两种旋转方向。 你可以把这种二维点块图形写两个函数,一个左旋转,一个右旋转。这样就没必要对每种小块的每种形态做模型了。
  • 打赏
  • 举报
回复
如果麻烦了那该如何做

64,649

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧