俄罗斯方块

作者在 2010-08-12 23:48:04 发布以下内容
/*
俄罗斯方块源码
编译环境:tc2.0
by:spygg
仿真环境:dosbox
若是移植到windows下需修改delay函数中的值为10000000000
游戏板大小为21行12列
*/
#include <graphics.h>
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>

void draw_little_block(int ,int ,int );
void draw_block(int ,int ,int,int);
void change(int *i,int *j,int key);
int check_block(int x,int y,int style);
void kill_line(int y);
void gameover();


int style_next,style,score=0,speed=0;  /*we use speed control the block's drop speed*/
int board[22][14]={0};
char str[100];

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


#define STARTX 13          /* The first block's x potision */
#define STARTY 1            /* The first block's y potision */

#define STARTX1 15             /* The preview of the block */
#define STARTY1 6

#define LEFT 0x4b00                    /*define of the key*/
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
#define ENTER 0x1c0d

/*以左上角为(0,0) ,第九个是颜色,第十个是变形后的索引*/
struct shape shapes[19]=
{
    /*set lefttop's potision is (0,0)  ;after 8 x,y valule is color; and then next we call it style      */
    {1,1,1,2,1,3,2,3,1,1},        /*                                      __                                      */
    {2,2,0,3,1,3,2,3,1,2},        /* |                                       |                                        */
    {1,1,2,1,2,2,2,3,1,3},        /* |                      |                |              _____               */
    {0,2,1,2,2,2,0,3,1,0},        /* |__        _____|                |             |                        */

    {1,1,2,1,1,2,1,3,2,5},       /*    ------                                                                       */
    {0,2,0,3,1,3,2,3,2,6},        /*   |                                       |                                   */
    {2,1,2,2,1,3,2,3,2,7},        /*   |           |                           |             _____              */
    {0,2,1,2,2,2,2,3,2,4},        /*    |          |_____            _ _|                       |               */

    {1,2,0,3,1,3,2,3,6,9},       /*                                                                                */
    {2,1,1,2,2,2,2,3,6,10},    /*                           |                            |                            */
    {0,2,1,2,2,2,1,3,6,11},    /*       |           - ---  |          -------         |----                       */
    {1,1,1,2,2,2,1,3,6,8},      /*    -----                |              |             |                         */



    {1,2,2,2,0,3,1,3,4,13},      /*        ----        |__                                                       */
    {1,1,1,2,2,2,2,3,4,12},      /*    __|                |                                                       */

    {0,2,1,2,1,3,2,3,14,15},       /*    ----                     __|                                          */
    {2,1,1,2,2,2,1,3,14,14},       /*        |__                |                                               */

    {1,0,1,1,1,2,1,3,3,17},      /*     |                                                                           */
    {0,3,1,3,2,3,3,3,3,16},      /*     |            ____                                                    */
                                    /*         ___                                                                    */
    {1,2,2,2,1,3,2,3,61,18}      /*             |__|                                                             */
};


void draw_little_block(int x,int y,int color)                  /*DARK==0*/
{
    setfillstyle(1,color);               /*当color 值为0时候画的为黑色方块*/                            
    bar(x*16+1,y*16+1,x*16+16-1,y*16+16-1);             /*加1和减1是为了美观*/
}

/*style是方块的种类,way决定了方块是否为黑色*/
void draw_block(int x,int y,int style,int way)          /*style is the shape of the block 0~18, way decide the block is dark or not*/
{
    int i,j;
    for(i=0;i<=6;i+=2)
    {
        if(way==1)        /*由大方块左上角的x值加上STARTX得到相对于起始位置的坐标因为方块总是从游戏板中间下落,加STATRX只是为了方便没有什么特别的意义*/
            draw_little_block(x+STARTX+shapes[style].xy[i], y+STARTY+shapes[style].xy[i+1], shapes[style].gen_color);/*画出方块并着色*/
        else
            draw_little_block(x+STARTX+shapes[style].xy[i], y+STARTY+shapes[style].xy[i+1], 0);                           /*把方块涂黑*/
    }
}


int check_block(int x,int y,int style)
{
    int i;
    for(i=0;i<=6;i+=2)
        if((board[y+shapes[style].xy[i+1]-4][x+shapes[style].xy[i]+5]!=0))     /*如果方块此位置非空则返回*/
            return 0;
    return 1;
}

