1 /********************************************
2 * 程序名称:MR.DUAN 的打砖块(KILL THE BLOCKS !)
3 * 作 者:WindAutumn <duanxu@outlook.com>
4 * 最后修改:2012-8-11-PM
5 * 版 本 号:1.0
6 *
7 *// 好像有个BUG。。。间歇性发作,可能是编译器问题吧,不管了。。。
8 *
9 * *****************************************/
10
11 #include<stdio.h>
12 #include<Windows.h>
13 #include<conio.h>
14
15 #define PI 3.1415926
16 #define LEFT 0
17 #define RIGHT34
18 #define UP 0
19 #define DOWN24
20 #define X_OFFSET 2
21 #define Y_OFFSET 1
22 #define BLOCK_MAP 0xffff// 砖块地图
23
24 unsigned short block[10]= {0};
25 char blocks[10][16]= {0};
26 int arm_head=10+X_OFFSET, arm_tail=18+X_OFFSET;
27
28 void HideCursor(HANDLE hBlock);
29 void GotoXY(HANDLE hBlock, int x, int y);
30 void InitScreen(HANDLE hBlock);
31 void GameStart();
32 void GameOver(HANDLE hBlock, int mode);
33 void PrintBlock(HANDLE hBlock);
34 void ChangeArm(HANDLE hBlock);
35 void PrintBall(HANDLE hBlock);
36 void KillBlock(HANDLE hBlock, int x, int y);
37
38 void main()
39 {
40 system("color 7b");// 默认颜色,白色底色
41 SetConsoleTitle("KILL THE BLOCKS !");// 设置控制台标题
42 GameStart();// 开始游戏
43 }
44
45 void GameStart()
46 {
47 int i;
48
49 HANDLE hBlock = GetStdHandle(STD_OUTPUT_HANDLE);
50 HideCursor(hBlock);// 隐藏光标
51 InitScreen(hBlock);// 初始化屏幕
52 for(i=0; i<10; i++)
53 block[i]=BLOCK_MAP;
54 PrintBlock(hBlock);// 绘制砖块地图
55
56 GotoXY(hBlock, arm_head, DOWN - 1);// 以下3行打印托盘
57 for(i=0; i<(arm_tail-arm_head)/2+1; i++)
58 printf("□");
59
60 PrintBall(hBlock);// 对小球的控制
61 }
62
63 void InitScreen(HANDLE hBlock)// 初始化屏幕
64 {
65 int i;
66 SetConsoleTextAttribute(hBlock, FOREGROUND_INTENSITY | FOREGROUND_BLUE | BACKGROUND_BLUE |BACKGROUND_GREEN | BACKGROUND_RED);
67 // 白的背景色,亮蓝色前景色
68 GotoXY(hBlock, 0, 0);
69 printf("╔");
70 for(i=1; i<RIGHT/2; i++)
71 printf("═");
72 //printf("%2d",i);
73 printf("╗");
74
75 for(i=1; i< DOWN; i++)
76 {
77 GotoXY(hBlock, 0, i);
78 //printf("%d",i);
79 printf("║");
80 GotoXY(hBlock, RIGHT, i);
81 printf("║");
82 }
83
84 GotoXY(hBlock, 0, DOWN);
85 printf("╚");
86 for(i=1; i<RIGHT/2; i++)
87 printf("═");
88 printf("╝");
89
90 GotoXY(hBlock, 0, 0);
91
92 }
93
94 void HideCursor(HANDLE hBlock)// 隐藏光标
95 {
96 CONSOLE_CURSOR_INFO cursor_info = {1, 0};
97 SetConsoleCursorInfo(hBlock, &cursor_info);
98 }
99
100 void GotoXY(HANDLE hBlock, int x, int y)
101 {
102 COORD coord;
103 coord.X = x;
104 coord.Y = y;
105 SetConsoleCursorPosition(hBlock, coord);
106 }
107
108 void PrintBlock(HANDLE hBlock)
109 {
110 int i,j;
111 for(i=0; i<10; i++)// 打印右侧数字视图
112 {
113 for(j=0; j<16; j++)
114 {
115 if(((block[i]<<j)&0x8000) == (unsigned short)0x8000)
116 blocks[i][j]=1;
117 else blocks[i][j]=0;
118 GotoXY(hBlock,50+j,i);
119 printf("%d",blocks[i][j]);
120 }
121 }
122 for(i=0; i<10; i++)// 打印砖块
123 {
124 for(j=0; j<16; j++)
125 {
126 if(blocks[i][j]==1)
127 {
128 GotoXY(hBlock,2+2*j,1+i);
129 printf("□");
130 }
131 }
132 }
133 }
134
135 void ChangeArm(HANDLE hBlock)
136 {
137 int key_direct=0;
138 if(_kbhit())
139 {
140 key_direct = getch();
141 if(key_direct == 'a'&&arm_head > LEFT+2)// 托盘往左走
142 {
143 arm_head -= 2;
144 GotoXY(hBlock, arm_head, DOWN-1);
145 printf("□");
146 GotoXY(hBlock, arm_tail, DOWN-1);
147 printf(" ");
148 arm_tail -= 2;
149 }
150 if(key_direct == 'd'&&arm_tail < RIGHT-2)// 托盘向右走
151 {
152 arm_tail += 2;
153 GotoXY(hBlock, arm_tail, DOWN-1);
154 printf("□");
155 GotoXY(hBlock, arm_head, DOWN-1);
156 printf(" ");
157 arm_head += 2;
158 }
159 }
160 }
161
162 void PrintBall(HANDLE hBlock)
163 {
164 int k,flag=0;
165 int x = (arm_head+arm_tail)/2, y =DOWN - 2;// 球的坐标
166 int tempx = x,tempy = y;
167 int degree =90;// 初始角度
168
169 GotoXY(hBlock, x, y);// 初始球坐标
170 printf("□");
171 while(1)
172 {
173 if(x == LEFT+2 || x == RIGHT-2)
174 degree = (degree<=180)?(180-degree):(540-degree);// 碰左右边的角度计算
175 if(y == UP+1)
176 degree = 360 - degree;// 碰上边的角度计算
177 if(y == DOWN-2)
178 {
179 if(!(x>=arm_head&&x<=arm_tail))// 没有碰上托盘的情况
180 GameOver(hBlock,0);// 失败
181 else if(degree > 180)
182 {
183 if(x == (arm_head+arm_tail)/2)
184 degree = 360 - degree;// 计算碰托盘之后角度
185 else
186 degree = 360 - degree + 15 * ((arm_head+arm_tail)/2 - x);
187 }
188
189 }
190 switch(degree)// 根据角度确定方块移动方向
191 {
192 case 360:
193 case 0:
194 case 30 :
195 tempx = x+2;
196 tempy = y-1;
197 break;
198 case 60 :
199 tempx = x+2;
200 tempy = y-1;
201 break;
202 case 90 :
203 tempx = x ;
204 tempy = y-1;
205 break;
206 case 120 :
207 tempx = x-2;
208 tempy = y-1;
209 break;
210 case 150 :
211 tempx = x-2;
212 tempy = y-1;
213 break;
214 case 180:
215 case 210 :
216 tempx = x-2;
217 tempy = y+1;
218 break;
219 case 240 :
220 tempx = x-2;
221 tempy = y+1;
222 break;
223 case 270 :
224 tempx = x ;
225 tempy = y+1;
226 break;
227 case 300 :
228 tempx = x+2;
229 tempy = y+1;
230 break;
231 case 330 :
232 tempx = x+2;
233 tempy = y+1;
234 break;
235 }
236
237 GotoXY(hBlock, tempx, tempy);// 下一个点在哪?
238 printf("□");
239 GotoXY(hBlock, x, y);// 消除上一个点
240 printf(" ");
241 x = tempx;
242 y = tempy;
243
244 ChangeArm(hBlock);
245 KillBlock(hBlock,x,y);
246 for(k=0; k<10; k++)// 如果每行非0就置flag为1
247 if(block[k]!=(unsigned short)0x0000)
248 flag=1;
249 if(flag==0)// 如果flag为0则游戏胜利
250 GameOver(hBlock,1);
251 flag=0;
252 GotoXY(hBlock,50,20);// 打印坐标,角度信息
253 printf("%3d,%2d,%2d",degree,x,y);
254 Sleep(100);// 暂停0.1s *********************important
255 }
256 }
257
258 void KillBlock(HANDLE hBlock, int x, int y)
259 {
260 int i,j;
261 unsigned short temp;
262 i=y-1;
263 j=(x-2)/2;
264 if(blocks[i][j] == 1)
265 {
266 blocks[i][j] = 0;
267 temp = ~(0x0001<<j);// 掩码
268 block[i]=block[i] & temp;// 将block信息与( 1111 1110 1111 1111 )进行与运算,消除bit位
269 GotoXY(hBlock,50+j,i);// 刷新右侧数字区
270 printf("0");
271 //GotoXY(hBlock,50,12+i);// 打印实时每行信息
272 //printf("%#x",block[j]);
273 }
274 }
275
276 void GameOver(HANDLE hBlock, int mode)
277 {
278 GotoXY(hBlock,50,15);
279 if(mode)
280 printf("you win");
281 else
282 printf("you loss");
283
284 getch();
285 exit(0);
286 }