在linux下用c语言利用信号机制完成了一个弹球的小游戏,代码如下:
bounce.h
/* bounce.h */
/* some settings for the game */
#define BLANK ' '
#define DFL_SYMBOL 'o'
#define TOP_ROW 5
#define BOT_ROW 20
#define LEFT_EDGE 10
#define RIGHT_EDGE 70
#define X_INIT 10 /* starting col */
#define Y_INIT 10 /* starting row */
#define TICKS_PER_SEC 50 /* affects speed */
#define X_TTM 5
#define Y_TTM 8
/** the ping pong ball **/
struct ppball {
int y_pos, x_pos,
y_ttm, x_ttm,
y_ttg, x_ttg,
y_dir, x_dir;
char symbol ;
} ;
pppaddle.h
struct pppaddle
{
int pad_top;
int pad_bot;
int pad_col;
char pad_char;
};
void paddle_init(struct pppaddle * p);
int paddle_up(struct pppaddle * p);
int paddle_down(struct pppaddle * p);
int paddle_contact(int x,int y,struct pppaddle * p);
pong.c
#include <curses.h>
#include <signal.h>
#include "bounce.h"
#include <stdlib.h>
#include "pppaddle.h"
#define MAXSPEED 10
#define MAXMODIFY 3
struct ppball the_ball;
struct pppaddle the_paddle;
int ball_left = 3;
/** the main loop **/
void set_up();
void wrap_up();
void draw_wall();
void draw_paddle();
int main() {
int c;
set_up();
while (ball_left > 0 && (c = getchar()) != 'Q') {
if (c == 'j') {
if (paddle_down(&the_paddle) == 1) {
move(the_paddle.pad_top - 1, the_paddle.pad_col);
addch(' ');
move(the_paddle.pad_bot, the_paddle.pad_col);
addch('#');
}
}
if (c == 'k') {
if (paddle_up(&the_paddle) == 1) {
move(the_paddle.pad_bot + 1, the_paddle.pad_col);
addch(' ');
move(the_paddle.pad_top, the_paddle.pad_col);
addch('#');
}
}
}
wrap_up();
}
void set_up()
/*
* init structure and other stuff
*/
{
void ball_move(int);
paddle_init(&the_paddle);
the_ball.y_pos = Y_INIT;
the_ball.x_pos = X_INIT;
the_ball.y_ttg = the_ball.y_ttm = rand() % MAXSPEED;
the_ball.x_ttg = the_ball.x_ttm = rand() % MAXSPEED;
the_ball.y_dir = 1;
the_ball.x_dir = 1;
the_ball.symbol = DFL_SYMBOL;
initscr();
noecho();
crmode();
signal( SIGINT, SIG_IGN);
mvaddch(the_ball.y_pos, the_ball.x_pos, the_ball.symbol);
draw_wall();
refresh();
signal( SIGALRM, ball_move);
set_ticker(1000 / TICKS_PER_SEC); /* send millisecs per tick */
}
void wrap_up() {
set_ticker(0);
endwin(); /* put back to normal */
}
void ball_move(int signum) {
int y_cur, x_cur, moved;
signal( SIGALRM, SIG_IGN); /* dont get caught now */
y_cur = the_ball.y_pos; /* old spot */
x_cur = the_ball.x_pos;
moved = 0;
if (the_ball.y_ttm > 0 && the_ball.y_ttg-- == 1) {
the_ball.y_pos += the_ball.y_dir; /* move */
the_ball.y_ttg = the_ball.y_ttm; /* reset*/
moved = 1;
}
if (the_ball.x_ttm > 0 && the_ball.x_ttg-- == 1) {
the_ball.x_pos += the_ball.x_dir; /* move */
the_ball.x_ttg = the_ball.x_ttm; /* reset*/
moved = 1;
}
if (moved) {
mvaddch(y_cur, x_cur, BLANK);
mvaddch(y_cur, x_cur, BLANK);
mvaddch(the_ball.y_pos, the_ball.x_pos, the_ball.symbol);
bounce_or_lose(&the_ball);
move(LINES - 1, COLS - 1);
refresh();
}
signal( SIGALRM, ball_move); /* for unreliable systems */
}
int bounce_or_lose(struct ppball *bp) {
int return_val = 0;
if (bp->y_pos == TOP_ROW) {
bp->y_dir = 1;
change_the_speed();
return_val = 1;
} else if (bp->y_pos == BOT_ROW) {
bp->y_dir = -1;
change_the_speed();
return_val = 1;
}
if (bp->x_pos == LEFT_EDGE) {
bp->x_dir = 1;
change_the_speed();
return_val = 1;
} else if (paddle_contact(bp->x_pos, bp->y_pos, &the_paddle)) {
bp->x_dir = -1;
change_the_speed();
return_val = 1;
}
if(the_ball.x_pos == 71)
{
move(the_ball.y_pos,the_ball.x_pos);
addch(' ');
move(LINES - 1, COLS - 1);
refresh();
bp->x_pos = 10;
bp->y_pos = 10;
ball_left--;
if(ball_left == 0)
{
clear();
exit(0);
}
}
return return_val;
}
void draw_wall() {
int i;
for (i = 9; i <= 70; i++) {
move(4, i);
addch('*');
}
for (i = 4; i <= 21; i++) {
move(i, 9);
addch('*');
}
for (i = 9; i <= 70; i++) {
move(21, i);
addch('*');
}
for (i = the_paddle.pad_top; i <= the_paddle.pad_bot; i++) {
move(i, the_paddle.pad_col);
addch('#');
}
}
void draw_paddle() {
int i;
for (i = the_paddle.pad_top; i <= the_paddle.pad_bot; i++) {
move(i, the_paddle.pad_col);
addch('#');
}
}
void change_the_speed() {
int add_or_delete = rand() % MAXSPEED;
if (add_or_delete % 2 == 0)
add_or_delete = 1;
else
add_or_delete = -1;
int speed_change = rand() % MAXMODIFY;
if (the_ball.x_ttm + (speed_change * add_or_delete) > 0)
the_ball.x_ttm = the_ball.x_ttm + (speed_change * add_or_delete);
add_or_delete = rand() % MAXSPEED;
if (add_or_delete % 2 == 0)
add_or_delete = 1;
else
add_or_delete = -1;
speed_change = rand() % MAXMODIFY;
if (the_ball.y_ttm + (speed_change * add_or_delete) > 0)
the_ball.y_ttm = the_ball.y_ttm + (speed_change * add_or_delete);
}
pppaddle.c
#include "pppaddle.h"
void paddle_init(struct pppaddle * p)
{
p->pad_char = '#';
p->pad_col = 71;
p->pad_bot = 16;
p->pad_top = 11;
}
int paddle_up(struct pppaddle * p)
{
if(p->pad_top != 5)
{
p->pad_top--;
p->pad_bot--;
return 1;
}
return 0;
// int i;
// for(i = the_paddle.pad_top; i <= the_paddle.pad_bot;i++)
// {
// move(i,the_paddle.pad_col);
// addch('#');
// }
}
int paddle_down(struct pppaddle * p)
{
if(p->pad_bot != 20)
{
p->pad_top++;
p->pad_bot++;
return 1;
}
return 0;
// int i;
// for(i = the_paddle.pad_top; i <= the_paddle.pad_bot;i++)
// {
// move(i,the_paddle.pad_col);
// addch('#');
// }
}
int paddle_contact(int x,int y,struct pppaddle * p)
{
if(x == 70 && y <= p->pad_bot && y >= p->pad_top)
return 1;
else
return 0;
}
set_ticker.c
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
/*
* set_ticker.c
* set_ticker( number_of_milliseconds )
* arranges for the interval timer to issue
* SIGALRM's at regular intervals
* returns -1 on error, 0 for ok
*
* arg in milliseconds, converted into micro seoncds
*/
void set_ticker(int n_msecs )
{
struct itimerval new_timeset;
long n_sec, n_usecs;
n_sec = n_msecs / 1000 ;
n_usecs = ( n_msecs % 1000 ) * 1000L ;
new_timeset.it_interval.tv_sec = n_sec; /* set reload */
new_timeset.it_interval.tv_usec = n_usecs; /* new ticker value */
new_timeset.it_value.tv_sec = n_sec ; /* store this */
new_timeset.it_value.tv_usec = n_usecs ; /* and this */
setitimer(ITIMER_REAL, &new_timeset, NULL);
}