プログラミング演習 II B (12/09)


課題9:イベント駆動への拡張

いままで作ってきたプログラムの主要部分はおそらく次のようなもの になっているはずである。

    nlights = count_lights(lights);
    while ( nlights > 0 ) {
	turn++;
	Turn と Left の表示
	print_lights(lights);
	input_position( &x, &y );
	change_lights( lights, x, y );
	nlights = count_lights(lights);
    }
このままの構成で input_position() 関数にマウス入力を付加する ことももちろん可能だが、「中断」や「やりなおし」といったボタンを さらに追加することが難しくなる。
なぜなら、どのボタンに対する入力がいつ行われるか、あらかじめ知る ことができないからである。

そこで、

を分離して、今後の拡張をやりやすくする。


1)XpWaitEvent() 関数の出力を格納するための構造体を宣言する。
ヘッダファイル lights.h に次の宣言を追加せよ。

typedef struct {
    char ch;
    int x; /* pos[0] に対応する */
    int y; /* pos[1] に対応する */
} Event ;

2)display.c に次の関数を追加せよ。

/*
 * void get_event( Event *ev )
 * XpWaitEvent() を1回実行し、結果を Event 構造体の
 * メンバ変数 ch, x, y に格納せよ。
 */
念のため補足するが、この宣言の意味は、 この関数が Event 構造体へのポインタ ev を引数として呼び出される、という意味である。
get_event() 関数内で構造体のメンバを参照するときは ev->ch, ev->x, ev->y と記述する。


3)display.c に次の関数を追加せよ。

/*
 * int check_click_board( Event *ev, int *x, int *y )
 * 機能:
 *   ev の内容を読み取り、ゲーム盤内のクリックであれば
 *   *x および *y に 0..4 の座標を代入し、返り値 1 を返せ。
 *   さもなくば返り値 0 を返せ。
 */
なお、座標のチェックには極力 lights.h 内の定数を用いよ。


4)main.c の main() 関数の変数宣言部に次の行を追加せよ。

    Event ev;

5)main.c の main() 関数のメインループを次のように変更せよ。
(きちんと動作すれば、こまかいところは違っていてもよい)

    while ( nlights > 0 ) {
	get_event() の呼び出し

	if ( check_click_board() の返り値が1ならば ) {
	    change_lights( lights, x, y );
	    turn++;
            Turn と Left の表示
	    nlights = count_lights(lights);
	    print_lights(lights);
	}
    }
    面クリアのメッセージ

6)make して動作を確認せよ。


Takuya NISHIMOTO
Last modified: Mon Jan 27 11:44:14 1997