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