이게 뭐라고 또 올립니다...;
사실 테트리스를 만들려다가 급 귀찮아지면 같은 솔루션안에 묶여있는 스네이크 프로젝트를 열고 머리를 비우고 스네이크 게임을 하게 되더라구요...
그러다가 이거좀 고쳐볼까? 생각하게되고 조금 뜯어고쳐보는거죠.
/*
_WINDOW : 윈도우
_C4DROID : 안드로이드 C4Droid 기준
*/
#define _WINDOW
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <malloc.h>
#ifdef _WINDOW
#include <Windows.h>
#include <conio.h>
#endif
#ifdef _C4DROID
#include <conio.h>
#endif
/*상수 정의*/
#define EMPTY 0
#define WALL 1
#define SNAKE 2
#define FOOD 3
#define UP 0
#define DOWN 1
#define LEFT 2
#define RIGHT 3
/*각종 구조체*/
typedef struct Pos {
int x;
int y;
}Pos;
typedef struct Map {
int** map;
int max_height;
int max_width;
int food_count;
Pos food;
}Map;
typedef struct Snake {
Pos head;
Pos* bodys;
int body_length;
int way;
}Snake;
/*함수 선언*/
void intro(void); //인트로 출력 함수
void gameStart(Map* map, Snake* snake); //게임 시작 함수
Pos setPos(int x, int y); //편의를 위한 좌표 반환 함수
void initMap(Map* map, int height, int width); //맵 기본 설정
void setWall(Map* map); //벽을 설정함
void printMap(const Map* map, const Snake* snake); //맵 출력
char getObjectSymbol(int code); //각 오브젝트 코드별 문자를 반환(아스키코드 내에서만 가능)
void mapReflesh(Map* map, const Snake* snake); //맵에 오브젝트들을 새로고침 함.
void placeFood(Map *map); //맵에 푸드를 배치함.
void initSnake(Snake* snake, int default_length); //스네이크 기본 설정
int moveSnake(Map* map, Snake* snake); //스네이크 이동
void snakeKeyEvent(Snake* snake); //스네이크 이동 경로 변경
void addSnakeBody(Snake* snake); //스네이크 몸 길이 증가
void eatFood(Map* map, Snake* snake); //스네이크가 음식을 먹음
int main(void)
{
const int MAP_MAX_HEIGHT = 20;
const int MAP_MAX_WIDTH = 20;
Map map; //맵
Snake snake; //스네이크
srand(time(NULL));
while (1)
{
intro();
initMap(&map, MAP_MAX_HEIGHT, MAP_MAX_WIDTH);
initSnake(&snake, 5);
gameStart(&map, &snake);
}
return 0;
}
void intro(void)
{
#ifdef _WINDOW
system("cls");
#endif
#ifdef _C4DROID
clrscr();
#endif
printf("==[ C로 만든 텍스트 스네이크 게임 ]==\n");
printf("\n아무 키나 누르면 시작합니다.\n");
#ifdef _WINDOW
_getch();
#endif
#ifdef _C4DROID
getch();
#endif
}
/*Pos 관련 함수 정의*/
Pos setPos(int x, int y)
{
Pos pos;
pos.x = x;
pos.y = y;
return pos;
}
void gameStart(Map* map, Snake* snake)
{
while (1)
{
snakeKeyEvent(snake);
switch (moveSnake(map, snake))
{
case -1:
printf("알 수 없는 오류 발생");
break;
case 1://사망
printf("이런 머리를 박고 사망하였습니다.\n");
/*메모리 반환*/
free(snake->bodys);
#ifdef _DEBUG
printf("[Debug] snake.bodys 메모리 반환 완료\n");
#endif
free(map->map);
#ifdef _DEBUG
printf("[Debug] map.map 메모리 반환 완료\n");
#endif
#ifdef _WINDOW
_getch();
#endif
#ifdef _C4DROID
getch();
#endif
return;
}
placeFood(map);
mapReflesh(map, snake);
printMap(map, snake);
#ifdef _WINDOW
Sleep(80);
#endif
#ifdef _C4DROID
usleep(100000);
#endif
}
}
/***************************
* 맵 관련 함수 정의
****************************/
void setWall(Map *map)
{
int i;
/*상단 벽면 설정*/
for (i = 0; i < map->max_width; i++)
map->map[i][0] = WALL;
/*좌측 벽면 설정*/
for (i = 0; i < map->max_height; i++)
map->map[0][i] = WALL;
/*하단 벽면 설정*/
for (i = 0; i < map->max_width; i++)
map->map[i][map->max_height - 1] = WALL;
/*우측 벽면 설정*/
for (i = 0; i < map->max_height; i++)
map->map[map->max_width - 1][i] = WALL;
}
void printMap(const Map* map, const Snake* snake)
{
int i, j;
#ifdef _WINDOW
system("cls");
#endif
#ifdef _C4DROID
clrscr();
#endif
for (i = 0; i < map->max_height; i++)
{
for (j = 0; j < map->max_width; j++)
putchar(getObjectSymbol(map->map[j][i]));
/*추가 출력*/
switch (i)
{
case 0:
printf(" - 길이 : %d", snake->body_length + 1);
break;
#ifdef _DEBUG
case 1:
printf(" - D:헤드 좌표 : (%d, %d)", snake->head.x, snake->head.y);
break;
case 2:
printf(" - D:진행 방향 : %d", snake->way);
break;
#endif
}
putchar('\n');
}
}
char getObjectSymbol(int code)
{
switch (code)
{
case EMPTY:
return ' ';
case WALL:
return '@';
case SNAKE:
return '#';
case FOOD:
return '*';
default:
return 'E';
}
}
void initMap(Map* map, int height, int width)
{
int i;
map->max_height = height;
map->max_width = width;
map->food_count = 0;
map->map = (int**)malloc(sizeof(int*) * width);
for (i = 0; i < width; i++)
{
map->map[i] = (int*)malloc(sizeof(int) * height);
}
}
void mapReflesh(Map* map, const Snake* snake)
{
int i, j;
/*비움*/
for (i = 0; i < map->max_width; i++)
{
for (j = 0; j < map->max_height; j++)
{
map->map[i][j] = EMPTY;
}
}
/*벽 표시*/
setWall(map);
/*스네이크 표시*/
map->map[snake->head.x][snake->head.y] = SNAKE;
for (i = 0; i < snake->body_length; i++)
{
map->map[snake->bodys[i].x][snake->bodys[i].y] = SNAKE;
}
/*푸드 표시*/
map->map[map->food.x][map->food.y] = FOOD;
}
void placeFood(Map *map)
{
if (map->food_count == 0)
{
do
{
map->food = setPos((rand() % (map->max_width - 2) + 1), (rand() % (map->max_height - 2) + 1));
map->food_count = 1;
} while (map->map[map->food.x][map->food.y] == SNAKE);
}
}
/*****************************
* 스네이크 관련 함수 정의
******************************/
void initSnake(Snake* snake, int default_length)
{
int i;
snake->way = RIGHT;
snake->head = setPos(4, 4);
snake->bodys = (Pos*)malloc(sizeof(Pos) * default_length);
snake->body_length = default_length;
for (i = 0; i < default_length; i++)
{
snake->bodys[i] = snake->head;
}
}
int moveSnake(Map* map, Snake* snake)
{
int i;
int x = snake->head.x, y = snake->head.y; //뱀 헤드 좌표의 임시 변수
Pos temp_pos;
Pos temp_pos2;
temp_pos = snake->head;
switch (snake->way)
{
case UP:
switch (map->map[x][y - 1])
{
case FOOD: eatFood(map, snake);
case 0:
snake->head.y--;
break;
case 1:
case 2:
return 1;
}
break;
case DOWN:
switch (map->map[x][y + 1])
{
case FOOD: eatFood(map, snake);
case 0:
snake->head.y++;
break;
case 1:
case 2:
return 1;
}
break;
case LEFT:
switch (map->map[x - 1][y])
{
case FOOD: eatFood(map, snake);
case 0:
snake->head.x--;
break;
case 1:
case 2:
return 1;
}
break;
case RIGHT:
switch (map->map[x + 1][y])
{
case FOOD: eatFood(map, snake);
case 0:
snake->head.x++;
break;
case 1:
case 2:
return 1;
}
break;
default:
return -1;
}
for (i = 0; i<snake->body_length; i++)
{
temp_pos2 = snake->bodys[i];
snake->bodys[i] = temp_pos;
temp_pos = temp_pos2;
}
return 0;
}
void snakeKeyEvent(Snake* snake)
{
#ifdef _WINDOW
if (_kbhit())
{
switch (_getch())
#endif
#ifdef _C4DROID
if (kbhit())
{
switch (getch())
#endif
{
case 'w':
case 'W':
if (!(snake->way == DOWN))
snake->way = UP;
break;
case 'a':
case 'A':
if (!(snake->way == RIGHT))
snake->way = LEFT;
break;
case 's':
case 'S':
if (!(snake->way == UP))
snake->way = DOWN;
break;
case 'd':
case 'D':
if (!(snake->way == LEFT))
snake->way = RIGHT;
break;
case 'p':
case 'P':
getchar();
}
}
}
void addSnakeBody(Snake* snake)
{
snake->body_length++;
snake->bodys = (Pos*)realloc(snake->bodys, sizeof(Pos) * snake->body_length);
}
void eatFood(Map* map, Snake* snake)
{
map->food_count = 0;
addSnakeBody(snake);
}
'프로그래밍 > C' 카테고리의 다른 글
[C] 스네이크 게임, 전각 문자 사용 (0) | 2017.01.24 |
---|---|
[C] 스네이크 게임 (안드로이드 C4Droid 지원) (0) | 2016.09.21 |
[C] 스네이크 게임 (0) | 2016.09.12 |
[C] 리눅스 환경에서 컴파일 (0) | 2016.08.09 |
[C] 각종 자료형들 크기 알아보기 (0) | 2016.07.08 |