1. 程式人生 > >C++藉助curses庫實現俄羅斯方塊

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