第48回
特殊な画面制御~GCCの画面制御ライブラリ

ncursesを使ったサンプル

ncursesライブラリの関数を使ったプログラムを紹介しておきましょう(リスト1)。

矢印キー(←↑↓→)の操作で「*」記号で描いたハートマークが上下左右に移動します。

終了するには[ESC]キーを押します。

ハートマークを描くviewheart関数とハートマークを消すclrheart関数内で、カーソルを移動するmove関数と文字列を出力するprintw関数を使って、char型の2次元配列を順に出力しています。

moveheart関数内ではwhileループを使い、矢印キーが押されると矢印の方向へハートマークを移動するため、
clrheart関数で現在表示されているハートマークを消す
viewheart関数で新しい座標にハートマークを描く
――という動作を、[ESC]キーが押されるまで繰り返しています。

リスト1:画面上にハートマークを描き、移動させる
#include <curses.h>

/* --------------------------------------------------------------
  viewheart -- 座標を指定してハートマークを描く
   -------------------------------------------------------------- */
void viewheart(int x, int y)
{
  int i;
  char heart[8][32 + 1] = {
    " ****      ****",
    "******    ******",
    "*******  *******",
    " **************",
    "   **********",
    "    ********",
    "      ****",
    "       **"
  };

  for (i = 0; i < 8; i++) {
    mvprintw(y+i, x, heart[i]);
  }
}

/* --------------------------------------------------------------
  clrheart -- 座標を指定してハートマークを消す
   -------------------------------------------------------------- */
void clrheart(int x, int y)
{
  int i;
  /* 他の形にも対応できるよう矩形領域をスペースで消す */
  char clr[8][32 + 1] = {
    "                ",
    "                ",
    "                ",
    "                ",
    "                ",
    "                ",
    "                ",
    "                ",
  };

  for (i = 0; i < 8; i++) {
    mvprintw(y+i, x, clr[i]);
  }

/* 
  clr[] = "                ";
    と宣言しておいて
  for (i = 0; i < 8; i++) {
    mvprintw(y+i, x, clr);
  }
    のようにしてもOK。
 */
}

/* --------------------------------------------------------------
  moveheart -- 矢印キーでハートマークを動かす
   -------------------------------------------------------------- */
void moveheart()
{
  /* [ESC]キーが押されるまで繰り返す */
  while ((key = getch()) != KEY_ESC) {
    switch (key) {
    case KEY_UP :
      oldx = x;
      oldy = y;
      y--;
      if (y < 0) y = 0;
      break;
    case KEY_DOWN :
      oldx = x;
      oldy = y;
      y++;
      if (y > 17) y = 17;
      break;
    case KEY_LEFT :
      oldx = x;
      oldy = y;
      x--;
      if (x < 0) x = 0;
      break;
    case KEY_RIGHT :
      oldx = x;
      oldy = y;
      x++;
      if (x > 63) x = 63;
      break;
    }
    /* ハートを描く */
    clrheart(oldx, oldy);
    viewheart(x, y);
  }
}

/* --------------------------------------------------------------
  main
   -------------------------------------------------------------- */
int main(void)
{
  int i;
  int key;
  int x, y;
  int oldx, oldy;

  initscr();

  /* 特殊キーを受け取る */
  noecho();
  cbreak();
  keypad(stdscr, TRUE);

  /* 初期座標 */
  x = 32;
  y = 8;

  viewheart(x, y);  /* ハートを表示 */
  moveheart();      /* キーでハートを動かす */

  endwin();
  return (0);
}

あとがき

4年間にわたって長々と続けてきたこのコラムも、今回で一区切りを付けることになりました。

C言語にはじめて触れる人だけでなく、かつて学び、実際にプログラミングを経験したことのある人も含めて、基礎から開発までのテクニックと考え方をひととおり紹介してきたつもりです。

説明不足の部分も多々あったかと思いますが、なにとぞご容赦ください。

連載中、読者のみなさんからはたくさんのご感想、ご意見、ご要望、ご指摘などを頂きました。この場を借りて感謝の意を表します。


さて、これ以降は、「プログラムのアイデアから実現まで」の過程を、実際にプログラムを作りながら紹介していき、そこから「アルゴリズム編」へと突入する予定です。

今後とも、ご支援・ご愛読のほどをよろしくお願いいたします。

筆者敬白