EXAM DRILL 1.0
読み取り中…
検索中…
一致する文字列を見つけられません
[Lv2] Life of Game

詳解

練習のテーマ

全体シーケンス

処理フロー

関数詳解

◆ main()

int main ( int  argc,
char *  argv[] 
)

ライフゲーム・シミュレーターのエントリポイント

全体の実行フロー(練習の要点)

  1. 引数パース: parse_arguments() を呼び出し、実行に必要なパラメータを取得する。
  2. メモリ確保: current_board_objnext_board_obj の2つを生成する。
    注意
    片方の確保に失敗した場合、既に確保した方を解放して異常終了すること。
  3. 初期化: initialize_board_from_input() を呼び出し、ユーザー入力から初期盤面を作成する。
  4. シミュレーション: simulate_life_obj() を実行し、指定世代数後の状態を計算する。
  5. 結果出力: 最終的な盤面を print_board_obj() で表示する。
  6. 後処理: 使用した全ての Board オブジェクトを解放し、メモリリークがない状態で終了する。
引数
argcコマンドライン引数の個数
argvコマンドライン引数の配列
戻り値
int 終了ステータス (0: 正常終了, 1: 異常終了)

main.c117 行目に定義があります。

◆ parse_arguments()

int parse_arguments ( int  argc,
char *  argv[],
int *  width,
int *  height,
int *  iterations 
)

コマンドライン引数のバリデーションとパース

チェック項目

  • 引数の個数が正しいか(プログラム名を含めて4つ)。
  • width, height が正の整数か。
  • iterations が0以上の整数か。
覚え書き
エラー時は標準エラー出力に適切なメッセージを表示して終了してください。
戻り値
1: 成功, 0: 失敗

main.c161 行目に定義があります。

◆ create_board_obj()

Board * create_board_obj ( int  width,
int  height 
)

ゲーム盤(Board構造体)のメモリ確保と初期化

実装のステップ

  1. Board構造体自体のメモリを calloc 等で確保する。
  2. 指定された height 分の char* 配列(行)を確保する。
  3. 各行に対して width 分の char 配列(セル)を確保する。
  4. すべてのセルを死滅状態(DEAD)で初期化する。
覚え書き
途中のメモリ確保で失敗した場合は、それまでに確保したメモリをすべて解放(ロールバック)し、 メモリリークを防ぐように実装してください。
引数
[in]width盤の横幅
[in]height盤の縦幅
戻り値
生成されたBoardへのポインタ(失敗時はNULL)

main.c196 行目に定義があります。

◆ free_board_obj()

void free_board_obj ( Board board_obj)

ゲーム盤のメモリ解放

実装のステップ

  1. 2次元配列 cells の各行を順次解放する。
  2. 行ポインタの配列自体を解放する。
  3. Board構造体本体を解放する。
注意
board_obj が NULL の場合にアクセスしないようガードを入れてください。
引数
board_obj解放するBoardオブジェクトへのポインタ

main.c245 行目に定義があります。

◆ initialize_board_from_input()

void initialize_board_from_input ( Board board_obj,
PenState pen_state 
)

標準入力からペン操作を受け取り、初期盤面を作成する

操作コマンドの定義

  • w, a, s, d: ペン座標の移動(上下左右)
  • x: ペンの「描画中/非描画」状態の切り替え(トグル)

実装のステップ

  1. ペンの初期位置を (0,0)、描画状態を OFF に設定する。
  2. 標準入力から1文字ずつ読み込む(read 等を使用)。
  3. 入力文字に応じてペン座標を更新する(盤外に出ないよう制御)。
  4. ペンの状態が「描画中」であれば、現在の座標のセルを ALIVE に更新する。
引数
[in,out]board_obj編集対象の盤
[in,out]pen_stateペンの座標や描画状態を保持する構造体

main.c274 行目に定義があります。

◆ simulate_life_obj()

void simulate_life_obj ( Board current_board,
Board next_board,
int  iterations 
)

ライフゲームのルールに基づき、次世代の盤を計算する

ライフゲームの基本ルール

  • 誕生: 死んでいるセルに隣接する生存セルがちょうど3つあれば、次は生存。
  • 生存: 生きているセルに隣接する生存セルが2つか3つなら、次は生存。
  • 過疎・過密: それ以外の場合、次の世代では死滅する。

実装のステップ

  1. 指定された iterations 回数だけ以下の処理を繰り返す。
  2. 全セルをループで走査し、各マスの「次の状態」を count_live_neighbors_obj() を使って判定する。
  3. 判定結果を next_board に書き込む。
  4. すべての更新が終わったら、next_board の内容を current_board にコピーする。copy_board_obj()
引数
[in,out]current_board現在の世代(処理後、次世代に書き換わる)
[in]next_board作業用のバッファ盤
[in]iterationsシミュレーションを回す世代数

main.c322 行目に定義があります。

◆ count_live_neighbors_obj()

static int count_live_neighbors_obj ( const Board board_obj,
int  x,
int  y 
)
static

指定した座標の周囲(8近傍)にいる生存セル数をカウントする

実装のステップ

  1. 対象座標 (x, y) の周囲1マス(-1 〜 +1)をループで走査する。
  2. 自分自身の座標 (0, 0) はカウントから除外すること。
  3. 走査先の座標が盤の範囲内(0 <= x < width 等)にあるかチェックする。
  4. 範囲内のセルが ALIVE であればカウントを増やす。
引数
[in]board_obj参照する盤
[in]x対象のX座標
[in]y対象のY座標
戻り値
生存している近傍セルの数 (0〜8)

main.c369 行目に定義があります。

◆ copy_board_obj()

static void copy_board_obj ( Board dest,
const Board src 
)
static

ある盤の状態を別の盤に完全に複製する

実装のステップ

  1. 二重ループ(y, x)を使用して、全てのセルの座標を走査する。
  2. src->cells[y][x] の値を dest->cells[y][x] に代入する。
注意
両方の盤の widthheight が同一であることを前提としますが、 実装ミスを防ぐため、コピー前にサイズの一致を確認する処理を入れるとより安全です。
引数
[out]destコピー先の盤(上書きされる)
[in]srcコピー元の盤(参照のみ)

main.c403 行目に定義があります。

◆ print_board_obj()

void print_board_obj ( const Board board_obj)

盤面の現在の状態を標準出力に描画する

実装のステップ

  1. 外側のループで「行(y座標)」を走査する。
  2. 内側のループで「列(x座標)」を走査し、putchar() 等でセル内の文字を表示する。
  3. 各行の終わりには必ず改行文字(\n)を出力 する。
覚え書き
DEAD はスペース(' ')、ALIVE はゼロ('0')など、定義されたマクロを使用して 出力内容を切り替えてください。
引数
[in]board_obj出力対象の盤

main.c432 行目に定義があります。