1. 需求分析
将运动分解为鸟的垂直运动和杆的左右运动。
2. 概要设计
2.1 鸟运动部分
2.2 杆的运动
3. 代码实现
#include <stdio.h>
#include <ncurses.h>
#include <stdlib.h>
#include <time.h>
int vx = 0;
int vy = 1;
int bird_r;
int bird_c;
int rows;
int cols;
int bird_init_x = 5;
int bird_init_pole_gap = 6;
int last_fly_time = 1;
int up_time = 3;
int pole_width = 3;
int pole_bt_gap = 6;
int pole_in_gap = 6;
int pass_pole_nums = 0;
int pole_nums;
struct _pole_node {
int pole_lb_x;
int pole_gap_y;
};
typedef struct _pole_node pole_node;
pole_node pn[100];
int pole_nxt;
enum HIT_STATUS {
HIT_NORMAL,
HIT_GROUND,
HIT_POLE,
};
enum GAME_STATUS {
GAME_NORMAL,
GAME_QUIT,
};
void reset_vy()
{
vy = 1;
}
void set_pole_nums( )
{
int tot = cols - bird_init_x - 2;
tot -= bird_init_pole_gap;
pole_nums = tot /( pole_width + pole_bt_gap );
}
void gen_next_pole(pole_node *prev, pole_node *cur )
{
if ( !prev || !cur )
return;
cur->pole_lb_x = prev->pole_lb_x + pole_bt_gap + pole_width;
int prev_y = prev->pole_gap_y;
int ub = prev_y - pole_bt_gap - pole_in_gap + 1;
ub = ub < pole_width + 1 ? pole_width + 1: ub;
int lb = prev_y + pole_bt_gap + pole_in_gap - 1;
lb = lb > rows - 1 - pole_width - pole_in_gap ? rows - 1 - pole_in_gap - pole_width : lb;
cur->pole_gap_y = ub + rand() % (lb - ub + 1);
}
void init_pole_bound()
{
// pole_fp = 0;
// pole_bp = pole_nums - 1;
pn[0].pole_lb_x = bird_init_x + bird_init_pole_gap + 1;
pn[0].pole_gap_y = ( bird_r - bird_init_pole_gap) + (rand()%(2 * bird_init_pole_gap));
int prev_y;
for ( int i = 1; i < pole_nums; ++i) {
gen_next_pole( pn + i - 1, pn + i );
/*
pn[i].pole_lb_x = pn[ i - 1].pole_lb_x + pole_bt_gap + pole_width;
prev_y = pn[ i - 1 ].pole_gap_y;
int ub = prev_y - pole_bt_gap - pole_in_gap + 1;
ub = ub < pole_width + 1 ? pole_width + 1: ub;
int lb = prev_y + pole_bt_gap + pole_in_gap - 1;
lb = lb > rows - 1 - pole_width - pole_in_gap ? rows - 1 - pole_in_gap - pole_width : lb;
pn[i].pole_gap_y = ub + rand() % (lb - ub + 1);
*/
}
}
void bird_fly( )
{
vy = -1;
up_time = last_fly_time;
}
int check_hit( )
{
if ( bird_r - 1 == rows )
return HIT_GROUND;
int nx = pn[pole_nxt].pole_lb_x;
int ny = pn[pole_nxt].pole_gap_y;
if ( bird_c >= nx && bird_c < nx + pole_width) {
if ( bird_r < ny || bird_r >= ny + pole_in_gap )
return HIT_POLE;
}
return HIT_NORMAL;
}
void pole_move( )
{
for ( int i = 0; i < pole_nums; ++i) {
pn[i].pole_lb_x--;
int pole_rb = pn[i].pole_lb_x + pole_width - 1;
if ( pole_rb < 1) {
int idx = ( i - 1 + pole_nums ) % pole_nums;
gen_next_pole( pn + idx, pn + i);
}
}
if ( pn[pole_nxt].pole_lb_x + pole_width == bird_c ) {
pole_nxt = ( pole_nxt + 1 ) % pole_nums;
pass_pole_nums++;
}
}
void bird_move( )
{
bird_r += vy;
bird_c += vx;
if ( up_time) {
up_time--;
if ( !up_time ) {
vy = 1;
}
}
if ( bird_r < 1)
bird_r = 1;
}
void draw_wall( )
{
box(stdscr, '#', '#');
}
void draw_pole()
{
for ( int j = 0; j < pole_nums; ++j ) {
for ( int i = 1; i < rows - 1; ++i) {
if ( i >= pn[j].pole_gap_y && i < pn[j].pole_gap_y + pole_in_gap)
continue;
for ( int k = 0; k < pole_width; ++k) {
int curx = pn[j].pole_lb_x + k;
int cury = i;
if ( curx > 0 && curx < cols - 1 && cury > 0 && cury < rows - 1)
mvaddch(cury, curx, '*');
}
}
}
}
void draw_bird( )
{
mvaddch( bird_r, bird_c, '@');
}
void draw_tips( )
{
int mid_r = LINES / 2;
int bg_c = COLS - 20;
mvprintw(mid_r, bg_c,"scores: %d", pass_pole_nums );
mvprintw(mid_r + 1, bg_c, "Q: quit");
}
void draw_frame( )
{
clear();
draw_wall();
draw_bird();
draw_pole();
draw_tips();
refresh();
}
void get_rows_cols(int *prows, int *pcols)
{
if ( !prows || !pcols)
return;
*prows = LINES;
*pcols = COLS - 20;
}
void init_ncurse_settings( )
{
initscr();
noecho( );
timeout( 0 );
curs_set( 0 );
}
int process_input( int ch )
{
switch ( ch )
{
case 'Q':
case 'q':
return GAME_QUIT;
case 'j':
case 'J':
bird_fly();
break;
}
return GAME_NORMAL;
}
int main( int argc, char *argv[])
{
srand( (unsigned)time(NULL));
init_ncurse_settings();
get_rows_cols( &rows, &cols );
set_pole_nums();
bird_r = ( rows - 2) / 2;
bird_c = bird_init_x;
int ch;
init_pole_bound();
while ( 1 ) {
usleep( 300000 );
if ( check_hit() )
break;
ch = getch();
int ret = process_input( ch );
if ( ret == GAME_QUIT )
break;
bird_move();
pole_move();
draw_frame();
}
endwin();
return 0;
}