解答5.1

解答5.2

(a) autoは予約語なので列挙型の要素名には使用できない.

typedef enum transmisson {
  automatic. semi_automatic, manual
} Transmission;

(b) blueとredがともに値2を持つので区別できない

typedef enum bodycolor {
  black=0, red=2, orange=3, green=5, blue, silver
} Bodycolor;

解答5.3

funcを関数へのポインタの配列として定義するつもりが、 []が()より外側にあるため配列を返す関数と解釈され、コンパイルエラーになる.

さらにfunc[1]=f2を呼び出すつもりの *fp+1は(*fp)+1と解釈される. すなわちf1の開始アドレスの 次のアドレスから実行することになり、異常終了する.

正しいプログラムは以下の通り.
()や[]が複雑な入れ子になる場合はtypedefを使用して読みやすくするのが望ましい.

void f1(int x) { printf("f1=%d\n",x); }
void f2(int x) { printf("f2=%d\n",x*2); }

typedef void (*Func)(int); // intからvoidへの関数
Func func[] = {f1,f2};

int main() {
   void (**fp)() = func;
   (*fp)(1);
   (*(fp+1))(2);
   return 0;
}

解答5.4

変更点は以下のとおり.
ただし復元(ロード)の実現に関しては、現在のゲームを破棄してよいか 確認メッセージを表示する、ロード直後にgame_mainの (盤面初期化を飛ばして)whileループを最初から実行できる ようにする、などの工夫が必要である.

typedef struct {
    ...
    Move *move_list[2]; // 手の履歴記録用(0:先手,1:後手)
} Board;
void game_main() {
    ...
    input_move(&m,&b);
    append_move(&m, b.move_list[b.turn]); // 手を履歴に追加
    update_board(&m,&b);
    ...
}
int input_move(Move *mp, Board *bp) {
    input_point(&(mp1->from));
    if (resigned(mp1->from)) { ... }
    if (save_command(mp1->from)) { save_board(bp); ... }
    ...
}

なおGUIなどを利用していつでも保存/復元できるように する場合にはイベント駆動という仕組みについて学習する必要がある. 興味のある方は試みてみよ.