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