• C++借助curses库实现俄罗斯方块


    主要要实现如下几个功能:方块的移动控制、方块变形、判定方块是否接触边界和进行方块堆积、对方块进行消除。

    1.方块的移动控制
    上下左右四个方向
    上-->变形,下-->加速下落,左-->向左移动,右-->向右移动
    注意在移动的时候,还要判定是否接触边界,特别是向下移动,除了需要确定是否接触底部边界外,还要注意是否发生方块堆积。

      1 void Piece::show(){
      2     fd_set set;
      3     FD_ZERO(&set);
      4     FD_SET(0, &set);
      5     struct timeval timeout;
      6     timeout.tv_sec = 0;
      7     timeout.tv_usec= 500000;
      8     if (select(1, &set, NULL, NULL, &timeout) == 0){
      9         //mvwprintw(game_win,21,20,"+");
     10         pos_x++;
     11         if(reachBottom()){
     12             pos_x--;
     13             int x=10;
     14             for(int i=0;i<shape_x;i++){
     15                 for(int j=0;j<shape_y;j++){
     16                     if(shape[i][j]==1){
     17                         map[pos_x+i+1][pos_y+j+1]=1;
     18                         mvwaddch(game_win,pos_x+i+1,pos_y+j+1,'#');
     19                     }
     20                 }
     21             }
     22             pos_x=0;
     23             srand((int)time(0));
     24             pos_y=rand()%(map_y-2);
     25             while(pos_y==0){
     26                 pos_y=rand()%(map_y-2);
     27             }
     28             next_shape_id=rand()%7;
     29             //shape_id=3;
     30             nextShape();
     31             wrefresh(game_win);
     32             int flag=1;
     33             int lines=0;
     34             if(flag==1){
     35                 for(int i=map_x-3;i>=2;i--){
     36                     while(fullLine(i)){
     37                             lines++;
     38                             int k=i-1;
     39                             while(fullLine(k)){
     40                                 k--;
     41                                 lines++;
     42                             }
     43                             for(int j=0;j<(map_y-3);j++){
     44                                 map[k+2][j+1]=0;
     45                                 mvwaddch(game_win,k+2,j+1,' ');
     46                             }
     47                             int kk=k+1;
     48                             for(;kk>=2;kk--){
     49                                 for(int jj=0;jj<(map_y-3);jj++){
     50                                     if(map[kk][jj+1]==1){
     51                                         map[kk+1][jj+1]=1;
     52                                         mvwaddch(game_win,kk+1,jj+1,'#');
     53                                     }else{
     54                                         map[kk+1][jj+1]=0;
     55                                         mvwaddch(game_win,kk+1,jj+1,' ');
     56                                     }
     57                                 }
     58                             }
     59                             score+=(lines*10);
     60                             std::string tempS;
     61                             std::ostringstream ex_msg;
     62                             ex_msg<<"score: "<<score;
     63                             tempS=ex_msg.str();
     64                             mvwprintw(score_win,5,5,tempS.c_str());
     65                             wrefresh(score_win);
     66                             //mvwaddch(game_win,k+1,j,' ');
     67                             wrefresh(game_win);
     68                     }
     69                 }
     70             }
     71         }else{
     72             //mvwprintw(game_win,21,20,"-");
     73             for(int i=3;i>=0;i--){
     74                 for(int j=3;j>=0;j--){
     75                     if(shape[i][j]==1){
     76                         int x=11;
     77                         mvwaddch(game_win,pos_x+i,pos_y+1+j,' ');
     78                         mvwaddch(game_win,pos_x+i+1,pos_y+1+j,'#');
     79                     }
     80                 }
     81             }
     82             wrefresh(game_win);
     83         }
     84     }
     85     if(FD_ISSET(0,&set)){
     86         while((key=getch())==-1);
     87 
     88         if(key==KEY_RIGHT){
     89             //clearShape();
     90             pos_y++;
     91             if(reachBottom()){
     92                 pos_y--;
     93             }else{
     94                 for(int i=0;i<=3;i++){
     95                     for(int j=3;j>=0;j--){
     96                         if(shape[i][j]==1){
     97                             //列上的移动
     98                             mvwaddch(game_win,pos_x+i+1,pos_y+j,' ');
     99                             mvwaddch(game_win,pos_x+i+1,pos_y+j+1,'#');
    100                         }
    101                     }
    102                 }
    103                 wrefresh(game_win);
    104             }
    105         }
    106 
    107         if(key==KEY_LEFT){
    108             //clearShape();
    109             pos_y--;
    110             if(reachBottom()){
    111                 pos_y++;
    112             }else{
    113                 for(int i=0;i<=3;i++){
    114                     for(int j=0;j<=3;j++){
    115                         if(shape[i][j]==1){
    116                             //列上的移动
    117                             mvwaddch(game_win,pos_x+i+1,pos_y+j+2,' ');
    118                             mvwaddch(game_win,pos_x+i+1,pos_y+j+1,'#');
    119                         }
    120                     }
    121                 }
    122                 wrefresh(game_win);
    123             }
    124         }
    125 
    126         if(key==KEY_UP){
    127             changeShape();
    128         }
    129         if(key==KEY_DOWN){
    130             pos_x++;
    131             if(reachBottom()){
    132                 pos_x--;
    133             }else{
    134                 for(int i=3;i>=0;i--){
    135                     for(int j=3;j>=0;j--){
    136                         if(shape[i][j]==1){
    137                             int x=11;
    138                             mvwaddch(game_win,pos_x+i,pos_y+1+j,' ');
    139                             mvwaddch(game_win,pos_x+i+1,pos_y+1+j,'#');
    140                         }
    141                     }
    142                 }
    143                 wrefresh(game_win);
    144             }
    145         }
    146     }
    147 }

    2.方块变形
    做法很简单,首先,4x4整体按左右对称,再交换方块实际长和宽的值,在实际的长和宽这个范围内再进行左右对称。
    同样这里要注意是否发生了越界和方块堆积,如果发生了,就恢复原形状。

     1 void Piece::changeShape(){
     2     int temp[4][4]={0};
     3     int temp1[4][4]={0};
     4     int temp2[4][4]={0};
     5     for(int i=0;i<4;i++){
     6         for(int j=0;j<4;j++){
     7             temp[j][i]=shape[i][j];
     8             temp2[i][j]=shape[i][j];//保存shape数组
     9         }
    10     }
    11     for(int i=0;i<4;i++){
    12         for(int j=0;j<4;j++)
    13             shape[i][j]=0;
    14     }
    15     int temp3=shape_x;
    16     shape_x=shape_y;
    17     shape_y=temp3;
    18     for(int i=0;i<shape_x;i++){
    19         for(int j=0;j<shape_y;j++){
    20             temp1[i][shape_y-1-j]=temp[i][j];
    21         }
    22     }
    23     for(int i=0;i<4;i++){
    24         for(int j=0;j<4;j++)
    25             shape[i][j]=temp1[i][j];
    26     }
    27     if(reachBottom()){
    28         for(int i=0;i<4;i++){
    29             for(int j=0;j<4;j++)
    30                 shape[i][j]=temp2[i][j];
    31         }
    32         int temp3=shape_x;
    33         shape_x=shape_y;
    34         shape_y=temp3;
    35     }else{
    36         for(int i=0;i<4;i++){
    37             for(int j=0;j<4;j++){
    38                 if(temp2[i][j]==1){
    39                     mvwaddch(game_win,pos_x+i+1,pos_y+1+j,' ');
    40                 }
    41             }
    42         }
    43         wrefresh(game_win);
    44         for(int i=3;i>=0;i--){
    45             for(int j=3;j>=0;j--){
    46                 if(shape[i][j]==1){
    47                     mvwaddch(game_win,pos_x+i+1,pos_y+1+j,'#');
    48                     wrefresh(game_win);
    49                 }
    50             }
    51         }
    52     }
    53 }

    3.判定方块是否接触边界和进行方块堆积
    这里主要是要考虑到,左右上下类似装饰条的行。方块堆积就是判定下一行方块要占据的位置是否已经有其他方块占据了。

     1 bool Piece::reachBottom(){
     2     for(int i=0;i<shape_x;i++){
     3         for(int j=0;j<shape_y;j++){
     4             if(shape[i][j]==1){
     5                 if(pos_x+i>(map_x-3)){
     6                     return true;
     7                 }
     8                 if(pos_y+j>(map_y-3)||pos_y+j<0){
     9                     return true;
    10                 }
    11                 if(map[pos_x+i+1][pos_y+j+1]==1){
    12                     return true;
    13                 }
    14             }
    15         }
    16     }
    17     return false;
    18 }

    4.对方块进行消除
    从最后一行放置方块的行号开始,依次判定此行是否需要消除,消除后还要继续判定本行的情况(应对连续消除多行的情况)。

     1 for(int i=map_x-3;i>=2;i--){
     2                     while(fullLine(i)){
     3                             lines++;
     4                             int k=i-1;
     5                             while(fullLine(k)){
     6                                 k--;
     7                                 lines++;
     8                             }
     9                             for(int j=0;j<(map_y-3);j++){
    10                                 map[k+2][j+1]=0;
    11                                 mvwaddch(game_win,k+2,j+1,' ');
    12                             }
    13                             int kk=k+1;
    14                             for(;kk>=2;kk--){
    15                                 for(int jj=0;jj<(map_y-3);jj++){
    16                                     if(map[kk][jj+1]==1){
    17                                         map[kk+1][jj+1]=1;
    18                                         mvwaddch(game_win,kk+1,jj+1,'#');
    19                                     }else{
    20                                         map[kk+1][jj+1]=0;
    21                                         mvwaddch(game_win,kk+1,jj+1,' ');
    22                                     }
    23                                 }
    24                             }
    25                             score+=(lines*10);
    26                             std::string tempS;
    27                             std::ostringstream ex_msg;
    28                             ex_msg<<"score: "<<score;
    29                             tempS=ex_msg.str();
    30                             mvwprintw(score_win,5,5,tempS.c_str());
    31                             wrefresh(score_win);
    32                             //mvwaddch(game_win,k+1,j,' ');
    33                             wrefresh(game_win);
    34                     }
    35                 }

    完整代码:https://github.com/JsonZhangAA/shiyanlou/tree/master/C%2B%2B_%E4%BF%84%E7%BD%97%E6%96%AF%E6%96%B9%E5%9D%97

  • 相关阅读:
    lnmp vhost 虚拟目录配置
    vi 编辑器常用命令(转)
    centos7 nginx 加入开机启动
    centos7 编译安装mysql
    IE8以下支持css3 border-radius渲染方法
    html5 web 摇一摇切换歌曲
    L0、L1与L2范数
    c++多线程编程:常见面试题
    核函数以及SVM相关知识(重点)
    梯度下降法的三种形式BGD、SGD以及MBGD
  • 原文地址:https://www.cnblogs.com/JsonZhangAA/p/9935992.html
Copyright © 2020-2023  润新知