이중 동적 할당을 활용하여 원하는 크기의 미로를 만들었으며,

stack을 활용하여 탈출 가능한 미로를 판별하고, 미로 게임을 진행 하도록 프로그램을 작성하였습니다.

 

https://youtu.be/UJwUcwXcFN4?si=b-xJkZxb3YuJqPUm

 

 

stack.h

#ifndef STACK_H
#define STACK_H
typedef struct {
	int r;
	int c;
}element;

typedef struct {
	int capacity;
	int top;
	element* data;
}StackType;

void init_stack(StackType* s) {
	s->capacity = 1;
	s->top = -1;
	s->data = (element*)malloc(sizeof(element) * s->capacity);
}

int is_full(StackType* s) {
	return s->top == (s->capacity - 1);
}

int is_empty(StackType* s) {
	return s->top == -1;
}

void push(StackType* s, element item) {
	if (is_full(s)) {
		s->capacity *= 2;
		s->data = (element*)realloc(s->data, sizeof(element) * s->capacity);
	}
	s->data[++(s->top)] = item;
}

element pop(StackType* s) {
	if (is_empty(s)) {
		fprintf(stderr, "스택 공백 에러\n");
		exit(1);
	}
	else return s->data[(s->top)--];
}

void break_stack(StackType* s) {
	free(s->data);
}

#endif

 

 

maze.h

#ifndef MAZE_H
#define MAZE_H

element here, entry;
char** maze;
int heart = 3;

void print_maze(element size) {
	printf("\n");
	for (int i = 0; i < size.r; i++) {
		for (int j = 0; j < size.c; j++) {
			printf("%c", maze[i][j]);
		}
		printf("\n");
	}
}

void make_maze(element size) {
	maze = (char**)malloc(sizeof(char*) * size.r);
	for (int i = 0; i < size.r; i++) {
		maze[i] = (char*)malloc(sizeof(char) * size.c);
	}
}

void input_random_maze(element size) {

	for (int i = 0; i < size.r; i++) {
		for (int j = 0; j < size.c; j++) {
			if (i == 0 || j == 0 || size.r - 1 == i || size.c - 1 == j)
				maze[i][j] = '1';
			else
				maze[i][j] = rand() % 2 + '0';
		}
	}
	maze[rand() % (size.r - 2) + 1][rand() % (size.c - 2) + 1] = 'x';

	entry.r = rand() % (size.r - 2) + 1;
	entry.c = rand() % (size.c - 2) + 1;
	maze[entry.r][entry.c] = 'e';
}

int push_loc(StackType* s, int r, int c, element size) {
	//printf("%d %d\n", r, c);
	if (r < 0 || r > size.r - 1 || c < 0 || c>size.c - 1) { // 미로의 테두리가 무조건 '1' 이기 때문에 없어도 되는 조건이긴 하다
		//printf("리턴\n");
		return 0;
	}
	if (maze[r][c] != '.' && maze[r][c] != '1') {
		element temp;
		temp.r = r;
		temp.c = c;
		push(s, temp);
		return 1;
	}
	else if (maze[r][c] == '1') {
		heart--;
		return 0;
	}
}

int check_maze(element size) {
	StackType s;
	int r, c;
	init_stack(&s);

	here = entry;
	while (maze[here.r][here.c] != 'x') {
		r = here.r;
		c = here.c;
		maze[r][c] = '.';
		push_loc(&s, r - 1, c, size);
		push_loc(&s, r, c - 1, size);
		push_loc(&s, r + 1, c, size);
		push_loc(&s, r, c + 1, size);

		if (is_empty(&s)) {
			break_stack(&s);
			return 0;
		}
		else {
			here = pop(&s);
		}
	}
	break_stack(&s);
	return 1;
}

void init_maze(element size) {

	for (int i = 0; i < size.r; i++)
		for (int j = 0; j < size.c; j++)
			if (maze[i][j] == '.')
				maze[i][j] = '0';

	maze[entry.r][entry.c] = 'e';
	heart = 3;
}


void print_heart() {

	for (int i = 0; i < heart; i++) {
		printf("♥");
	}
	for (int i = 0; i < 3 - heart; i++) {
		printf("♡");
	}
}

void break_maze(element size) {
	for (int i = 0; i < size.r; i++) {
		free(maze[i]);
	}
	free(maze);
}

