/* fun.c源文件 */ #include <curses.h> #include <signal.h> #include <sys/time.h> #include "play.h" #include <stdio.h> #include <stdlib.h> void init(void); void exit_a(void); void paint_boat(int); void paint_table(int, int, int); int settimer(int); void move_person(int); void win(void); void lost(void); struct person p1; int beg_boat; void main(void) { long ch; init(); signal(SIGINT, SIG_IGN); /* 设置定时器,单位出发时间初始化为20毫秒。 小球水平,垂直方向运动,以单位定时器的倍数为准,加入为x:5,则触发五次定时器,则小球横向移动一个单元格, 加速,是通过减少相应方向定时器的倍数。 */ signal(SIGALRM, move_person ); settimer(20); while ((ch = getch()) != ‘q‘){ if (ch == KEY_LEFT) paint_boat(1); if (ch == KEY_RIGHT) paint_boat(-1); if (ch == ‘ ‘) signal(SIGALRM, SIG_IGN); if (ch == ‘c‘) { signal(SIGALRM, move_person); settimer(20); } if (ch == ‘w‘) { if (p1.y_ttm > SPEED_MIN) p1.y_ttm--; } if (ch == ‘s‘) { if (p1.y_ttm < SPEED_MAX) p1.y_ttm++; } if (ch == ‘a‘) { if (p1.x_ttm > SPEED_MIN) p1.x_ttm--; } if (ch == ‘d‘) { if (p1.x_ttm < SPEED_MAX) p1.x_ttm++; } } } /* 退出时调用,用于恢复终端属性 */ void exit_a(void) { endwin(); } /* 初始化 */ void init(void) { int n, m; //初始化小球基本信息 p1.remain = (MINE_BOT - MINE_TOP + 1)*(MINE_RIGHT - MINE_LEFT + 1); p1.score = 0; //init the person p1.pos_x = (LEFT_COL + RIGHT_COL)/2; p1.pos_y = BOT_LINE; p1.dir_x = LEFT; p1.dir_y = UP; p1.x_ttm = p1.x_ttg = 4; p1.y_ttm = p1.y_ttg = 4; p1.per = CHAR_PERSON; //设置终端属性,函数来自与curses库 atexit(exit_a); initscr(); noecho(); keypad(stdscr, TRUE); crmode(); //paint the edge for (n = TOP_LINE - 1; n <= (BOT_LINE + 1); n++) { mvaddch(n, LEFT_COL - 1, CHAR_EDGE); mvaddch(n, RIGHT_COL + 1, CHAR_EDGE); mvaddch(n, LEFT_COL - 2, CHAR_EDGE); mvaddch(n, RIGHT_COL + 2, CHAR_EDGE); } for (n = LEFT_COL - 1; n <= (RIGHT_COL + 1); n++) { mvaddch(TOP_LINE - 1, n, CHAR_EDGE); mvaddch(TOP_LINE - 2, n, CHAR_EDGE); } //paint table paint_table( RIGHT_COL + 5, TOP_LINE + 5, 0); //paint mine for(n = MINE_TOP ; n <= MINE_BOT; n++) for (m = MINE_LEFT; m <= MINE_RIGHT; m++) mvaddch(n, m, CHAR_MINE); // paint boat beg_boat = (LEFT_COL + RIGHT_COL)/2 - LENGTH_BOAT/2; paint_boat(1); //paint the person mvaddch(p1.pos_y, p1.pos_x, p1.per); refresh(); } //打印信息表,分数等,x,y为打印位置,how:0擦除,1打印 void paint_table(int x, int y, int how) { char tot[15]; char rem[15]; char sco[15]; char spe_x[15]; char spe_y[15]; //char s_p_x[15]; //char s_p_y[15]; //char s_d_x[15]; //char s_d_y[15]; static int flag = 0; if (how == 0) { mvaddstr(y, x, " "); mvaddstr(y + 1, x, " "); mvaddstr(y + 2, x, " "); mvaddstr(y + 3, x, " "); mvaddstr(y + 4, x, " "); //mvaddstr(y + 5, x, " "); //mvaddstr(y + 6, x, " "); //mvaddstr(y + 7, x, " "); } else { sprintf(tot, "TOTAL: %d", (MINE_BOT - MINE_TOP + 1)*(MINE_RIGHT - MINE_LEFT + 1)); sprintf(rem, "REMAIN:%d", p1.remain); sprintf(spe_x, "SPEED_X: %d", SPEED_MAX - p1.x_ttm); sprintf(spe_y, "SPEED_Y: %d", SPEED_MAX - p1.y_ttm); sprintf(sco, "SCORE: %d", p1.score); //sprintf(s_p_x, "P_X: %d", p1.pos_x); //sprintf(s_p_y, "P_Y: %d", p1.pos_y); //sprintf(s_d_x, "D_X: %d", p1.dir_x); //sprintf(s_d_y, "D_Y: %d", p1.dir_y); mvaddstr(y, x, tot); mvaddstr(y + 1, x, rem); mvaddstr(y + 2, x, spe_x); mvaddstr(y + 3, x, spe_y); mvaddstr(y + 4, x, sco); //mvaddstr(y + 4, x, s_p_x); //mvaddstr(y + 5, x, s_p_y); //mvaddstr(y + 6, x, s_d_x); //mvaddstr(y + 7, x, s_d_y); } } //打印短板,dir表示方向,1向左,-1向右 void paint_boat(int dir) { int n; for ( n = 0; n < LENGTH_BOAT; n++) mvaddch(BOT_LINE + 1, n + beg_boat, BLANK ); if (dir == 1 && beg_boat > LEFT_COL) beg_boat--; if (dir == -1 && beg_boat < (RIGHT_COL +1- LENGTH_BOAT)) beg_boat++; for ( n = 0; n < LENGTH_BOAT; n++) mvaddch(BOT_LINE + 1, n + beg_boat, CHAR_BOAT ); refresh(); } //设置定时器 int settimer(int msec) { struct itimerval new; long n_sec, n_usec; n_sec = msec/1000; n_usec = (msec%1000)*1000L; new.it_interval.tv_sec = n_sec;//下次触发时间 new.it_interval.tv_usec = n_usec; new.it_value.tv_sec = n_sec;//定时器间隔时间 new.it_value.tv_usec = n_usec; return setitimer(ITIMER_REAL, &new, NULL); } /* 查看小球是否触碰到砖块 大砖块,分为两类,一类小球贴在砖块上,一类小球打在砖块上,不同方式对小球的运动影响不同 */ void dig_mine(void) { int n_x, n_y; static int min_val[MINE_BOT - MINE_TOP + 1][MINE_RIGHT - MINE_LEFT + 1]; n_y = p1.pos_y - MINE_TOP; n_x = p1.pos_x - MINE_LEFT; //打, 小球位置恰好为砖块位置,根据小球目前运动方向,四周砖块情况,决定怎么改变小球的运动状态(方向),并消除砖块,增加积分等。 if (n_x >= 0 && n_x <= (MINE_RIGHT - MINE_LEFT) && n_y >= 0 && n_y <= (MINE_BOT - MINE_TOP)) if (min_val[n_y][n_x] == MINE_HIDE) { if (n_y - 1 >=0 && min_val[n_y - 1][n_x] == MINE_HIDE) p1.dir_y = -p1.dir_y; if (n_y + 1 <= (MINE_BOT - MINE_TOP) && min_val[n_y + 1][n_x] == MINE_HIDE) p1.dir_y = -p1.dir_y; if (n_x - 1 >= 0 && min_val[n_y][n_x - 1] == MINE_HIDE) p1.dir_x = -p1.dir_x; if (n_x + 1 <= (MINE_RIGHT - MINE_LEFT) && min_val[n_y][n_x + 1] == MINE_HIDE) p1.dir_x = -p1.dir_x; min_val[n_y][n_x] = MINE_DIG; mvaddch(p1.pos_y, p1.pos_x, BLANK); p1.remain--; p1.score += (SPEED_MAX - p1.x_ttm)*(SPEED_MAX - p1.y_ttm)/10; return; } //贴,小球运动方向上,下一个位置,恰好是砖块位置(重点),根据四周情况,改变小球运动状态 if (n_x + 1 >= 0 && n_x - 1 <= (MINE_RIGHT - MINE_LEFT) && n_y + 1 >= 0 && n_y - 1<= (MINE_BOT - MINE_TOP)) { if (n_y - 1 >=0 && n_x >= 0 && n_x <= MINE_RIGHT - MINE_LEFT) if (min_val[n_y - 1][n_x] == MINE_HIDE&& p1.dir_y == UP) { min_val[n_y -1 ][n_x] = MINE_DIG; mvaddch(p1.pos_y - 1, p1.pos_x, BLANK); p1.remain--; p1.score += (SPEED_MAX - p1.x_ttm)*(SPEED_MAX - p1.y_ttm)/10; p1.dir_y = -p1.dir_y; } if (n_y + 1 <= MINE_BOT - MINE_TOP && n_x >= 0 && n_x <= MINE_RIGHT - MINE_LEFT) if (min_val[n_y + 1][n_x] == MINE_HIDE&& p1.dir_y == DOWN) { min_val[n_y + 1][n_x] = MINE_DIG; mvaddch(p1.pos_y + 1, p1.pos_x, BLANK); p1.remain--; p1.score += (SPEED_MAX - p1.x_ttm)*(SPEED_MAX - p1.y_ttm)/10; p1.dir_y = -p1.dir_y; } if (n_x - 1 >= 0 && n_y >= 0 && n_y <= MINE_BOT - MINE_TOP) if (min_val[n_y][n_x - 1] == MINE_HIDE&& p1.dir_x == LEFT) { min_val[n_y][n_x - 1] = MINE_DIG; mvaddch(p1.pos_y, p1.pos_x - 1, BLANK); p1.remain--; p1.score += (SPEED_MAX - p1.x_ttm)*(SPEED_MAX - p1.y_ttm)/10; p1.dir_x = -p1.dir_x; } if (n_x + 1 <= MINE_RIGHT - MINE_LEFT && n_y >= 0 && n_y <= MINE_BOT - MINE_TOP) if (min_val[n_y][n_x + 1] == MINE_HIDE&& p1.dir_x == RIGHT) { min_val[n_y][n_x + 1] = MINE_DIG; mvaddch(p1.pos_y, p1.pos_x + 1, BLANK); p1.remain--; p1.score += (SPEED_MAX - p1.x_ttm)*(SPEED_MAX - p1.y_ttm)/10; p1.dir_x = -p1.dir_x; } } } /* 小球运行判定函数 */ void move_person(int signo) { signal(SIGALRM, SIG_IGN); int flag = 0, bef_x, bef_y; bef_x = p1.pos_x; bef_y = p1.pos_y; //指定次数定时器是否触发 if (p1.x_ttm > 0 && p1.x_ttg-- == 1) { p1.x_ttg = p1.x_ttm; flag += 2; } if (p1.y_ttm > 0 && p1.y_ttg-- == 1) { p1.y_ttg = p1.y_ttm; flag += 1; } if (flag > 0) { //lost 判定小球是否越出下边界,是,则失败,结束 if (p1.dir_y == DOWN && bef_y == BOT_LINE) if (bef_x < beg_boat || bef_x >= (beg_boat + LENGTH_BOAT)) { paint_table(RIGHT_COL + 5, TOP_LINE + 5, 0); paint_table(LEFT_COL + 6, TOP_LINE + 4, 1); lost(); return; } else p1.dir_y = -p1.dir_y; //win 判定砖块被全打光,是 ,胜利,游戏结束 if (p1.remain == 0) { paint_table(RIGHT_COL + 5, TOP_LINE + 5, 0); paint_table(LEFT_COL + 6, TOP_LINE + 4, 1); win(); return; } //小球在砖块潜在位置,才进行砖块判定 if (p1.pos_x >= MINE_LEFT - 1 && p1.pos_x <= MINE_RIGHT+1 && p1.pos_y >= MINE_TOP - 1 && p1.pos_y <= MINE_BOT+1) dig_mine(); if (flag == 1) p1.pos_x += p1.dir_x; else if (flag == 2) p1.pos_y += p1.dir_y; else { p1.pos_x += p1.dir_x; p1.pos_y += p1.dir_y; } //打印信息表 paint_table(RIGHT_COL + 5, TOP_LINE + 5, 0); paint_table(RIGHT_COL + 5, TOP_LINE + 5, 1); mvaddch(bef_y, bef_x, BLANK); //当小球,遇到上,左,右边界时,改变运行方向 if ( p1.dir_x == LEFT &&p1.pos_x == LEFT_COL) p1.dir_x = -p1.dir_x; if (p1.dir_x == RIGHT && p1.pos_x == RIGHT_COL) p1.dir_x = -p1.dir_x; if (p1.dir_y == UP &&p1.pos_y == TOP_LINE) p1.dir_y = -p1.dir_y; mvaddch(p1.pos_y, p1.pos_x, CHAR_PERSON); move(LINES - 1, COLS -1); refresh(); } signal(SIGALRM, move_person); } //成功时,打印 void win(void) { move(TOP_LINE + 3, LEFT_COL + 20); printw("%s", " "); move(TOP_LINE + 4, LEFT_COL + 20); printw("%s", "* * *** * * * * * * ** * "); move(TOP_LINE + 5, LEFT_COL + 20); printw("%s", " * * * * * * * * * * * * * "); move(TOP_LINE + 6, LEFT_COL + 20); printw("%s", " * * * * * * * * * * * * "); move(TOP_LINE + 7, LEFT_COL + 20); printw("%s", " * * * * * * * * * * * ** "); move(TOP_LINE + 8, LEFT_COL + 20); printw("%s", " * *** *** * * * * * "); move(TOP_LINE + 9, LEFT_COL + 20); printw("%s", " "); refresh(); } //失败时打印 void lost(void) { move(TOP_LINE + 3, LEFT_COL + 20); printw("%s", " "); move(TOP_LINE + 4, LEFT_COL + 20); printw("%s", "* * *** * * * *** **** ***** "); move(TOP_LINE + 5, LEFT_COL + 20); printw("%s", " * * * * * * * * * * * "); move(TOP_LINE + 6, LEFT_COL + 20); printw("%s", " * * * * * * * * **** * "); move(TOP_LINE + 7, LEFT_COL + 20); printw("%s", " * * * * * * * * * * "); move(TOP_LINE + 8, LEFT_COL + 20); printw("%s", " * *** *** **** *** **** * "); move(TOP_LINE + 9, LEFT_COL + 20); printw("%s", " "); refresh(); }
算法未经允许,请勿转载,谢谢。
时间: 2024-10-08 13:18:39