欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-05-25 16:50:44
主要要实现如下几个功能:方块的移动控制、方块变形、判定方块是否接触边界和进行方块堆积、对方块进行消除。 1.方块的移动控制上下左右四个方向上-->变形,下-->加速下落,左-->向左移动,右-->向右移动注意在移动的时候,还要判定是否接触边界,特别是向下移动,除了需要确定是否接触底部边界外,还要注意 ......

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

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