回 帖 发 新 帖 刷新版面

主题:TC下的俄罗斯方块游戏 

/* 制作人  :波上清风       */
/* TC下的俄罗斯方块游戏   */
/*QQ:164094487*/
/*个人主页:http://mail.ustc.edu.cn/~fygood          */
/*游戏开始前用四个方向键调整高度和速度,按回车键开始游戏 */
/*游戏过程中回车键为暂停键,ESC键为退出键*/

/*需要有C:\\turboc2       */
/*不好意思,本人前一次发的有问题,现在重发一遍*/
/*感谢那些提出问题和建议的人*/

#include <graphics.h>
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>

/*定义左上角点在屏幕上的位置*/
#define MAPXOFT     9
#define MAPYOFT     5

/*定义下一个方块显示的位置*/
#define MAPXOFT1     13
#define MAPYOFT1     -2


#define LEFT  0x4b00
#define RIGHT 0x4d00
#define DOWN  0x5000  /*此键为加速键*/
#define UP    0x4800  /*此键为变形键*/
#define ESC   0x011b  /*此键为退出键*/
#define ENTER 0x1c0d


#define TIMER 0x1c /* 时钟中断的中断号 */

/* 中断处理函数在C和C++中的表示略有不同。
如果定义了_cplusplus则表示在C++环境下,否则是在C环境下。 */

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

int TimerCounter=0; /* 计时变量,每秒钟增加18。 */

/* 指向原来时钟中断处理过程入口的中断处理函数指针(句柄) */
void interrupt ( *oldhandler)(__CPPARGS);

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

/* 设置新的时钟中断处理过程 */
void SetTimer(void interrupt (*IntProc)(__CPPARGS))
{
    oldhandler=getvect(TIMER);
    disable(); /* 设置新的时钟中断处理过程时,禁止所有中断 */
    setvect(TIMER,IntProc);
    enable(); /* 开启中断 */
}

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


struct shape
{
    int xy[8],next;
};

struct shape shapes[19]=
{
/*x1,y1,x2,y2,x3,y3,x4,y4 指四个小方块的相对坐标,next指此方块变形后应变为哪个小方块
    { x1,y1,x2,y2,x3,y3,x4,y4,next}*/
    { 0,-2, 0,-1, 0, 0, 1, 0, 1},
    {-1, 0, 0, 0, 1,-1, 1, 0, 2},
    { 0,-2, 1,-2, 1,-1, 1, 0, 3},
    {-1,-1,-1, 0, 0,-1, 1,-1, 0},
    { 0,-2, 0,-1, 0, 0, 1,-2, 5},
    {-1,-1, 0,-1, 1,-1, 1, 0, 6},
    { 0, 0, 1,-2, 1,-1, 1, 0, 7},
    {-1,-1,-1, 0, 0, 0, 1, 0, 4},
    {-1, 0, 0,-1, 0, 0, 1, 0, 9},
    { 0,-2, 0,-1, 0, 0, 1,-1,10},
    {-1,-1, 0,-1, 1,-1, 0, 0,11},
    { 0,-1, 1,-2, 1,-1, 1, 0, 8},
    {-1, 0, 0,-1, 0, 0, 1,-1,13},
    { 0,-2, 0,-1, 1,-1, 1, 0,12},
    {-1,-1, 0,-1, 0, 0, 1, 0,15},
    { 0,-1, 0, 0, 1,-2, 1,-1,14},
    { 0,-3, 0,-2, 0,-1, 0, 0,17},
    {-1, 0, 0, 0, 1, 0, 2, 0,16},
    { 0,-1, 0, 0, 1,-1, 1, 0,18}
};

int board[10][20]={0};/*定义游戏板初始化为0*/
char sp[]="0",le[]="0",sc[]="00000";
int speed,speed0,level,score;
int sign,flag;
int style,style1;  /*style为当前方块的种类,style1为即将输出的方块的种类*/

void draw_block(int x,int y,int style,int way);
void draw_little_block(int x,int y);
void init();
void initialize();
void speed_change(void);
void score_change(int);
void kill_line(int y);
void fill_board(int x,int y, int style);
int  change(int *i,int *j,int key);
void renovate(void);
void ajustment(void);
void level_change(void);


