Write a guessing game in ncurses on Linux | Opensource.com

Write a guessing game in ncurses on Linux

Use the flexibility and power of ncurses to create a guess-the-number game on Linux.

question mark in chalk
Image credits : 
TeroVesalainen via Pixabay CC0
x

Subscribe now

Get the highlights in your inbox every week.

In my last article, I gave a brief introduction to using the ncurses library to write text-mode interactive applications in C. With ncurses, we can control where and how text gets displayed on the terminal. If you explore the ncurses library functions by reading the manual pages, you’ll find there are a ton of different ways to display text, including bold text, colors, blinking text, windows, borders, graphic characters, and other features to make your application stand out.

If you’d like to explore a more advanced program that demonstrates a few of these interesting features, here’s a simple “guess the number” game, updated to use ncurses. The program picks a random number in a range, then asks the user to make repeated guesses until they find the secret number. As the user makes their guess, the program lets them know if the guess was too low or too high.

Note that this program limits the possible numbers from 0 to 7. Keeping the values to a limited range of single-digit numbers makes it easier to use getch() to read a single number from the user. I also used the getrandom kernel system call to generate random bits, masked with the number 7 to pick a random number from 0 (binary 0000) to 7 (binary 0111).

#include <curses.h>
#include <string.h>          /* for strlen */
#include <sys/random.h>      /* for getrandom */

int
random0_7()
{
   int num;
   getrandom(&num, sizeof(int), GRND_NONBLOCK);
   return (num & 7); /* from 0000 to 0111 */
}

int
read_guess()
{
  int ch;

  do {
    ch = getch();
  } while ((ch < '0') || (ch > '7'));

  return (ch - '0'); /* turn into a number */
}

By using ncurses, we can add some visual interest. Let’s add functions to display important text at the top of the screen and a message line to display status information at the bottom of the screen.

void
print_header(const char *text)
{
  move(0, 0);
  clrtoeol();

  attron(A_BOLD);
  mvaddstr(0, (COLS / 2) - (strlen(text) / 2), text);
  attroff(A_BOLD);
  refresh();
}

void
print_status(const char *text)
{
  move(LINES - 1, 0);
  clrtoeol();
 
  attron(A_REVERSE);
  mvaddstr(LINES - 1, 0, text);
  attroff(A_REVERSE);
  refresh();
}

With these functions, we can construct the main part of our number-guessing game. First, the program sets up the terminal for ncurses, then picks a random number from 0 to 7. After displaying a number scale, the program then enters a loop to ask the user for their guess.

As the user makes their guess, the program provides visual feedback. If the guess is too low, the program prints a left square bracket under the number on the screen. If the guess is too high, the game prints a right square bracket. This helps the user to narrow their choice until they guess the correct number.

int
main()
{
  int number, guess;

  initscr();
  cbreak();
  noecho();

  number = random0_7();
  mvprintw(1, COLS - 1, "%d", number); /* debugging */

  print_header("Guess the number 0-7");

  mvaddstr(9, (COLS / 2) - 7, "0 1 2 3 4 5 6 7");

  print_status("Make a guess...");

  do {
    guess = read_guess();

    move(10, (COLS / 2) - 7 + (guess * 2));

    if (guess < number) {
      addch('[');
      print_status("Too low");
    }

    else if (guess > number) {
      addch(']');
      print_status("Too high");
    }

    else {
      addch('^');
    }
  } while (guess != number);

  print_header("That's right!");
  print_status("Press any key to quit");
  getch();

  endwin();

  return 0;
}

Copy this program and compile it for yourself to try it out. Don’t forget that you need to tell GCC to link with the ncurses library:

$ gcc -o guess guess.c -lncurses

I’ve left the debugging line in there, so you can see the secret number near the upper-right corner of the screen:

guessnumber07.png

guess number game interface

Figure 1: Guess the number game. Notice the secret number in the upper right.

Get yourself going with ncurses

This program uses a bunch of other features of ncurses that you can use as a starting point. For example, the print_header function prints a message in bold text centered at the top of the screen, and the print_status function prints a message in reverse text at the bottom-left of the screen. Use this to help you get started with ncurses programming.

Person using a laptop

Use ncurses in Linux to place text at specific locations on the screen and enable more user-friendly interfaces.
Javascript code close-up with neon graphic overlay

Take the first steps toward creating interactive, dynamic web content by practicing some basic JavaScript concepts with a simple game.
Person typing on a 1980's computer

Because Fortran was written in the punched card era, its syntax is pretty limited. But you can still write useful and interesting programs with it.

About the author

photo of Jim Hall
Jim Hall - Jim Hall is an open source software advocate and developer, best known for usability testing in GNOME and as the founder + project coordinator of FreeDOS. At work, Jim is CEO of Hallmentum, an IT executive consulting company that provides hands-on IT Leadership training, workshops, and coaching.