红联Linux门户
Linux帮助

俄罗斯方块Linux版

发布时间:2016-01-07 15:56:00来源:linux网站作者:sduzh9011

用了大概三天时间用C语言加ncurses.h库在Linux下面写了一个简易的俄罗斯方块,还有很多地方可以完善,不过不打算写了。运行效果如下:

俄罗斯方块Linux版

用方向键控制方块的移动,向上变换形状,ESC退出。

写之前参考了一本书上的方块等的数据结构定义(书名我真的忘了,好像叫《C语言项目实践……》)。


main.c 文件:
    /*

***************************
    * Copyright(C):
    * Filename    :
    * Author      :
    * Version     :
    * Date        :
    * Description :
****************************
    */ 
     
    #include <stdlib.h> 
    #include <time.h> 
    #include <unistd.h> 
    #include <sys/time.h> 
    #include <signal.h> 
    #include <ncurses.h> 
    #include "colors.h" 
    #include "tetris.h" 
    #include "shapes.h" 
     
    #define MAX(a,b)      ((a)>(b)?(a):(b)) 
    #define MIN(a,b)      ((a)<(b)?(a):(b)) 
     
    /*---------------------CONSTS--------------------------*/ 
     
    #define MYKEY_ESC          27    
    /* 每个Block在Y和X方向占用字符数 */ 
    #define BLOCK_CHARS_Y       4                                                                            
    #define BLOCK_CHARS_X       8 
    /* Window左上角X Y 坐标 */ 
    #define WINDOW_ORGN_X      10 
    #define WINDOW_ORGN_Y      5 
    /* Window在X和Y方向可以容纳的Block数 */ 
    #define WINDOW_BLOCKS_Y    8 
    #define WINDOW_BLOCKS_X    5     /* 这个值应尽量是奇数,保证新的Block从中间出现 */ 
    /* Window的字符宽度和长度 */ 
    #define WINDOW_HEIGHT      (WINDOW_BLOCKS_Y * BLOCK_CHARS_Y +2) 
    #define WINDOW_WIDTH       (WINDOW_BLOCKS_X * BLOCK_CHARS_X +2) 
    /* 子窗口大小 要至少可以容纳一个方块大小*/ 
    #define SUBWND_HEIGHT      WINDOW_HEIGHT     
    #define SUBWND_WIDTH       (BLOCK_CHARS_X*5/2) 
    /* 子窗口显示位置(左上角坐标) */ 
    #define SUBWND_ORGN_X      (WINDOW_ORGN_X+WINDOW_WIDTH) 
    #define SUBWND_ORGN_Y      (WINDOW_ORGN_Y) 
    /* _board_table数组大小 */ 
    #define BOARD_TABLE_X      (WINDOW_BLOCKS_X*4) 
    #define BOARD_TABLE_Y      (WINDOW_BLOCKS_Y*4) 
    /* 新的Block出现时的X Y坐标 */ 
    #define BLOCK_INIT_X       (1+BLOCK_CHARS_X*((WINDOW_BLOCKS_X)/2));  
    #define BLOCK_INIT_Y       1 
    /* 每消除一行增加的分数 */ 
    #define SCORE_ADD_PERLINE    100 
    /* 每升一级需要的分数 */ 
    #define SCORE_PERLEVEL       1000  
     
    /*--------- GLOBAL VARIABLES DECLARATION----------------*/ 
     
    static int _block_x;           /* 方块左上角x坐标 */ 
    static int _block_y;           /* 方块左上角y坐标 */ 
    static int _block_index;   
    static int _block_next; 
    static int _table_shape_curr[4][4]; 
    static int _table_shape_next[4][4]; 
     
    static int _line_noneempty_min; 
     
    static int _flag_new;          /* 新方块产生标志 */  
    static int _flag_done;         /* 游戏结束标志 */ 
    static int _time_down;         /* 方块下降时间,ms */ 
     
    static int _window_height; 
    static int _window_width; 
     
    static short _bg_color;        /* 背景颜色 */ 
    static short _fg_color;        /* 前景颜色 */ 
     
    static WINDOW *_pwindow;        
    static WINDOW *_subwnd; 
    static struct BOARD _board_table[ BOARD_TABLE_Y ][ BOARD_TABLE_X ]; 
     
    static int _level_max;                /* 最大等级 */ 
    static int _level_cur;                /* 当前等级 */ 
    static unsigned int _score;           /* 分数 */ 
     
    static int _table_downtime[ ] = { /* 每个等级对应的下降时间,ms */ 
        500,450,400,350,300,250,200,250,100,50,20 
    }; 
     
    static const unsigned char _arrow_up[5][5] = { 
        {0,0,1,0,0}, 
        {0,1,1,1,0}, 
        {0,0,1,0,0}, 
        {0,0,1,0,0}, 
        {0,0,1,0,0}, 
    }; 
     
    static const unsigned char _arrow_right[5][5] = { 
        {0,0,0,0,0}, 
        {0,0,0,1,0}, 
        {1,1,1,1,1}, 
        {0,0,0,1,0}, 
        {0,0,0,0,0}, 
    }; 
     
    static const unsigned char _arrow_left[5][5] = { 
        {0,0,0,0,0}, 
        {0,1,0,0,0}, 
        {1,1,1,1,1}, 
        {0,1,0,0,0}, 
        {0,0,0,0,0}, 
    }; 
     
    static const unsigned char _arrow_down[5][5] = { 
        {0,0,1,0,0}, 
        {0,0,1,0,0}, 
        {0,0,1,0,0}, 
        {0,1,1,1,0}, 
        {0,0,1,0,0}, 
    }; 
    /*----------FUNCTION DECLARATION----------------------*/ 
     
    void    CalBlockShape(int index, int buf[4][4]); 
    void    Change(void); 
    int     CearFullLines(void); 
    int     Collision(void); 
    WINDOW *CreateNewWindow(int height, int weight, int y, int x); 
    void    CreateSquare(WINDOW *win, int y, int x); 
    void    DrawArrow(const unsigned char arrow[5][5], int y, int x ); 
    void    DrawBackground(int l); 
    void    DrawNext(WINDOW *win,int y,int x); 
    void    DrawShape(WINDOW *win, int index, int table_shape[4][4], int tl_y, int tl_x); 
    void    DrawSquare(WINDOW *win, int y, int x); 
    int     HasFullLine(int start, int end, int *fullline); 
    void    InitNcurses(void); 
    void    Initial(void); 
    int     LeftBorder(void); 
    int     MaxRight(void); 
    int     MinLeft(void); 
    void    OnAlarm(int p); 
    void    OnColor(WINDOW *win, int index); 
    void    OffColor(WINDOW *win, int index); 
    void    RandomBlock(void); 
    int     RightBorder(void); 
    void    ShowInfo(WINDOW *win); 
    void    UpdateBackground(int y, int x); 
     
    /* main */ 
    int main(int argc, char**argv){ 
        int ch = 0; 
        int quit = 0; 
        struct itimerval tick; 
         
        int max_x, max_y; 
     
        Initial(); 
        InitNcurses(); 
         
        getmaxyx(stdscr,max_y,max_x); 
        if ( max_x < WINDOW_ORGN_X+WINDOW_WIDTH+SUBWND_WIDTH+5 ||  
             max_y < WINDOW_ORGN_Y+WINDOW_HEIGHT+2 ){ 
            addstr("your screen is to small! press any key to quit!"); 
            getch(); 
            endwin(); 
            exit(1); 
        } 
     
        curs_set(0);    /* 隐藏光标 */ 
     
        _pwindow = CreateNewWindow(WINDOW_HEIGHT, 
                                   WINDOW_WIDTH, 
                                   WINDOW_ORGN_Y, 
                                   WINDOW_ORGN_X 
                                   ); 
        wattron(_pwindow,A_REVERSE);  /* 反白显示 */ 
     
        _subwnd = CreateNewWindow(SUBWND_HEIGHT, 
                                  SUBWND_WIDTH, 
                                  SUBWND_ORGN_Y, 
                                  SUBWND_ORGN_X 
                                  ); 
        wattron(_subwnd,A_REVERSE); /* 反白显示 */ 
     
        attron(COLOR_PAIR(7)); 
        mvaddstr(0,1,"Press ESC to quit"); 
        mvaddstr(1,1,"Press Up to change"); 
        mvaddstr(2,1,"Press Arrows to move"); 
        attroff(COLOR_PAIR(7)); 
        refresh(); 
         
        signal(SIGALRM,OnAlarm); 
        tick.it_value.tv_sec = _time_down/1000; 
        tick.it_value.tv_usec = 1000*(_time_down%1000); 
     
        tick.it_interval.tv_sec = _time_down/1000; 
        tick.it_interval.tv_usec = 1000*(_time_down%1000); 
     
        setitimer(ITIMER_REAL, &tick, NULL); 
     
        while( 1 ){ /* press ESC to quit*/ 
     
            switch( ch=getch() ){ 
            case KEY_LEFT :                 /* 左移 */ 
                if ( !MinLeft() ) 
                    _block_x = _block_x-2;  /* 注意这里不是减1 */ 
                break; 
            case KEY_RIGHT :                /* 右移 */      
                if ( !MaxRight() ) 
                    _block_x = _block_x+2;  /* 注意这里不是加1 */ 
                break; 
            case KEY_DOWN :                 /* 向下 */ 
                while( !Collision() ) 
                    _block_y = _block_y+1;  
                break; 
            case KEY_UP :                   /* 变形 */ 
                Change(); 
                break; 
            case MYKEY_ESC :                /* 退出 */ 
                quit = 1; 
                break; 
            } 
             
            if ( quit != 0 )  /* 推出游戏 */ 
                break; 
             
            werase(_pwindow); /* 用werase() 用wclear()屏幕会闪烁 */ 
            DrawShape(_pwindow, _block_index, _table_shape_curr, _block_y, _block_x); 
            DrawBackground(_line_noneempty_min); 
            box(_pwindow,'|','-'); 
            wrefresh(_pwindow); 
        } 
        delwin(_pwindow); 
        delwin(_subwnd); 
        endwin(); 
        return 0; 
    }; 
     
    void CalBlockShape(int index, int buf[4][4]){ 
        int i; 
        unsigned int value; 
         
        value = (_shapes[index].box[0]<<8)|(_shapes[index].box[1]); 
         
        for (i=0; i<4; i++){ 
            buf[0][i] = (value&(1U<<(15-i)))!=0 ? 1:0; 
            buf[1][i] = (value&(1U<<(11-i)))!=0 ? 1:0; 
            buf[2][i] = (value&(1U<<(7-i )))!=0 ? 1:0; 
            buf[3][i] = (value&(1U<<(3-i )))!=0 ? 1:0; 
        }        
    } 
     
    /*******************************************
    * Change();
    * 如果满足变形的条件则变换形状
    * Input : NONE
    * Output: NONE
    * Return: 可以变形返回 1,不可以返回 0
    *-------------------------------------------
    * 备注:判断依据是变形之后是否有部分方块在
    * 右边界之外(不可能从左边界出去)
    *******************************************/ 
    void Change(void){ 
        int tmp_index; 
     
        /* 如果已经到底,不能变形 */ 
        if ( Collision() ) 
            return; 
     
        tmp_index = _block_index;    
        _block_index = _shapes[_block_index].next; 
        CalBlockShape(_block_index,_table_shape_curr); 
     
        /* 有可能发生碰撞 */ 
        if ( _block_x+8 > WINDOW_WIDTH-2 ){  
            _block_x = _block_x-2; 
            if ( RightBorder() ){ 
                _block_x = _block_x+2; 
                _block_index = tmp_index; 
                CalBlockShape(_block_index,_table_shape_curr); 
                return; 
            } 
            _block_x = _block_x+2; 
            return; 
        } 
    } 
     
    int ClearFullLines(void){ 
        int i, j; 
        int end = BOARD_TABLE_Y-1; 
        int start = _line_noneempty_min; 
        int fullline; 
        int cnt=0; 
        while( HasFullLine(start,end,&fullline) ){ 
            for ( i=fullline; i>=_line_noneempty_min && i>=1; i-- ){ 
                for( j=0; j<BOARD_TABLE_X; j++ ){ 
                    _board_table[i][j] = _board_table[i-1][j]; 
                } 
            } 
            _line_noneempty_min++; /* 注意这里不是减奥 */ 
            end = fullline; 
            start = _line_noneempty_min; 
            cnt++; 
        } 
        return cnt; /* 返回清除的行数 */ 
    } 
     
    int Collision(void){ 
        int i, j, x,y; 
     
        x = (_block_x-1)/2; 
        y = (_block_y-1)/1; 
        for (i=0; i<4 && y<BOARD_TABLE_Y; i++ ){ 
            for (j=0; j<4 && x<BOARD_TABLE_X; j++){ 
                if (_table_shape_curr[i][j] != 0 && 
                    _board_table[y+1][x].value != 0  
                    ) 
                    return 1; 
                x++; 
            } 
            if ( i<3 && 
                 _table_shape_curr[i+1][0] == 0 && 
                 _table_shape_curr[i+1][1] == 0 && 
                 _table_shape_curr[i+1][2] == 0 && 
                 _table_shape_curr[i+1][3] == 0 
                 ) 
                break; 
     
            if ( i == 3) 
                break; 
            x = (_block_x-1)/2; 
            y++; 
        } 
        if ( y+1 >= WINDOW_BLOCKS_Y*BLOCK_CHARS_Y ) /* 到底了 */ 
            return 1; 
        return 0; 
    } 
  
    WINDOW *CreateNewWindow(int height, int weight, int y, int x){ 
        WINDOW *pwin = newwin(height, weight, y, x); 
        box(pwin,'|','-'); 
        wrefresh(pwin); 
         
        return pwin; 
    } 
     
    void DrawArrow(const unsigned char arrow[5][5], int y, int x ){ 
        int i,j; 
        int x0 = x; 
        for ( i=0; i<5; i++ ){ 
            for ( j=0; j<5; j++ ){ 
                if ( arrow[i][j] ) 
                    mvaddch(y,x,'|'); 
                x++; 
            } 
            x = x0; 
            y++; 
        } 
    } 
     
    void DrawBackground(int line){ 
        int i, j; 
        int r_x, r_y; 
     
        r_x = 1; 
        r_y = line+1; 
        for ( i=line; i<BOARD_TABLE_Y; i++ ){ 
            for ( j=0; j<BOARD_TABLE_X; j++ ){ 
                if ( _board_table[i][j].value != 0 ){ 
                    OnColor(_pwindow, _board_table[i][j].color); 
                    DrawSquare(_pwindow,r_y,r_x); 
                    OffColor(_pwindow,_board_table[i][j].color); 
                } 
                r_x+=2; 
            } 
            r_x = 1; 
            r_y += 1; 
        } 
    } 
     
     
    void DrawSquare(WINDOW *win,int y, int x){ 
        if ( win == NULL ) 
            win = stdscr; 
     
        mvwaddch(win,y,x,'['); 
        mvwaddch(win,y,x+1,']'); 
    } 
     
     
    void DrawShape(WINDOW *win, int index, int table_shape[4][4], int tl_y, int tl_x){ 
        int i, j, y, x; 
        y = tl_y; 
        x = tl_x; 
         
        if ( win == NULL ) 
            win = stdscr; 
     
        OnColor(win, _shapes[index].color_id); 
     
        for (i=0; i<4; i++){ 
            for (j=0; j<4; j++){ 
                if( table_shape[i][j] != 0 ) 
                    DrawSquare(win,y,x); 
                x+=2; 
            } 
            x = tl_x; 
            y++; 
        } 
        OffColor(win, _shapes[index].color_id);  
    } 
     
     
    int HasFullLine(int start, int end,  int *fullline){ 
        int i, j; 
     
        if ( start<0 || end>BOARD_TABLE_Y-1 ) 
            return 0; 
     
        /* 从下往上找,一旦找到便退出 */ 
        for ( i=end; i>=start; i-- ){ 
            for ( j=0; j<BOARD_TABLE_X; j++ ){ 
                if ( _board_table[i][j].value == 0 ) 
                    break; 
            } 
            if ( j == BOARD_TABLE_X ){ 
                *fullline = i; 
                return 1; 
            } 
        } 
        return 0; 
    } 
     
     
    int LeftBorder(void){ 
        if ( _block_x <= 1 ){ 
            if ( _shapes[_block_index].box[0] & 0x88 ||  
                 _shapes[_block_index].box[1] & 0x88   
                 ) 
                return 1; 
            else 
                return 0; 
        } 
        return 0; 
    } 
     
     
    int MaxRight(void){ 
        int i,j; 
        int x,y; 
        if ( RightBorder() ) 
            return 1; 
         
        y = (_block_y-1)/1; 
        for ( i=0; i<4 && y<BOARD_TABLE_Y && y>=0; i++ ){ 
            x = (_block_x-1)/2+3; 
            for ( j=3; j>=0 && x+1<BOARD_TABLE_X && x+1>=0; j-- ){ 
                if ( _table_shape_curr[i][j] != 0 ){ 
                    if ( _board_table[y][x+1].value != 0 ) 
                        return 1; 
                    else 
                        break; 
                } 
                x--; 
            } 
            y++; 
        } 
     
        return 0; 
    } 
 
    int MinLeft(void){ 
        int i,j; 
        int x,y; 
        if ( LeftBorder() ) 
            return 1; 
     
        x = (_block_x-1)/2; 
        y = (_block_y-1)/1; 
        for ( i=0; i<4 && y<BOARD_TABLE_Y && y>=0; i++ ){ 
            for ( j=0; j<4 && x-1<BOARD_TABLE_X && x-1>=0; j++ ){ 
                if ( _table_shape_curr[i][j] != 0 ){ 
                    if ( _board_table[y][x-1].value != 0 ) 
                        return 1; 
                    else 
                        break; 
                } 
                x++; 
            } 
            x = (_block_x-1)/2; 
            y++; 
        } 
     
        return 0; 
    } 
  
    void OnColor(WINDOW *win, int index){ 
        if ( win == NULL ) 
            win = stdscr; 
     
        switch( index ){ 
        case 1 : 
            wattron(win,COLOR_PAIR(1)); 
            break; 
        case 2 : 
            wattron(win,COLOR_PAIR(2)); 
            break; 
        case 3 : 
            wattron(win,COLOR_PAIR(3)); 
            break; 
        case 4 : 
            wattron(win,COLOR_PAIR(4)); 
            break; 
        case 5 : 
            wattron(win,COLOR_PAIR(5)); 
            break; 
        case 6 : 
            wattron(win,COLOR_PAIR(6)); 
            break; 
        case 7 : 
            wattron(win,COLOR_PAIR(7)); 
            break; 
        default:     
            break; 
        } 
    } 
 
    void OffColor(WINDOW *win, int index){ 
        if ( win == NULL ) 
            win = stdscr; 
     
        switch( index ){ 
        case 1 : 
            wattroff(win,COLOR_PAIR(1)); 
            break; 
        case 2 : 
            wattroff(win,COLOR_PAIR(2)); 
            break; 
        case 3 : 
            wattroff(win,COLOR_PAIR(3)); 
            break; 
        case 4 : 
            wattroff(win,COLOR_PAIR(4)); 
            break; 
        case 5 : 
            wattroff(win,COLOR_PAIR(5)); 
            break; 
        case 6 : 
            wattroff(win,COLOR_PAIR(6)); 
            break; 
        case 7 : 
            wattroff(win,COLOR_PAIR(7)); 
            break; 
        default:     
            break; 
        } 
    } 
 
    void OnAlarm(int p){ 
        int lines = 0; 
         
        if ( _flag_done != 0 ){ 
            return; 
        } 
     
        if ( _flag_new!=0 ){ 
            _flag_new = 0; 
            RandomBlock(); 
            ShowInfo(_subwnd); 
        }else if ( !Collision() ){ 
            _block_y++; 
        }else{ 
            if ( _block_y <= BLOCK_INIT_Y ) 
                _flag_done = 1; 
            UpdateBackground(_block_y,_block_x); 
            _flag_new = 1; 
        }    
        werase(_pwindow); 
        DrawShape(_pwindow,_block_index, _table_shape_curr,_block_y,_block_x); 
        lines = ClearFullLines(); 
        DrawBackground(_line_noneempty_min); 
        box(_pwindow,'|','-'); 
     
        if ( lines ){ 
            _score += lines*SCORE_ADD_PERLINE; 
            _level_cur = MIN(_score/SCORE_PERLEVEL,_level_max); 
            ShowInfo(_subwnd); 
        } 
     
        wrefresh(_pwindow); 
        if ( _flag_done != 0 ){ 
            mvaddstr(WINDOW_ORGN_Y-1,WINDOW_ORGN_X,"Done!"); 
            wrefresh(stdscr); 
        } 
    } 
  
    void RandomBlock(void){ 
         
        _block_index = _block_next; 
        _block_y = BLOCK_INIT_Y; 
        _block_x = BLOCK_INIT_X; 
        CalBlockShape(_block_index,_table_shape_curr); 
        /* 随机产生下一个方块 */ 
        srand(time(NULL)); 
        _block_next = rand()%MAX_BOX; 
    } 
     
    int RightBorder(void){ 
        int i; 
        int x = (WINDOW_WIDTH-1-_block_x)/2-1; 
        if ( _block_x+8 >= WINDOW_WIDTH-1  ){ /* +8是因为x方向每个小方块占两个字符间距 */ 
            for (i=0;i<4;i++){ 
                if (_table_shape_curr[i][x] != 0 ) 
                    return 1; 
            } 
        } 
        return 0; 
    } 
     
    void ShowInfo(WINDOW *win){ 
        int x, y; 
        int i; 
        werase(win); 
        x = 1+SUBWND_WIDTH/2-BLOCK_CHARS_X/2; 
        y = 4; 
        DrawNext(win, y, x); 
     
        y += BLOCK_CHARS_Y+1; 
        for ( i=1; i<SUBWND_WIDTH-1; i++ ){ 
            mvwaddch(win,y,i,'-'); 
        } 
        wattroff(win,A_REVERSE);  /* 关闭反白 */ 
         
        y += 1; 
        mvwaddstr(win,y,x,"Next"); 
     
        y = SUBWND_HEIGHT/2; 
        x = SUBWND_WIDTH/10; 
        mvwprintw(win,y,x,"%s: %d","Score",_score); 
        y += 2; 
        mvwprintw(win,y,x,"%s: %d","Level",_level_cur); 
        y += 4; 
        mvwaddstr(win,y,x,"Version: V1.0.0"); 
        y += 1; 
        mvwaddstr(win,y,x,"Author : sduzh"); 
        wattron(win,A_REVERSE);  /* 打开反白 */ 
         
        box(win,'|','-'); 
        wrefresh(win); 
    } 
     
    void DrawNext(WINDOW *win, int y, int x){ 
         
        CalBlockShape(_block_next, _table_shape_next); 
        DrawShape(win, _block_next, _table_shape_next,y, x); 
    } 
     
     
    void Initial(void){ 
        int i,j; 
     
        srand(time(NULL)); 
        _block_next = rand()%MAX_BOX; 
     
        _bg_color = COLOR_BLACK; 
        _fg_color = COLOR_WHITE; 
        _block_x = BLOCK_INIT_X; 
        _block_y = BLOCK_INIT_Y; 
        _flag_new = 1; 
        _flag_done = 0; 
        _window_height = WINDOW_BLOCKS_Y*BLOCK_CHARS_Y+2; 
        _window_width  = WINDOW_BLOCKS_X*BLOCK_CHARS_X+2; 
        _line_noneempty_min = BOARD_TABLE_Y-1; 
     
        _score = 0; 
        _level_max = sizeof(_table_downtime)/sizeof(_table_downtime[0])-1; 
        _level_cur = 0; 
        _time_down = _table_downtime[_level_cur]; 
        for (i=0; i<BOARD_TABLE_Y; i++ ){ 
            for (j=1; j<BOARD_TABLE_X; j++){ 
                _board_table[ i ][ j ].value = 0; 
            } 
        } 
    } 
     
    void InitNcurses(void){ 
        initscr(); 
        start_color(); 
        init_pair(1, _tab_color[1], _bg_color); 
        init_pair(2, _tab_color[2], _bg_color); 
        init_pair(3, _tab_color[3], _bg_color); 
        init_pair(4, _tab_color[4], _bg_color); 
        init_pair(5, _tab_color[5], _bg_color); 
        init_pair(6, _tab_color[6], _bg_color); 
        init_pair(7, _tab_color[7], _bg_color); 
        cbreak(); 
        nonl(); 
        noecho(); 
        intrflush(stdscr,FALSE); 
        keypad(stdscr,TRUE); 
    } 
     
    // x, y:发生碰撞时方块左上角x和y坐标 
    void UpdateBackground(int y, int x){ 
        int i,j; 
        int row, line; 
        short color = _shapes[_block_index].color_id; 
        /* 先将字符坐标x,y转换为在_board_table数组中对应的位置 */ 
        line = y-1; 
        row  = (x-1)/2; 
        for ( i=0; (i<4) && (line+i<BOARD_TABLE_Y); i++ ){ 
            for ( j=0; (j<4) && (row+j<BOARD_TABLE_X); j++ ){ 
                _board_table[line+i][row+j].value |= _table_shape_curr[i][j]; 
                if ( _table_shape_curr[i][j] != 0 ) 
                    _board_table[line+i][row+j].color = color; 
            } 
        } 
     
        _line_noneempty_min = MIN(line,_line_noneempty_min); 
    } 


