東京理科大学 infoserv[更新日]2000.5.1


次の問7から問10までの4問については,この中から1問を選択し,
答案用紙の選択欄の[ 選 ] を マークして解答してください。
 なお,2問以上選択した場合には,はじめの1問について採点します。

問7 次の C プログラムの説明及びプログラムを読んで, 設問に答えよ。

〔プログラムの説明〕

水平及び垂直方向に 512 ピクセル(画素)からなるビットマップ画面がある。 水平方向を X 座標,垂直方向を Y 座標とする。座標の割当てを図に示す。この画面上に, 指定した時刻の時計を描画する関数 DisplayClock を作成した。

図 ビットマップ画面の座標の割当て

目盛りは 1 周に 60 個描画する。5 個ごとに半径 6 ピクセルの大型円形マーカを, それ以外は半径 2 ピクセルの小型円形マーカを描画する。時計の針の仕様は表のとおりである。

表 時計の針の仕様

長さ   太さ   描画精度
 秒針  中心と目盛りを結んだ長さ 1 ピクセル 6 度( 1 秒きざみ)
 分針  秒針と同じ 3 ピクセル 1 度(10 秒きざみ)
 時針  分針の 75% の長さ 7 ピクセル 1 度( 2 分きざみ)

関数 DisplayClock は,次に示す ACLOCK 構造体へのポインタを引数とする。

typedef   struct  {
  int Ready;           /* TRUE のとき目盛りの座標値を再計算しない*/
  int Hour, Minute, Second;     /* 描画する時刻               */
  int Cx, Cy;                   /* 時計の針の回転軸の座標値     */
  int Radius;                   /* 目盛りの半径               */
  int PlateX[360], PlateY[360]; /* 1度単位の目盛り座標値       */
} ACLOCK;
ACLOCK 構造体変数は,時計の中心の座標値,目盛り円の半径や座標値を記憶する。 初めて時計を描画する場合や時計の位置や大きさが変わった場合,引数である ACLOCK 構造体のメンバ変数 Ready の値を FALSE にして実行すると, 目盛りの座標値を計算して時計を描画する。

描画する時刻は,ACLOCK 構造体のメンバ変数 Hour,Minute,Second で指定する。 それぞれの値の範囲は次のとおりである。

0 ≦ Hour ≦ 23
0 ≦ Minute ≦ 59
0 ≦ Second ≦ 59

この範囲を超えた値が設定された場合は,時計は正しく描画されない。

2 点(sx, sy)と(ex, ey)を結ぶ太さ Width ピクセルの線分を描画する関数 DrawLineと,中心(x, y),半径 r ピクセルの塗りつぶした円を描く関数 DrawCircle が用意されている。それぞれの関数の原型(プロトタイプ)は,次のとおりである。

void DrawLine( int sx, int sy, int ex, int ey, int Width );

void DrawCircle( int x, int y, int r );

〔プログラム〕

#include <math.h> 
#define TRUE    1
#define FALSE   0
 
typedef  struct  {
  int    Ready;
  int    Hour, Minute, Second; 
  int    Cx, Cy;
  int    Radius;
  int    PlateX[ 360 ], PlateY[ 360 ];
} ACLOCK;
 
void    DrawLine( int sx, int sy, int ex, int ey, int Width );
void    DrawCircle( int x, int y, int r );
 
void    DisplayClock( ACLOCK *pt )
{
 const  double Rad      = 3.14159265359 / 180.0;
 const  int  LargeMark  = 6;
 const  int  SmallMark  = 2;
 const  int  HourHand   = 7;
 const  int  MinuteHand = 3;
 const  int  SecondHand = 1;
 int    angle, Size, Hx, Hy, w, x, y;
       
 if ( pt->Ready == FALSE ) {    /* 座標を計算する */
      for ( w = -90, x = y = 0; w < 270; ) {
          pt->PlateX[x] = pt->Cx + (int)(pt->Radius*cos(w*Rad));
          pt->PlateY[y] = pt->Cy + (int)(pt->Radius*sin(w*Rad));
      }
      pt->Ready = TRUE;
 }
 
 for ( angle = 0; angle < 360; angle += 6 ){ /* 目盛りを描画する */
      if (  )    Size = LargeMark;
      else               Size = SmallMark;
      DrawCircle( pt->PlateX[angle], pt->PlateY[angle], Size);
 }
 
 angle = pt->Second*6;                 /* 秒針を描く */
 DrawLine( pt->Cx, pt->Cy,  
           pt->PlateX[angle], pt->PlateY[angle], SecondHand );
 
 angle = ;                     /* 分針を描く */
 DrawLine( pt->Cx, pt->Cy,  
           pt->PlateX[angle], pt->PlateY[angle], MinuteHand );
 
 if ( pt->Hour >= 12 ) pt->Hour -= 12;
 angle = ;                     /* 時針を描く */
 Hx = ( pt->Cx + pt->PlateX[angle] ) / 2;
 Hx = ( Hx +  ) / 2;
 Hy = ( pt->Cy + pt->PlateY[angle] ) / 2;
 Hy = ( Hy + pt->PlateY[angle] ) / 2;
 DrawLine( pt->Cx, pt->Cy, Hx, Hy, HourHand );
 DrawCircle( pt->Cx, pt->Cy, pt->Radius / 10 ); /* 中心軸を描く * /
}

設問 プログラム中の に入れる正しい答えを,解答群の中から選べ。

a に関する解答群

ア w++         イ w++, x++, y++

ウ w++, x++, y--    エ w++, x+=6, y+=6

オ w+=6, x++, y++    カ w+=6, x+=6, y+=6

b に関する解答群

ア angle % 30 >= 0    イ angle % 30 != 0

ウ angle % 30 <= 30   エ angle % 30 == 0

オ angle / 30 == 0     カ angle / 30 != 0

c に関する解答群

ア pt->Minute

イ pt->Minute*6

ウ pt->Minute*6 + pt->Second

エ pt->Minute*6 + pt->Second/10

オ pt->Minute*6 + pt->Second/60

d に関する解答群

ア pt->Hour

イ pt->Hour*30

ウ pt->Hour + pt->Minute

エ pt->Hour + pt->Minute/2

オ pt->Hour*30 + pt->Minute/2

カ pt->Hour*30 + pt->Minute/60

e に関する解答群

ア pt->Cx    イ pt->Cy

ウ pt->PlateX[angle]    エ pt->PlateY[angle]

オ pt->PlateX[pt->Hour]    カ pt->PlateY[pt->Hour]


東京理科大学 infoserv 戻る 次頁:問08