main()
{
    int i,j,key,x0=5,y0=1;
    randomize();
    while(!flag)                    /*flag为0表示重新开始游戏*/
    {
        level=score=speed=0;
        strcpy(le,"0");
        strcpy(sp,"0");
        strcpy(sc,"00000");
        for(i=0;i<10;i++)
            for(j=0;j<20;j++)
                board[i][j]=0;       /*初始化一些变量为0*/
            initialize();            /*初始化进入图形模式*/
            init();                  /*初始化游戏板记分器等*/
            SetTimer(newhandler);    /* 修改时钟中断 */
            ajustment();             /*开始游戏前调整速度和高度*/
            
            if(level>0)
                level_change();       /*根据高度随机确定方块是否存在*/
            
            style=random(19);         /*随机确定方块种类*/
            
            
            while(1)
            {
                i=x0,j=y0;
                
                style1=random(19);    /*随机确定即将出现的方块种类*/
                setcolor(WHITE);
                sign=1;
                draw_block(MAPXOFT1,MAPYOFT1,style1,1);
                /*画出即将出现的方块*/
                
                for(j=y0;j<=20;j++)   /*使方块下降*/
                {
                    
                    
                    if(!check_block(i,j,style))
                        break;
                    draw_block(i,j,style,1);
                    
                    
                    while(1)
                    {
                        if(speed0==0)                /*未按下加速键时的处理*/
                            
                        {
                            if (TimerCounter>18/(speed+1))
                            {
                                /* 恢复计时变量 */
                                TimerCounter=0;
                                break;
                            }
                        }
                        else if(TimerCounter>18/(9+1))/*按下加速键时的处理*/
                        {
                            /* 恢复计时变量 */
                            TimerCounter=0;
                            speed0=0;
                            break;
                        }
                        if(bioskey(1))
                        {
                            key=bioskey(0);
                            if(change(&i,&j,key))/*根据按键值做调整*/
                            {
                                flag=1;
                                goto end;
                            }
                            
                        }
                        
                        
                        
                    }
                    
                    draw_block(i,j,style,0);
                    renovate();                   /*刷新屏幕*/
                    
                    
                }
                
                if(j==y0)
                    break;
                j--;
                
                draw_block(i,j,style,1);
                
                fill_board(i,j,style);
                
                
                sign=1;
                draw_block(MAPXOFT1,MAPYOFT1,style1,0);
                style=style1;
                kill_line(j);     /*消去的函数,消去若干行并改变分数和速度*/
                
                
                while(bioskey(1))    /*清除内存中的按键*/
                    key=bioskey(0);
            }
            setcolor(CYAN);
            settextstyle(0,0,2);
            TimerCounter=0;
            
            while(1)
                if(TimerCounter>54)
                {
                    TimerCounter=0;
                    break;
                }
                while(bioskey(1))     /*清除内存中的按键*/
                    key=bioskey(0);
                outtextxy(400,340,"Game over!");
                outtextxy(360,360,"Enter to replay.");
                outtextxy(360,380,"Esc to quit.");
                while(bioskey(1)==0);
                key=bioskey(0);
                
                 end:;
                closegraph();
                KillTimer();
                if(key==ESC||flag)
                    break;
    }
    
}



void initialize()/*初始化进入图形模式*/
{
    int gdriver = VGA, gmode=VGAHI, errorcode;
    
    /* initialize graphics mode */
    
    initgraph(&gdriver, &gmode, "c:\\Turboc2");
    
    /* read result of initialization */
    errorcode = graphresult();
    
    if (errorcode != grOk) /* an error occurred */
        
    {
        printf("Graphics error: %s\n", grapherrormsg(errorcode));
        printf("Press any key to halt:");
        getch();
        exit(1); /* return with error code */
    }
}