tetris.h文件:

    #ifndef TEIRIS_H 
    #define TETRIS_H 
     
    /* Board */ 
    struct BOARD{ 
        int value; 
        int color; 
    }; 
     
    /* Shape */ 
    struct SHAPE{ 
    /*一个字节8位,每4位表示游戏方块中的一行,例如:
    box[0]=“0x88”,box[1]=“0xC0”表示:
    1000
    1000
    1100
    0000
    */ 
        unsigned char box[2]; 
        short color_id;  /* 每个方块的颜色索引 */ 
        int next;   /* 下个方块的编号 */ 
    }; 
    
    #endif /* TETRIS */ 


shapes.c文件:

    #include "tetris.h" 
    #include "shapes.h" 
     
    struct SHAPE  _shapes[MAX_BOX] = { 
    /*
    *  1     1 1 1   1 1       1
    *  1     1         1   1 1 1
    *  1 1             1
    */ 
        { {0x88,0xc0}, 1, 1 }, 
        { {0xe8,0x00}, 1, 2 }, 
        { {0xc4,0x40}, 1, 3 }, 
        { {0x2e,0x00}, 1, 0 }, 
     
    /*
    *    1   1       1 1  1 1 1
    *    1   1 1 1   1        1
    *  1 1           1    
    */ 
        { {0x44,0xc0}, 2, 5 }, 
        { {0x8e,0x00}, 2, 6 }, 
        { {0xc8,0x80}, 2, 7 }, 
        { {0xe2,0x00}, 2, 4 }, 
     
    /*
    *   1        1 1
    *   1 1    1 1
    *     1
    */ 
        { {0x8c,0x40}, 3, 9 }, 
        { {0x6c,0x00}, 3, 8 }, 
     
    /*
    *     1    1 1
    *   1 1      1 1
    *   1
    */ 
        { {0x4c,0x80}, 4, 11 }, 
        { {0xc6,0x00}, 4, 10 }, 
     
    /*
    *     1        1       1 1 1      1
    *   1 1 1      1 1       1      1 1
    *              1                  1      
    */ 
        { {0x4e,0x00}, 5, 13 }, 
        { {0x8c,0x80}, 5, 14 }, 
        { {0xe4,0x00}, 5, 15 }, 
        { {0x4c,0x40}, 5, 12 }, 
     
    /*
    *    1     1 1 1 1
    *    1
    *    1
    *    1
    */ 
        { {0x88,0x88}, 6, 17 }, 
        { {0xf0,0x00}, 6, 16 }, 
     
    /*
    *   1 1
    *   1 1
    */ 
        { {0xcc,0x00}, 7, 18 }, 
     
    }; 


shapes.h文件:

    #ifndef TETRIS_SHAPES_H 
    #define TETRIS_SHAPES_H 
     
    //#include "tetris.h" 
     
    #define MAX_BOX   19 
     
    extern struct SHAPE  _shapes[MAX_BOX]; 
     
    #endif  // TETRIS_SHAPES_H 


colors.c文件:

    #include "colors.h" 
     
    const short _tab_color[MAX_COLOR] = { 
        COLOR_BLACK, 
        COLOR_WHITE, 
        COLOR_CYAN, 
        COLOR_MAGENTA, 
        COLOR_YELLOW, 
        COLOR_BLUE, 
        COLOR_GREEN, 
        COLOR_RED, 
    }; 


colors.h文件:

    #ifndef TETRIS_COLORS_H 
    #define TETRIS_COLORS_H 
     
    #include <ncurses.h> 
     
    #define MAX_COLOR   8 
     
    extern const short  _tab_color[MAX_COLOR]; 
     
    #endif /* TETRIS_COLORS_H */