⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 16.txt

📁 打球小游戏C语言源代码
💻 TXT
字号:
1 /*
  2  * Brick & Ball
  3  * by Jerry Fleming <jerryfleming2006@gmail.com>
  4  * 
  5  * This is a small game inspired from similar one in Motorola Mobile C289,
  6  * and my first REAL program in C :) Please tell me if you have a better
  7  * implementation or any suggestions.
  8  * 
  9  * HISTORY:
 10  * 2006-10-25: third (current) version with c language
 11  * 2006-10-01: second version with tkinter
 12  * 2006-04-19: first version with curses
 13  * 
 14  * TODO:
 15  * Nothing to do right now. :) If you have any ideas to improve or enhance it,
 16  * please contact me.
 17  */
 18 
 19 #include <stdio.h>
 20 #include <string.h>
 21 #include <ncurses.h>
 22 #include <stdlib.h>          /* for exit(), rand(), abs() */
 23 
 24 #include <stddef.h>          /* for NULL */
 25 #include <time.h>            /* for sleep() */
 26 #include <signal.h>          /* for SIGWINCH */
 27 
 28 #define NORMAL 1             /* status of game */
 29 #define PAUSE  2
 30 #define OVER   3
 31 #define QUIT   4
 32 #define BLOCK  1             /* color pairs */
 33 #define TXT    2
 34 #define BAR    3
 35 #define BALL   4
 36 #define CLEAR  5
 37 
 38 extern unsigned int sleep(unsigned int seconds);
 39 
 40 /*
 41  * globals 
 42  */
 43 int speed = 10;
 44 int cnt = 0;                 /* bricks yet remain on board */
 45 int score = 0;
 46 int level = 0;
 47 int width = 40;
 48 int height = 50;             /* for the board */
 49 short state = NORMAL;        /* see define */
 50 char *statestr = "Normal";   /* additional str to explain the game status */
 51 const int bw = 7;            /* brick width */
 52 const char brick[] = "       ";
 53 int bricks[100][3];
 54 int pad;
 55 int ball[2];
 56 int dir[2] = { 1, -1 };
 57 int ch = 0;                  /* user command */
 58 
 59 /*
 60 +-- 62 lines: * text strings -------------------------------------------------------------------------------------------------------------
122  */
123 
124 /*
125  * change sceen size, exit if too small 
126  */
127 void resizescr(int sig)
128 {
129     statestr = "Screen resized.";
130     getmaxyx(stdscr, height, width);
131 }                            /* resizescr()  */
132 
133 /*
134  * print msg on center of screen, exit on pressing Y or N (key is true) or any
135  * char (key false)
136  */
137 bool print_msg(char *msg, bool y_n_key, bool clearmsg)
138 {
139     char *rest;
140     char *str[30];
141     char emptystr[width];
142     int line = 0;
143     int i;
144     int length;
145     int left;
146     int top;
147     char delimiters[] = "\n";
148 
149     length = strlen(str[line] = strtok(msg, delimiters));
150     while ((rest = strtok(NULL, delimiters)) != NULL) {
151         line++;
152         if (length < strlen(rest))
153             length = strlen(rest);
154         str[line] = rest;
155     }
156 
157     top = (height - line) / 2;
158     left = (width - length) / 2;
159     attrset(COLOR_PAIR(TXT));
160     for (i = 0; i <= line; i++) {
161         mvprintw(top++, left, "%s", str[i]);
162     }
164     refresh();
165 
166     timeout(3000);
167     for (;;) {
168         ch = getch();
169         if (y_n_key)
170             break;
171         else {
172             if (ch == ERR || ch == 'y' || ch == 'Y') {
173                 ch = 'Y';
174                 break;
175             }
176             if (ch == 'n' || ch == 'N') {
177                 ch = 'N';
178                 break;
179             }
180         }
181     }
182 
183     if (clearmsg) {
184         top = (height - line) / 2;
185         attrset(COLOR_PAIR(CLEAR));
186         for (i = 0; i < width; i++)
187             emptystr[i] = ' ';
188         for (i = 0; i <= line; i++) {
189             mvaddstr(top++, 0, emptystr);
190         }
191         refresh();
192     }
193     i = ch, ch = 0;          /* clear input for later use */
194     timeout(100);
195 
196     if (i == 'N')
197         return FALSE;
198     return TRUE;
199 }                            /* print_msg()  */
200 
201 /*
202  * draw pad, ball, bricks, and bar together 
203  */
204 void draw_board(void)
205 {
206     int i, j;
207     char barstr[width];
208 
209     level++;
210     cnt = 0;
211     dir[0] = 1, dir[1] = -1;
212 
213     /* brick */
214     i = width % (bw + 1) / 2;   /* width -1 + gap */
215     j = 1;
216     attrset(COLOR_PAIR(BLOCK));
217     for (;;) {
218         mvaddstr(j, i, brick);
219         bricks[cnt][0] = i;
220         bricks[cnt][1] = j;
221         bricks[cnt][2] = 1;
222         i = i + bw + 1;
223         cnt++;
224         if (i >= width - bw) {
225             if (cnt > 50)
226                 break;
227             i = width % (bw + 1) / 2;
228             j += 2;
229         }
230     }
231     bricks[cnt][2] = -1;     /* mark the end or all bricks */
232 
233     if (level == 1) {
234         /* pad */
235         attrset(COLOR_PAIR(BLOCK));
236         pad = rand() % (width - bw - 1);
237         mvaddstr(height - 2, pad, brick);
238 
239         /* bar */
240         for (i = 0; i < width; i++)
241             barstr[i] = ' ';
242         attrset(COLOR_PAIR(BAR));
243         mvaddstr(height - 1, 0, barstr);
244         mvprintw(height - 1, 0, "SCORE: %03d  LEVEL: %d  STATE: %-9s", score,
245                  level, statestr);
246     }
247 
248     /* ball */
249     attrset(COLOR_PAIR(BALL));
250     ball[0] = pad, ball[1] = height - 3;
251     while (abs(ball[0] - pad) < 15)
252         ball[0] = rand() % (width - bw - 1);
253     mvaddstr(ball[1], ball[0], " ");
254 
255     refresh();
256 }                            /* draw_board()  */
257 
258 /*
259  * try to stop game 
260  */
261 void quit_game(const int ch)
262 {
263     if (ch == 'q') {
264         if (cnt < 0          /* do not want another level */
265             || (cnt > 0 && print_msg(tExit, FALSE, TRUE))   /* really meant to
266                                                              * exit */
267             ) {
268             state = QUIT;
269             statestr = "Quit game";
270         }
271     } else if (ch == 'o') {
272         state = OVER;
273         statestr = "Game over";
274         print_msg(tOver, TRUE, FALSE);
275     } else if (state == PAUSE) {
276         state = NORMAL;
277         statestr = "Normal";
278     } else {
279         state = PAUSE;
280         statestr = "Pause";
281     }
282     /* bar */
283     attrset(A_NORMAL | COLOR_PAIR(BAR));
284     mvprintw(height - 1, 0, "SCORE: %03d  LEVEL: %d  STATE: %-9s", score, level,
285              statestr);
286     refresh();
287 }                            /* quit_game()  */
288 
289 /*
290  * move the ball forward, turn if necessary, add scores, and quite if hit ground
291  */
292 void move_ball()
293 {
294     int i;
295 
296     if (state != NORMAL)
297         return;
298 
299     /* ball */
300     attrset(A_REVERSE | COLOR_PAIR(BALL));
301     mvaddstr(ball[1], ball[0], " ");
302     /* restore pad after hit */
303     attrset(A_NORMAL | COLOR_PAIR(BLOCK));
304     mvaddstr(height - 2, pad, brick);
305     ball[0] += dir[0], ball[1] += dir[1];
306     attrset(A_NORMAL | COLOR_PAIR(BALL));
307     mvaddstr(ball[1], ball[0], " ");
308 
309     /* change direction */
310     if (ball[1] < 0)
311         dir[1] = -dir[1];
312     if (ball[0] < 0 || ball[0] > width)
313         dir[0] = -dir[0];
314 
315     /* hit bricks */
316     attrset(A_REVERSE | COLOR_PAIR(BLOCK));
317     for (i = 0;; i++) {
318         if (bricks[i][2] == -1)
319             break;
320         if (bricks[i][2] == 0)
321             continue;
322         if (bricks[i][0] <= ball[0]
323             && bricks[i][0] + bw >= ball[0]
324             && bricks[i][1] == ball[1]
325             ) {
326             bricks[i][2] = 0;
327             /*
328              * tricky: make sure the direction is top-down
329              */
330             dir[1] = abs(dir[1]);
331             score += 10;
332             cnt--;
333             refresh();
334             mvaddstr(bricks[i][1], bricks[i][0], brick);
335             if (cnt <= 0) {  /* another level */
336                 if (print_msg(tGoon, FALSE, TRUE)) {
337                     draw_board();
338                 } else {
339                     quit_game('q');
340                 }
341             }
342         }
343     }
344 
345     /* hit pad */
346     if (ball[1] == height - 2) {
347         if (ball[0] < pad || ball[0] > pad + bw)
348             quit_game('o');
349         /*
350          * for some reason, the ball may enter the pad, and change dir will not
351          * get it out, so use abs() to turn back
352          */
353         dir[1] = -abs(dir[1]);
354         if (ball[0] == pad || ball[0] == pad + bw) {    /* on both ends */
355             dir[0] = -dir[0];
356         }
357     }
358 
359     /* bar */
360     attrset(A_NORMAL | COLOR_PAIR(BAR));
361     mvprintw(height - 1, 0, "SCORE: %03d  LEVEL: %d  STATE: %-9s", score, level,
362              statestr);
364     refresh();
365 }                            /* move_ball()  */
366 
367 /*
368  * move pad to left or right according to command 
369  */
370 int move_pad(const int ch)
371 {
372     int move;
373 
374     switch (ch) {
375         case KEY_LEFT:
376             move = -2;
377             break;
378         case KEY_RIGHT:
379             move = 2;
380             break;
381         case 'q':
382             quit_game(ch);
383             break;
384         case 'p':
385             quit_game(ch);
386             break;
387         default:
388             return 0;
389     }
390     attrset(A_REVERSE | COLOR_PAIR(BLOCK));
391     mvaddstr(height - 2, pad, brick);
392     pad = pad + move;
393     if (pad < 0)
394         pad = 0;
395     if (pad > width - bw)
396         pad = width - bw;
397     attrset(A_NORMAL | COLOR_PAIR(BLOCK));
398     mvaddstr(height - 2, pad, brick);
399 
400     refresh();
401     return 0;
402 }                            /* move_pad()  */
403 
404 /*
405  * main 
406  */
407 int main(void)
408 {
409     initscr();
410     start_color();
411     init_pair(BLOCK, COLOR_BLACK, COLOR_RED);   /* for bricks and pad */
412     init_pair(TXT, COLOR_CYAN, COLOR_BLACK);    /* for text strings */
413     init_pair(BAR, COLOR_WHITE, COLOR_BLUE);    /* for bar */
414     init_pair(BALL, COLOR_BLACK, COLOR_WHITE);  /* for ball */
415     init_pair(CLEAR, COLOR_BLACK, COLOR_BLACK); /* to clear objects */
416     noecho();
417     raw();                   /* disable line buffering */
418     timeout(100);
419     cbreak();
420     keypad(stdscr, TRUE);
421     curs_set(0);
422     getmaxyx(stdscr, height, width);
423     signal(SIGWINCH, resizescr);
425     if (height >= 20 && width >= 80) {
426         print_msg(tStart, TRUE, TRUE);
431         clear();
432         draw_board();
433         for (;;) {
434             ch = getch();
435             move_ball();
436             if (ch != ERR)
437                 move_pad(ch);
438             if (state == OVER || state == QUIT)
439                 break;
440         }
441     } else {                 /* screen too small, exit with complaint */
442         state = QUIT;
443         statestr = "Screen too small. Game aborted.";
444     }
445 
446     sleep(1), flash();
447     sleep(1), flash();
448     sleep(1), flash();
449     curs_set(1);
450     keypad(stdscr, FALSE);
451     nocbreak();
452     notimeout(stdscr, TRUE);
453     noraw();
454     echo();
455     endwin();
456     puts(statestr);
457     exit(0);
458 }                            /* main()  */
459 
460 /*
461  * Local variables:
462  * tab-width: 4
463  * indent-tabs-mode: nil
464  * c-basic-offset: 4
465  * End:
466  * VIM: tw=80:sw=4:sts=4:fdm=marker
467  */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -