经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C » 查看文章
C++借助curses库实现俄罗斯方块
来源:cnblogs  作者:张杨  时间:2018/11/9 17:12:22  对本文有异议

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

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

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

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

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

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

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

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

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号