int get_score(double duration) {
	int score;
	if (heart == 3) score = 100;
	else if (heart == 2) score = 75;
	else score = 50;

	if (duration < 30)
		score *= 1.5;
	else if (duration < 60)
		score *= 1.25;
	else if (duration < 90)
		score *= 1.;
	else if (duration < 120)
		score *= 0.8;
	else
		score *= 0.6;

	return score;
}

#endif

 

main.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h> 
#include <time.h>
#include <conio.h>
#include <Windows.h>
#include "stack.h"
#include "maze.h"

int main() {
	srand(time(NULL));
	StackType s;
	element size;
	int r, c, count = 0, ch1, ch2;
	double duration;
	clock_t start, finish;
	init_stack(&s);

	printf("미로의 크기를 입력하시오(예시: 6x6):");
	scanf("%d x %d", &size.r, &size.c);

	while (1) {

		make_maze(size);
		//input_maze(size);
		input_random_maze(size);
		printf("--- 초기 미로 맵 ---\n");
		print_maze(size);
		printf("--------------------\n");
		if (check_maze(size)) {
			init_maze(size);
			printf("미로 탈출을 시작합니다.\n");
			start = clock();
			break;
		}
		else {
			Sleep(1000);
			printf("탈출 불가능한 미로가 생성되었습니다.\n");
			printf("미로를 재 생성합니다.\n");
			Sleep(1000);
			system("cls");
		}
	}

	Sleep(2000);
	here = entry;
	while (maze[here.r][here.c] != 'x') {
		r = here.r;
		c = here.c;
		maze[r][c] = '.';
		system("cls");
		printf("[%d번째 이동]--------------------", ++count);
		print_heart();
		print_maze(size);
		printf("-------------------------------\n");

		while (1) {
			Sleep(1000);
			fflush(stdin);
			if (heart == 0) {
				printf("목숨이 다했습니다.\n");
				printf("미로 탈출 실패\n");
				break_maze(size);
				break_stack(&s);
				return 0;
			}

			if (_kbhit()) {
				ch1 = _getch();
				if (ch1 == 224) {
					ch2 = _getch();
					if (ch2 == 72) {
						if (push_loc(&s, r - 1, c, size) == 0) {
							system("cls");
							printf("[%d번째 이동]--------------------", ++count);
							print_heart();
							print_maze(size);
							printf("-------------------------------\n");
							continue;
						}
						break;
					}
					else if (ch2 == 80) {
						if (push_loc(&s, r + 1, c, size) == 0) {
							system("cls");
							printf("[%d번째 이동]--------------------", ++count);
							print_heart();
							print_maze(size);
							printf("-------------------------------\n");
							continue;
						}
						break;
					}
					else if (ch2 == 75) {
						if (push_loc(&s, r, c - 1, size) == 0) {
							system("cls");
							printf("[%d번째 이동]--------------------", ++count);
							print_heart();
							print_maze(size);
							printf("-------------------------------\n");
							continue;
						}
						break;
					}
					else if (ch2 == 77) {
						if (push_loc(&s, r, c + 1, size) == 0) {
							system("cls");
							printf("[%d번째 이동]--------------------", ++count);
							print_heart();
							print_maze(size);
							printf("-------------------------------\n");
							continue;
						}
						break;
					}

					//switch (ch2) { // switch 랑 goto 같이 쓰는 것보다 if 랑 break 쓰는게 더 좋을 듯 싶음
					//printf("화살표 누름\n");
					//case 72: push_loc(&s, r - 1, c, size); goto next;// 상 
					//case 80: push_loc(&s, r + 1, c, size); goto next;// 하
					//case 75: push_loc(&s, r, c - 1, size); goto next;// 좌
					//case 77: push_loc(&s, r, c + 1, size); goto next;// 우
					//}

				}
			}
		}
		// next:
		if (is_empty(&s)) {
			printf("미로 탈출 실패\n");
			break_maze(size);
			break_stack(&s);
			return 0;
		}
		else {
			here = pop(&s);
			//printf("here: %d %d\n", here.r, here.c);
		}

	}
	finish = clock();
	printf("미로 탈출 성공\n");
	duration = (double)(finish - start) / CLOCKS_PER_SEC;
	printf("미로를 탈출하는데 %.2f초 걸렸습니다.\n", duration);
	printf("score: %d\n", get_score(duration));
	break_maze(size);
	break_stack(&s);
}

+ Recent posts