LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   LinuxQuestions.org Member Success Stories (https://www.linuxquestions.org/questions/linuxquestions-org-member-success-stories-23/)
-   -   learnign ncurses, just wrote this, yay :D (https://www.linuxquestions.org/questions/linuxquestions-org-member-success-stories-23/learnign-ncurses-just-wrote-this-yay-d-732897/)

jr_bob_dobbs 06-14-2009 04:03 PM

learnign ncurses, just wrote this, yay :D
 
So I've started to teach myself ncurses programming. Actually got a program working, a simple maze game. You start in the upper left and the goal/end is the lower right. Thought I'd share it here (curse_maze_2.c) :

Code:

/* gcc -o curses_maze_2 -lncurses curses_maze_2.c */
#include <curses.h>
#include <signal.h>
#include <time.h>  /* for random */
#ifndef memmove
  #include <string.h>
#endif
#ifndef srand
  #include <stdlib.h>
#endif
#define neq !=
#define eq ==
#define DOOPS 20
#define OKDOKEY 0
#define mod %
#define maze_width 72
#define maze_height 28
#define drill_north 0
#define drill_south 1
#define drill_west 2
#define drill_east 3


/* global vars */
char *maze;
int player_x, player_y, player_x_maze, player_y_maze;
int where_i_was_x, where_i_was_y, what_was_under_char;
int maze_displace_x, maze_displace_y;
unsigned int end_x_maze, end_y_maze;
unsigned short turns;
int pcc_use_colors;


/* forward references */
void handle_ctrl_c(int);
void build_maze();
void draw_info_line();
void draw_map();
void redraw_board();
void draw_under_character();
void draw_character();


/* start of actual program */
void handle_ctrl_c(s)
int s;
{
  ungetch('q'); /* put in quit command as an input char */
}


void build_maze()
{
  int y, x, turns, a, direction;

  for (y = 0; y neq maze_height; y++) {
    for (x = 0; x neq maze_width; x++) {
      maze[((y * maze_width) + x)] = '#';
    }
  }
  x = 1;
  y = maze_height / 2;
  maze[((y * maze_width) + x)] = ' '; /* start drilling */
  for (turns = 0; turns neq 800000; turns++) {
    y = 1 + (rand() mod (maze_height - 2));
    x = 1 + (rand() mod (maze_width - 2));
    if ('#' eq maze[((y * maze_width) + x)]) { /* if not already dug */
      /* At this point, we are at a filled spot. */
      /* Now, only if there is one space adjacent in a non-diagonal
        direction, can we drill/dig this spot */
      a = 0;
      if (' ' eq maze[(((y - 1) * maze_width) + x)])  { a++; direction = drill_north; }
      if (' ' eq maze[(((y + 1) * maze_width) + x)])  { a++; direction = drill_south; }
      if (' ' eq maze[((y * maze_width) + (x - 1))])  { a++; direction = drill_west; }
      if (' ' eq maze[((y * maze_width) + (x + 1))])  { a++; direction = drill_east; }
      if (1 eq a) {
        /* we have one adjacent non-diagonal space.
          Maybe we can drill.  the two diaognals opposing this  draw_map(0, 0, old_height, old_width);

          space must be un-dug for this to work */
        switch (direction) {
          case drill_north : /* check south diagonals */
            if (' ' eq maze[(((y + 1) * maze_width) + (x - 1))]) a = 0; /* can't drill */
            if (' ' eq maze[(((y + 1) * maze_width) + (x + 1))]) a = 0; /* can't drill */
            break;
          case drill_south : /* check north diagonals */
            if (' ' eq maze[(((y - 1) * maze_width) + (x - 1))]) a = 0; /* can't drill */
            if (' ' eq maze[(((y - 1) * maze_width) + (x + 1))]) a = 0; /* can't drill */
            break;
          case drill_west : /* check east diagonals */
            if (' ' eq maze[(((y - 1) * maze_width) + (x + 1))]) a = 0; /* can't drill */
            if (' ' eq maze[(((y + 1) * maze_width) + (x + 1))]) a = 0; /* can't drill */
            break;
          case drill_east : /* check west diagonals */
            if (' ' eq maze[(((y - 1) * maze_width) + (x - 1))]) a = 0; /* can't drill */
            if (' ' eq maze[(((y + 1) * maze_width) + (x - 1))]) a = 0; /* can't drill */
            break;
        } /* end switch */
        if (1 eq a) {
          /* we can drill/dig!  YAY! */
          maze[((y * maze_width) + x)] = ' ';
        }
      }
    }
  }
}


void draw_info_line()
{
  attron(A_BOLD);
  mvprintw(
    (LINES - 1), 0,
    "-- pcc maze --- %3d -- %3d --  ",
    player_x_maze, player_y_maze
  );
  attroff(A_BOLD);
}


void draw_side_bar_stats()
{
  attron(A_BOLD);
  mvprintw(
    1,
    ((COLS - 8) + 2),
    "      "
  );
  mvprintw(
    1,
    ((COLS - 8) + 2),
    "%d", turns
  );
  attroff(A_BOLD);
}


void draw_side_bar()
{
  mvprintw(0, (COLS - 8), "+-------"); 
  mvaddch(1, (COLS - 8), '|'); 
  mvaddch(2, (COLS - 8), '|');
  draw_side_bar_stats();
}


void draw_map()
{
  int x, y, xlim, ylim, c;

  xlim = COLS - 8;
  ylim = LINES - 1;
  for (y = 0; y neq ylim; y++) {
    for (x = 0; x neq xlim; x++) {
      if (((x + maze_displace_x) < maze_width) &&
          ((y + maze_displace_y) < maze_height)) {
        c = maze[(((y + maze_displace_y) * maze_width) + (x + maze_displace_x))];
        if (('.' eq c) && pcc_use_colors) {
          attron(COLOR_PAIR(3));
        }
        if ('X' eq c) {
          attron(A_BOLD);
          if (pcc_use_colors) {
            attron(COLOR_PAIR(4));
          }
        }
        mvaddch(
          y, x,
          c
        );
        if ('X' eq c) {
          if (pcc_use_colors) {
            attroff(COLOR_PAIR(4));
          }
          attroff(A_BOLD);
        }
        if (('.' eq c) && pcc_use_colors) {
          attroff(COLOR_PAIR(3));
        }
      } else {
        mvaddch(
          y, x,
          ' '
        );
      }
    }
  }
}


void redraw_board()
{
  draw_map(0, 0);
  draw_side_bar();
  draw_info_line();
  move(player_y, player_x);  refresh();
}


void pick_start_point()
{
  player_x = 1;
  player_y = 1;
  while (
    ' '
    neq
    maze[
      (
        (player_y * maze_width) + player_x
      )
    ]
  )
  {
    player_x++;
  }
  player_x_maze = player_x;
  player_y_maze = player_y;
}


void pick_end_point()
{
  end_x_maze = maze_width - 2;
  end_y_maze = maze_height - 2;
  while (
    ' '
    neq
    maze[
      (
        (end_y_maze * maze_width) + end_x_maze
      )
    ]
  )
  {
    end_x_maze--;
  }
  maze[((end_y_maze * maze_width) + end_x_maze)] = 'X';
}


void draw_under_character()
{
  what_was_under_char = maze[((player_y_maze * maze_width) + player_x_maze)];
  where_i_was_x = player_x_maze;
  where_i_was_y = player_y_maze;


  if (('.' eq what_was_under_char) && pcc_use_colors) {
    attron(COLOR_PAIR(3));
  }
  mvaddch(player_y, player_x, what_was_under_char);
  if (('.' eq what_was_under_char) && pcc_use_colors) {
    attroff(COLOR_PAIR(3));
  }
}


void draw_character()
{
  attron(A_BOLD);
  mvaddch(player_y, player_x, '@');
  attroff(A_BOLD);
  move(player_y, player_x);
}


void update_trail()
{
  if ('.' eq maze[((player_y_maze * maze_width) + player_x_maze)]) {
    maze[((where_i_was_y * maze_width) + where_i_was_x)] = ' ';
  } else {
    if (' ' eq maze[((player_y_maze * maze_width) + player_x_maze)]) {
      maze[((where_i_was_y * maze_width) + where_i_was_x)] = '.';
    }
  }
  draw_map();
}


int check_for_match()
{
  if (player_x_maze eq end_x_maze) {
    if (player_y_maze eq end_y_maze) {
      return(1);
    }
  }
  return(0);
}


main()
{
  int c;

  srand((unsigned int) time(NULL) );
  maze = malloc(maze_width * maze_height);
  if (NULL eq maze) {
    fprintf(stderr, "memory failure\n");
    exit(DOOPS);
  }
  turns = 0;
  build_maze();
  pick_start_point();
  pick_end_point();
  maze_displace_x = maze_displace_y = 0;
  signal(SIGINT, handle_ctrl_c);
  initscr();
  pcc_use_colors = 0;
  if (TRUE eq has_colors()) {
    pcc_use_colors++;
    start_color();
    use_default_colors();
    init_pair(3, COLOR_CYAN, -1);  /* Blue-green on clear */
    init_pair(4, COLOR_GREEN, -1);  /* green on clear */
  }
  keypad(stdscr, TRUE);
  cbreak();
  noecho();
  halfdelay(1);

  redraw_board();
  draw_character(player_y, player_x);

  while (1) {
    if (check_for_match()) break;
    c = getch();
    switch (c) {
      case 0xc : /* ^l */  /* user presses ^l to force redraw */
        redraw_board();
        break;
      case 3 :  /* control-c to exit */
      case 'q' : /* q to exit */
        move((LINES - 1), 0);  refresh();
        endwin();
        exit(OKDOKEY);
      case '6' : /* move east/right */
      case KEY_RIGHT :
        switch (maze[((player_y_maze * maze_width) + (player_x_maze + 1))]) {
          case ' ' :
          case '.' :
          case 'X' :
          draw_under_character();
          /* if we reached this point, then we can move east/right in the
            maze.  However, can we move east in the "window"? */
          if (player_x eq (COLS - 10)) {
            maze_displace_x++; /* do not change player_x!!! */
            draw_map();
          } else {
            player_x++;
          }
          player_x_maze++;
          turns++;
          update_trail();
          draw_info_line();
          draw_side_bar_stats();
          draw_character();
          refresh();
          break;
        } /* end switch */
        break;
      case '4' : /* move west/left */
      case KEY_LEFT :
        switch (maze[((player_y_maze * maze_width) + (player_x_maze - 1))]) {
          case ' ' :
          case '.' :
          case 'X' :
          draw_under_character();
          /* if we reached this point, then we can move west/left in the
            maze.  However, can we move north in the "window"? */
          if (player_x eq 1) {  /* need to scroll maze first */
            maze_displace_x--; /* do not change player_x!!! */
            draw_map();
          } else {
            player_x--;
          }
          player_x_maze--;
          turns++;
          update_trail();
          draw_info_line();
          draw_side_bar_stats();
          draw_character();
          refresh();
          break;
        } /* end switch */
        break;
      case '8' : /* move north/up */
      case KEY_UP :
        switch (maze[(((player_y_maze - 1) * maze_width) + player_x_maze)]) {
          case ' ' :
          case '.' :
          case 'X' :
          draw_under_character();
          /* if we reached this point, then we can move north/up in the
            maze.  However, can we move north in the "window"? */
          if (player_y eq 1) {  /* need to scroll maze first */
            maze_displace_y--; /* do not change player_y!!! */
            draw_map();
          } else {
            player_y--;
          }
          player_y_maze--;
          turns++;
          update_trail();
          draw_info_line();
          draw_side_bar_stats();
          draw_character();
          refresh();
          break;
        } /* end switch */
        break;
      case '2' : /* move south/down */
      case KEY_DOWN :
        switch (maze[(((player_y_maze + 1) * maze_width) + player_x_maze)]) {
          case ' ' :
          case '.' :
          case 'X' :
          draw_under_character();
          /* if we reached this point, then we can move down/south in the
            maze.  However, can we move south in the "window"? */
          if (player_y eq (LINES - 3)) { /* need to scroll maze first */
            maze_displace_y++; /* do not change player_y!!! */
            draw_map();
          } else {
            player_y++;
          }
          player_y_maze++;
          turns++;
          update_trail();
          draw_info_line();
          draw_side_bar_stats();
          draw_character();
          refresh();
          break;
        }
        break;
    } /* end switch */
  } /* end while */
  /* we could only reach this point if we sucesfully reached the
    end goal of the maze */

  maze[((where_i_was_y * maze_width) + where_i_was_x)] = '.';
  draw_map();
  attron(A_BOLD);
  mvprintw(2, (COLS - 8) + 2, "YOU"); 
  mvprintw(3, (COLS - 8) + 2, "WIN!"); 
  attroff(A_BOLD);
  draw_character();
  refresh();
  while (-1 eq (c = getch())); /* pause before exit */
  move((LINES - 1), 0);  refresh();
  endwin();
  exit(OKDOKEY);
}



All times are GMT -5. The time now is 01:26 AM.