速さを競うゲームの例

cursesライブラリとgettimeofday()を利用すると、 trrのようなリアルタイムキー入力速度判定ソフトが作れる。 以下のプログラムを参考にして欲しい。

gcc -o trrmodoki trrmodoki.c -lcurses
./trrmodoki cj

cjファイル(テキスト)

trrmodoki.c

/* trrmodoki.c
 * compile this program by
 *
 * % gcc -o trrmodoki trrmodoki -lcurses
 *
 */
#include <curses.h>
#include <sys/time.h>

#define TEXTLINE	3       /* テキストは3行のみ */
#define WIDTH		80      /* 1行の長さ */


int main(int argc, char *argv[])
{
  char text[TEXTLINE][WIDTH];   /* 試験テキスト */
  FILE *textfile;
  int i, x, ch, num=0, miss=0, score;
  struct timeval start, finish; /* 開始時刻と終了時刻 */
  struct timezone dummy;
  float elapse;                 /* 経過時間 */
  if (NULL == argv[1]) {
    fprintf(stderr, "データファイルを指定して下さい\n");
    fprintf(stderr, " 例: ./trrmodoki constitution.txt\n");
    exit(1);
  }
  if (NULL == (textfile=fopen(argv[1], "r"))) {
    fprintf(stderr, "%s が見つからないの。ちゃんと作ってね\n", argv[1]);
    exit(2);
  }
  for (i=0; i<TEXTLINE; i++) {
    fgets(text[i], WIDTH, textfile);
  }
  /* ここからcursesライブラリ使いまくり */
  /* 次の3行は言わば「お約束」 */
  initscr();                    /* curses初期化、画面も消去*/
  noecho();                     /* 入力文字を画面に出さない */
  cbreak();                     /* リターンキーなしでも入力可能に */
  /* 画面の高さと幅を調べる */
  if (COLS < 80 || LINES < 10) {
    fprintf(stderr, "画面が狭すぎて卑怯だわ!\n", argv[1]);
    exit(3);
  }
  /* 試験テキスト3行を表示 */
  //printf("%s\n", argv[1]);
  for (i=0; i<TEXTLINE; i++) {
    standout();
    mvaddstr(i*2, 0, text[i]);  /* 座標(0,i/2)にtext[i]を表示 */
    standend();
  }
  refresh();
  /* 開始時刻を記憶 */
  gettimeofday(&start, &dummy);
  /* さて入力 */
  for (i=0; i<TEXTLINE; i++) {
    x = 0;                      /* xは今の桁数 */
    move(2*i+1, 0);
    while (x < strlen(text[i])) {
      refresh();                /* 画面を表示 */
      ch = getch();             /* 1文字即入力 */
      mvaddch(2*i+1, x, ch);    /* 座標(0,i*2+1)にその文字を出力 */
      if (ch != text[i][x]) {
        beep();
        miss++;
        move(2*i+1, x);         /* 座標(0,i*2+1)に戻る */
      } else {
        x++;
        num++;                  /* 総タイプ数 */
      }
    }
  }
  /* 終了時刻を記録 */
  gettimeofday(&finish, &dummy);
  /* 経過時間を求める */
  elapse = (finish.tv_sec - start.tv_sec)
    + (float)(finish.tv_usec - start.tv_usec)/1000000;
  /* 秒数を表示して終了 */
  mvprintw(8, 0, "%.3f秒でした. ミスは%d打\n", elapse, miss);
  /* 60秒あたりのタイプ数を計算して表示。タイプミスは10倍減点 */
  score = (int)(num-miss*10)*60/elapse;
  if (score < 0) score = 0;
  mvprintw(9, 0, "%d点ね。また頑張ってね\n", score);
  addstr("またあう日まで\n");
  refresh();                    /* refresh() を忘れずに! */
  exit(0);                      /* 正常終了の場合は0 */
}

目次