void change(int *n,int *m,int key)
{
    speed=0;
    if(key==UP&&(check_block(*n,*m,shapes[style].next)==1))
    {
        draw_block(*n,*m,style,0);
        style=shapes[style].next;                                                  /*变形为同类的下一个见图形 */
        draw_block(*n,*m,style,1);
    }
    else if((key==LEFT)&&(check_block(*n-1,*m,style)==1)&&(*m>1))          
    {
        draw_block(*n,*m,style,0);
        (*n)--;
        draw_block(*n,*m,style,1);
    }
    else if((key==DOWN)&&(check_block(*n,*m+1,style)==1))
    {
        draw_block(*n,*m,style,0);
        (*m)++;
        draw_block(*n,*m,style,1);
        speed=1;
    }
    else if((key==RIGHT)&&(check_block(*n+1,*m,style)==1)&&(*m>1))
    {
        draw_block(*n,*m,style,0);
        (*n)++;
        draw_block(*n,*m,style,1);
    }
    else if(key==ENTER)
    {
        while(1)                         /*等待下一次ENTER按下*/
        {
            if(bioskey(1))
                if((key=bioskey(0))==ENTER)
                    break;
        }
    }
    else if(key==ESC)
        exit(0);
}
/*
此是游戏的难点,消行首先要判断时候有满行,判断条件是游戏板中的某行所有值都为1则说明满行
只有方块下落时才可能消行,又因为方块高度最大为4,所以判断四行
有满行要把满的行全部涂黑,值清零,再将此行上方的图形顺次下移一行
*/
void kill_line(int y)
{
    int i,j,k,flag=0;
    for(i=0;i<4;i++)       /*只需要判断四行*/
    {
        flag=0;
        for(j=0;j<12;j++)           /*每一行是否全满*/
        {
            flag=0;
            if(board[y+i-4][j+1]==0)
            {
                flag=1;
                break;
            }
        }
        if(flag==0)    /*若是有某行全满*/
        {
            score++;
            for(j=0;j<12;j++)     /*把此行的值赋值0 并涂黑*/
            {
                board[y+i-4][j+1]=0;
                draw_little_block(j+9,y+4-1,0);
            }
            for(k=0;k<y-4+i;k++)            /*从此行开始到最顶端所有的行*/
            {
                for(j=0;j<12;j++)
                {
                    draw_little_block(j+9,y+i-k+STARTY,0);            /*首先把消去行的涂黑,以便于下落*/
                    board[y+i-4-k][j+1]=board[y+i-1-4-k][j+1];      /*循环把上一行的值赋给下一行*/
                    if(board[y+i-4-k][j+1]!=0)                             /*如果有值则画出该小方块,没有的话不处理*/
                        draw_little_block(j+9,y+i-k+STARTY,board[y+i-4-k][j+1]);
                }
            }
            delay(100);
        }
    }
    delay(100);
}

void gameover(int *n,int *m,int style)
{
    int k,flag=0;
    for(k=4;k<8;k++)                                     /*判断最顶端的中间位置是否有方块*/
            if(board[1][k+1]!=0)
                flag=1;
                
    if((flag==1)&&(check_block(*n-1,*m,style)==0)&&(check_block(*n+1,*m,style)==0))  /*若是有方块并且不能左右移动则说明游戏结束*/
    {
        settextstyle(0,0,3);                                                    
        outtextxy(150,200,"Game Over!");
        exit(0);
    }
}

int main(void)
{

    int graph_driver,graph_mode;
    int m,n,key,i,k;
    graph_driver=DETECT;
    initgraph(&graph_driver,&graph_mode," ");                        /*初始化图形模式*/
    randomize();                                                                /*初始化随机函数*/
    for(i=0;i<22;i++)                                                        /*给方块增加三排卫兵*/
    {
        board[i][0]=1;
        board[i][13]=1;
    }
    for(i=1;i<13;i++)
        board[21][i]=1;
    
    
    settextstyle(0,0,3);                                                      /*设置文字格式*/
    outtextxy(20,200,"press any key to start!");                      /*输出等待提示用户开始*/
    getch();                                                                     /*等待用户任意键进入游戏*/
    cleardevice();                                                              /*清屏*/
    line(142,80,142,418);
    line(338,80,338,418);
    line(142,418,338,418);                                                  /*勾画游戏区域*/
    
    while(1)
    {
        settextstyle(0,0,1);
        setcolor(LIGHTRED); /* 画计分板*/
        setlinestyle(0,0,1);
        setfillstyle(1,BLUE);
        rectangle(450,50,500,70);
        floodfill(455,55,LIGHTRED);
        setcolor(14);
        itoa(score,str,10);
        outtextxy(460,55,str);

        style_next=random(19);                     /*随机化方块*/
        draw_block(STARTX1,STARTY1,style_next,1);             /*画出预览*/
        m=0;
        n=0;
        while(1)                           /*方块的调整*/
        {
            if(check_block(n,m+1,style)==0)
                break;
            if(bioskey(1))              /*等待按键按下*/
            {
                key=bioskey(0);
                change(&n,&m,key);
            }
            if(check_block(n,m+1,style)==0)
                break;
            draw_block(n,m,style,0);
            m++;
            draw_block(n,m,style,1);
            if(speed!=1)                              /*说明没有按下下落键*/
            {
                 for(k=0;k<=4;k++)                 /*为了循环检测按键*/
                 {
                    if(bioskey(1))
                    {
                        key=bioskey(0);
                        change(&n,&m,key);
                    }
                    else
                        delay(100);
                 }
            }
            else
            {
                speed=0;
                delay(10);
            }
            if(m>=21)
                break;
        }
        for(i=0;i<=6;i+=2)                           /*对方块中的每一个方块在游戏版中的位置赋值*/
            board[m+shapes[style].xy[i+1]-4][n+shapes[style].xy[i]+5]=shapes[style].gen_color;
        
        kill_line(m);
        draw_block(STARTX1,STARTY1,style_next,0);/*把预览涂黑*/
        style=style_next;                                     /*把预览的种类赋值给游戏版中要显示的种类*/
        gameover(&n,&m,style);                           /*判断游戏是否结束*/
    }
}

默认分类 | 阅读 746 次
文章评论,共0条
游客请输入验证码
浏览51134次
文章分类