void init(void)/*初始化游戏板记分器等*/
{
    int x1;
    x1=5+MAPXOFT;
    setcolor(GREEN);
    circle((x1+0.5)*16,(MAPYOFT-2)*16,3*16);
    setcolor(WHITE);
    line((x1-0.6)*16,(MAPYOFT-3.2)*16,x1*16,(MAPYOFT-3.2)*16);
    line((x1+1.4)*16,(MAPYOFT-3.2)*16,(x1+2.0)*16,(MAPYOFT-3.2)*16);
    line((x1+0.5)*16,(MAPYOFT-2)*16,(x1+0.5)*16,(MAPYOFT-1.7)*16);
    circle((x1+0.5)*16,(MAPYOFT-0.9)*16,0.3*16);
    setcolor(CYAN);
    line((MAPXOFT+3)*16,(MAPYOFT+21)*16,MAPXOFT*16,(MAPYOFT+23.5)*16);
    line((MAPXOFT+5.5)*16,(MAPYOFT+21)*16,MAPXOFT*16,(MAPYOFT+26)*16);
    line((MAPXOFT+9)*16,(MAPYOFT+21)*16,(MAPXOFT+12)*16,(MAPYOFT+23.5)*16);
    line((MAPXOFT+6.5)*16,(MAPYOFT+21)*16,(MAPXOFT+12)*16,(MAPYOFT+26)*16);
    setcolor(MAGENTA);
    ellipse((MAPXOFT+1)*16,(MAPYOFT+11)*16,90,270,7*16,7*16);
    ellipse((MAPXOFT+11)*16,(MAPYOFT+11)*16,-90,90,7*16,7*16);
    circle((MAPXOFT+24)*16,(MAPYOFT+6)*16,6*16);
    setcolor(WHITE);
    rectangle((x1-0.5)*16,(MAPYOFT-2.9)*16,(x1-0.1)*16,(MAPYOFT-2.5)*16);
    rectangle((x1+1.5)*16,(MAPYOFT-2.9)*16,(x1+1.9)*16,(MAPYOFT-2.5)*16);
    setcolor(YELLOW);
    rectangle(10*16,6*16,20*16,26*16);
    settextstyle(0,0,2);
    outtextxy(5*16,13.5*16,"level");
    outtextxy(20.4*16,13.5*16,"speed");
    outtextxy((MAPXOFT+22)*16,(MAPYOFT+3)*16,"score");
    settextstyle(0,0,4);
    outtextxy(6.5*16,15*16,"0");
    outtextxy(21.9*16,15*16,"0");
    settextstyle(0,0,3);
    outtextxy((MAPXOFT+21)*16,(MAPYOFT+6)*16,sc);
}


void ajustment(void)            /*开始游戏前调整速度和高度*/
{
    int key,boo=1,left=1;
    setcolor(YELLOW);
    settextstyle(0,0,2);
    outtextxy(500,340,"PRESS");
    outtextxy(500,360,"ENTER");
    outtextxy(500,380," TO  ");
    outtextxy(500,400,"START");
    while(1)
    {
        if(TimerCounter>8)
        {
            TimerCounter=0;
            boo*=-1;
            if(boo==-1)
                setcolor(BLACK);
            else
                setcolor(YELLOW);
            if(left==1)
            {
                line(6*16,17*16,8.5*16,17*16);
                setcolor(BLACK);
                line(21.4*16,17*16,23.9*16,17*16);
            }
            
            else
            {
                line(21.4*16,17*16,23.9*16,17*16);
                setcolor(BLACK);
                line(6*16,17*16,8.5*16,17*16);
            }
        }
        if(bioskey(1))
        {
            key=bioskey(0);
            if(key==UP||key==DOWN)
            {
                setcolor(BLACK);
                settextstyle(0,0,4);
                outtextxy(6.5*16,15*16,le);
                outtextxy(21.9*16,15*16,sp);
            }
            if(key==ENTER)
                break;
            else if(key==UP)
            {
                if(left==1)
                {
                    level--;
                    if(level==-1)
                        level=9;
                }
                else
                {
                    speed--;
                    if(speed==-1)
                        speed=9;
                }
            }
            else if(key==DOWN)
            {
                if(left==1)
                {
                    level++;
                    if(level==10)
                        level=0;
                    
                }
                else
                {
                    speed++;
                    if(speed==10)
                        speed=0;
                }
            }
            
            else if(key==LEFT||RIGHT)
                left*=-1;
            setcolor(YELLOW);
            sp[0]=speed+'0';
            le[0]=level+'0';
            settextstyle(0,0,4);
            outtextxy(6.5*16,15*16,le);
            outtextxy(21.9*16,15*16,sp);
        }
    }
    setcolor(YELLOW);
    sp[0]=speed+'0';
    le[0]=level+'0';
    settextstyle(0,0,4);
    outtextxy(6.5*16,15*16,le);
    outtextxy(21.9*16,15*16,sp);
    setcolor(BLACK);
    line(21.4*16,17*16,23.9*16,17*16);
    line(6*16,17*16,8.5*16,17*16);
    settextstyle(0,0,2);
    outtextxy(500,340,"PRESS");
    outtextxy(500,360,"ENTER");
    outtextxy(500,380," TO  ");
    outtextxy(500,400,"START");
}


