C++借助curses库实现俄罗斯方块
2018-11-12 06:48:27来源:博客园 阅读 ()
主要要实现如下几个功能:方块的移动控制、方块变形、判定方块是否接触边界和进行方块堆积、对方块进行消除。
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
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
下一篇:NOIP游记 Day0
- C++ 转换函数搭配友元函数 2020-06-10
- C++ 自动转换和强制类型转换(用户自定义类类型) 2020-06-10
- C++ rand函数 2020-06-10
- C++ 友元函数 2020-06-10
- C++ 运算符重载 2020-06-10
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash