試験ノート - 実装ドリル 1.0
読み取り中…
検索中…
一致する文字列を見つけられません
main.c
1
53#include <stdio.h>
54#include <stdlib.h>
55#include <unistd.h>
56
57#define ALIVE '0'
58#define DEAD ' '
59
60// Error message definitions
61#define USAGE_MSG "Usage: ./life width height iterations\n"
62#define INVALID_ARGS_MSG \
63 "Invalid arguments: width, height must be positive, iterations " \
64 "non-negative.\n"
65#define MEM_ALLOC_FAIL_MSG "Memory allocation failed\n"
66
67// Structure to represent the game board
68typedef struct {
69 int width;
70 int height;
71 char **cells; // 2D array for board cells
72} Board;
73
74// Structure to represent the pen state for initial drawing
75typedef struct {
76 int x;
77 int y;
78 int is_drawing; // 0 for off, 1 for on
79} PenState;
80
81int main(int argc, char *argv[]);
82int parse_arguments(int argc, char *argv[], int *width, int *height,
83 int *iterations);
84Board *create_board_obj(int width, int height);
85void free_board_obj(Board *board_obj);
86void initialize_board_from_input(Board *board_obj, PenState *pen_state);
87void simulate_life_obj(Board *current_board, Board *next_board, int iterations);
88static int count_live_neighbors_obj(const Board *board_obj, int x, int y);
89static void copy_board_obj(Board *dest, const Board *src);
90void print_board_obj(const Board *board_obj);
91
92// Function prototypes and their descriptions:
93
116int main(int argc, char *argv[]) {
117 int width, height, iterations;
118 Board *current_board_obj = NULL;
119 Board *next_board_obj = NULL;
120 PenState pen_state;
121
122 if (!parse_arguments(argc, argv, &width, &height, &iterations)) {
123 return 1;
124 }
125
126 current_board_obj = create_board_obj(width, height);
127 next_board_obj = create_board_obj(width, height);
128
129 if (!current_board_obj || !next_board_obj) {
130 write(STDERR_FILENO, MEM_ALLOC_FAIL_MSG, sizeof(MEM_ALLOC_FAIL_MSG) - 1);
131 free_board_obj(current_board_obj);
132 free_board_obj(next_board_obj);
133 return 1;
134 }
135
136 initialize_board_from_input(current_board_obj, &pen_state);
137
138 simulate_life_obj(current_board_obj, next_board_obj, iterations);
139
140 print_board_obj(current_board_obj);
141
142 free_board_obj(current_board_obj);
143 free_board_obj(next_board_obj);
144
145 return 0;
146}
147
160int parse_arguments(int argc, char *argv[], int *width, int *height,
161 int *iterations) {
162 if (argc != 4) {
163 write(STDERR_FILENO, USAGE_MSG, sizeof(USAGE_MSG) - 1);
164 return 0; // Failure
165 }
166
167 *width = atoi(argv[1]);
168 *height = atoi(argv[2]);
169 *iterations = atoi(argv[3]);
170
171 if (*width <= 0 || *height <= 0 || *iterations < 0) {
172 write(STDERR_FILENO, INVALID_ARGS_MSG, sizeof(INVALID_ARGS_MSG) - 1);
173 return 0; // Failure
174 }
175 return 1; // Success
176}
177
195Board *create_board_obj(int width, int height) {
196 Board *new_board = (Board *)calloc(1, sizeof(Board));
197 if (!new_board) return NULL;
198
199 new_board->width = width;
200 new_board->height = height;
201 new_board->cells = (char **)calloc(height, sizeof(char *));
202 if (!new_board->cells) {
203 free(new_board);
204 return NULL;
205 }
206
207 int i = 0;
208 while (i < height) {
209 new_board->cells[i] = (char *)calloc(width, sizeof(char));
210 if (!new_board->cells[i]) {
211 // Free previously allocated rows
212 while (i > 0) {
213 free(new_board->cells[--i]);
214 }
215 free(new_board->cells);
216 free(new_board);
217 return NULL;
218 }
219 // Initialize cells to DEAD (calloc already does this with null bytes, which
220 // is fine for space char)
221 int j = 0;
222 while (j < width) {
223 new_board->cells[i][j] = DEAD;
224 j++;
225 }
226 i++;
227 }
228 return new_board;
229}
230
244void free_board_obj(Board *board_obj) {
245 if (!board_obj) return;
246 int i = 0;
247 if (board_obj->cells) {
248 while (i < board_obj->height) {
249 free(board_obj->cells[i]);
250 i++;
251 }
252 free(board_obj->cells);
253 }
254 free(board_obj);
255}
256
273void initialize_board_from_input(Board *board_obj, PenState *pen_state) {
274 char buffer;
275 int bytes_read;
276
277 // Initialize pen state
278 pen_state->x = 0;
279 pen_state->y = 0;
280 pen_state->is_drawing = 0;
281
282 while ((bytes_read = read(STDIN_FILENO, &buffer, 1)) > 0) {
283 if (buffer == 'w') {
284 if (pen_state->y > 0) pen_state->y--;
285 } else if (buffer == 'a') {
286 if (pen_state->x > 0) pen_state->x--;
287 } else if (buffer == 's') {
288 if (pen_state->y < board_obj->height - 1) pen_state->y++;
289 } else if (buffer == 'd') {
290 if (pen_state->x < board_obj->width - 1) pen_state->x++;
291 } else if (buffer == 'x') {
292 pen_state->is_drawing = !pen_state->is_drawing;
293 }
294
295 if (pen_state->is_drawing) {
296 board_obj->cells[pen_state->y][pen_state->x] = ALIVE;
297 }
298 }
299}
300
321void simulate_life_obj(Board *current_board, Board *next_board,
322 int iterations) {
323 int iter = 0;
324 while (iter < iterations) {
325 int y = 0;
326 while (y < current_board->height) {
327 int x = 0;
328 while (x < current_board->width) {
329 int live_neighbors = count_live_neighbors_obj(current_board, x, y);
330
331 if (current_board->cells[y][x] == ALIVE) {
332 if (live_neighbors < 2 || live_neighbors > 3) {
333 next_board->cells[y][x] =
334 DEAD; // Underpopulation or overpopulation
335 } else {
336 next_board->cells[y][x] = ALIVE; // Survival
337 }
338 } else {
339 if (live_neighbors == 3) {
340 next_board->cells[y][x] = ALIVE; // Reproduction
341 } else {
342 next_board->cells[y][x] = DEAD;
343 }
344 }
345 x++;
346 }
347 y++;
348 }
349 copy_board_obj(current_board, next_board);
350 iter++;
351 }
352}
353
368static int count_live_neighbors_obj(const Board *board_obj, int x, int y) {
369 int count = 0;
370 int dx, dy;
371
372 for (dx = -1; dx <= 1; dx++) {
373 for (dy = -1; dy <= 1; dy++) {
374 if (dx == 0 && dy == 0) continue;
375
376 int nx = x + dx;
377 int ny = y + dy;
378
379 if (nx >= 0 && nx < board_obj->width && ny >= 0 &&
380 ny < board_obj->height && board_obj->cells[ny][nx] == ALIVE) {
381 count++;
382 }
383 }
384 }
385 return count;
386}
387
402static void copy_board_obj(Board *dest, const Board *src) {
403 int i = 0;
404 int j;
405
406 while (i < dest->height) {
407 j = 0;
408 while (j < dest->width) {
409 dest->cells[i][j] = src->cells[i][j];
410 j++;
411 }
412 i++;
413 }
414}
415
431void print_board_obj(const Board *board_obj) {
432 int i = 0;
433 int j;
434
435 while (i < board_obj->height) {
436 j = 0;
437 while (j < board_obj->width) {
438 putchar(board_obj->cells[i][j]);
439 j++;
440 }
441 putchar('\n');
442 i++;
443 }
444}
445
// グループの終わり
void free_board_obj(Board *board_obj)
ゲーム盤のメモリ解放
Definition main.c:244
int main(int argc, char *argv[])
ライフゲーム・シミュレーターのエントリポイント
Definition main.c:116
void initialize_board_from_input(Board *board_obj, PenState *pen_state)
標準入力からペン操作を受け取り、初期盤面を作成する
Definition main.c:273
void simulate_life_obj(Board *current_board, Board *next_board, int iterations)
ライフゲームのルールに基づき、次世代の盤を計算する
Definition main.c:321
static void copy_board_obj(Board *dest, const Board *src)
ある盤の状態を別の盤に完全に複製する
Definition main.c:402
static int count_live_neighbors_obj(const Board *board_obj, int x, int y)
指定した座標の周囲(8近傍)にいる生存セル数をカウントする
Definition main.c:368
void print_board_obj(const Board *board_obj)
盤面の現在の状態を標準出力に描画する
Definition main.c:431
int parse_arguments(int argc, char *argv[], int *width, int *height, int *iterations)
コマンドライン引数のバリデーションとパース
Definition main.c:160
Board * create_board_obj(int width, int height)
ゲーム盤(Board構造体)のメモリ確保と初期化
Definition main.c:195
Definition main.c:68