void level_change(void)         /*根据高度随机确定方块是否存在*/
{
    int i,j;
    setcolor(WHITE);
    for(i=1;i<=10;i++)
        for(j=1;j<=level;j++)
            if(random(2))
            {
                board[i-1][20-j]=1;
                
                draw_little_block(i+MAPXOFT,21-j+MAPYOFT);
            }
}





void draw_block(int x,int y,int style,int way)
/*此x,y为虚拟坐标,为19中形式中的一种:0~18中的一个
x,y为10*20的方格的坐标,下标从1开始
way为1表填充,为0表清除*/
{
    int x1=x+MAPXOFT,y1=y+MAPYOFT;
    int i;
    if(way==1)
        setcolor(WHITE);
    else
        setcolor(BLACK);
    for(i=0;i<=6;i+=2)
        draw_little_block(x1+shapes[style].xy[i],y1+shapes[style].xy[i+1]);
    if(sign==1)
        sign=0;
}






void draw_little_block(int x,int y)/*此处仅在10*20的游戏版内画小方块,若在外,不画之。*/
{
    if((x>=10&&x<20&&y>=6&&y<26)||sign)
    {
        rectangle(x*16,y*16,x*16+16,y*16+16);
        circle(x*16+8,y*16+8,4);
    }
}


int check_block(int x,int y,int style)/*此处检查在(x,y)处放置一方块是否可以,若是,则返回1,否则返回0*/
{
    int x1=x+MAPXOFT,y1=y+MAPYOFT;
    int x2,y2,i;
    for(i=0;i<=6;i+=2)
    {
        x2=x1+shapes[style].xy[i];
        y2=y1+shapes[style].xy[i+1];
        if(x2>=10&&x2<20&&y2<26&&(y2<6||board[x2-10][y2-6]==0))
            continue;
        else
            break;
    }
    if(i==8)
        return 1;
    else
        return 0;
}

void speed_change(void)        /*此为变速函数,当分数超过一级时,即加一。*/
{
    if(score>=(sp[0]-'0')*100&&(sp[0]-'0')<9)
    {
        settextstyle(0,0,4);
        setcolor(BLACK);
        outtextxy(21.9*16,15*16,sp);
        sp[0]++;
        speed++;
        settextstyle(0,0,4);
        setcolor(YELLOW);
        outtextxy(21.9*16,15*16,sp);
    }
}

void score_change(int count)        /*count为消去的行数,据此来改变score的值*/
{
    int score_inc[4]={1,3,7,13};
    int i;
    
    setcolor(BLACK);
    settextstyle(0,0,3);
    outtextxy((MAPXOFT+21)*16,(MAPYOFT+6)*16,sc);/*此处将原有的分数盖掉*/
    
    score+=score_inc[count-1];
    sc[4]+=score_inc[count-1];
    for(i=4;i>=1;i--)
    {
        
        sc[i-1]+=(sc[i]-'0')/10;
        sc[i]-=(sc[i]-'0')/10*10;
    }
    setcolor(YELLOW);
    settextstyle(0,0,3);
    outtextxy((MAPXOFT+21)*16,(MAPYOFT+6)*16,sc);      /*输出新分数*/
}



void kill_line(int y)/*消去的函数,消去若干行并改变分数和速度*/
{
    int count=0,i,t=1,j,k;
    for(;y>=1&&t<=4;y--,t++)
    {
        for(i=1;i<=10;i++)
            if(!board[i-1][y-1])
                break;
            if(i==11)
            {
                count++;
                for(k=1;k<=10;k++)
                {
                    setcolor(BLACK);
                    draw_little_block(k+MAPXOFT,y+MAPYOFT);
                }
                for(j=y-1;j>=1;j--)
                    for(k=1;k<=10;k++)
                    {
                        board[k-1][j]=board[k-1][j-1];
                        if(board[k-1][j])
                        {
                            setcolor(BLACK);
                            draw_little_block(k+MAPXOFT,j+MAPYOFT);
                            setcolor(WHITE);
                            draw_little_block(k+MAPXOFT,j+1+MAPYOFT);                    }
                    }
                    renovate();
                    delay(10000);
                    y++;
            }
            
    }
    
    if(count>0)
    {
        
        setcolor(CYAN);
        settextstyle(0,0,3);
        outtextxy(500,370,"Good!");
        TimerCounter=0;
        while(1)
            if(TimerCounter>3)
            {
                TimerCounter=0;
                break;
            }
            
            setcolor(BLACK);
            settextstyle(0,0,3);
            outtextxy(500,370,"Good!");
            
            
            score_change(count);
            speed_change();
    }
}

void fill_board(int x,int y, int style) /*当一方块停止时,将中相应的值改为1*/
{
    
    int x1,y1,i;
    for(i=0;i<=6;i+=2)
    {
        x1=x+shapes[style].xy[i];
        y1=y+shapes[style].xy[i+1];
        board[x1-1][y1-1]=1;
    }
}

int change(int *i,int *j,int key)/*控制方块移动、变形的函数*/
{
    int key1;
    if(key==UP&&check_block(*i,*j,shapes[style].next))
    {
        draw_block(*i,*j,style,0);
        style=shapes[style].next;
        draw_block(*i,*j,style,1);
    }
    else if(key==LEFT&&check_block(*i-1,*j,style))
    {
        draw_block(*i,*j,style,0);
        (*i)--;
        draw_block(*i,*j,style,1);
    }
    else if(key==RIGHT&&check_block(*i+1,*j,style))
    {
        draw_block(*i,*j,style,0);
        (*i)++;
        draw_block(*i,*j,style,1);
    }
    else if(key==DOWN&&check_block(*i,*j+1,style))
    {
        draw_block(*i,*j,style,0);
        (*j)++;
        draw_block(*i,*j,style,1);
        speed0=9;
    }
    else if(key==ENTER)
    {
        while(1)
        {
            
            if(bioskey(1))
                key1=bioskey(0);
            if(key1==ENTER)
                break;
        }
    }
    else if(key==ESC)
        return 1;
    else if(key==21040)
          {
        sign=1;
        draw_block(MAPXOFT1,MAPYOFT1,style1,0);
        style1=16;
        sign=1;
        draw_block(MAPXOFT1,MAPYOFT1,style1,1);
    }
    return 0;
}


void renovate(void)    /*刷新屏幕*/
{
    int i,j;
    setcolor(WHITE);
    for(i=1;i<=10;i++)
        for(j=1;j<=20;j++)
            if(board[i-1][j-1]==1)
                draw_little_block(i+MAPXOFT,j+MAPYOFT);
            
            setcolor(YELLOW);
            rectangle(10*16,6*16,20*16,26*16);
            
            
}
[url]http://mail.ustc.edu.cn/~fygood[/url]

回复列表 (共86个回复)

沙发

up一下

板凳

纯纯的自己编的?

3 楼

fatal error C1083: Cannot open include file: 'graphics.h': No such file or directory
Error executing cl.exe.

4 楼

tc下的include中有此图形文件,你是不是tc不完整??
本程序是参考了有关文件,但确实是自己所写。

5 楼

[size=2][color=000080]厉害![/color][/size]

6 楼

请问你是在dos底下,编译的吗??
反正我在98的ms-dos下老是会出错的,2k和xp 也一样

7 楼

WIN98环境下用TC编译的,没什么问题吧。

8 楼

天呀,你学多长时间能学到这种程度啊,以后可有问题多请教你了呀!

9 楼

我曾经在98的dos环境下进行过图形编程,可是每次都是说图形模式初始化错误,我听高手说过,那要在纯dos下会比较好

10 楼

 我学计算机的还不会编,惭愧呀

我来回复

您尚未登录,请登录后再回复。点此登录或注册