심심해서 안드로이드 환경에서도 컴파일해서 구동가능하도록 하여 보았습니다.

/*
_WINDOW : 윈도우
_ANDROID : 안드로이드 C4Droid 기준
*/
#define _ANDROID

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <malloc.h>
#ifdef _WINDOW
#include <Windows.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); //인트로 출력 함수

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));
start:

intro();
initMap(&map, MAP_MAX_HEIGHT, MAP_MAX_WIDTH);
initSnake(&snake, 5);

while (1)
{
snakeKeyEvent(&snake);
switch (moveSnake(&map, &snake))
{
case -1:
printf("알 수 없는 오류 발생");
break;
case 1:
printf("이런 머리를 박고 사망하였습니다.\n");
#ifdef _WINDOW
_getch();
#endif
#ifdef _ANDROID
getch();
#endif
goto start;
break;
}
placeFood(&map);
mapReflesh(&map, &snake);
printMap(&map, &snake);
#ifdef _WINDOW
Sleep(80);
#endif
#ifdef _ANDROID
usleep(100000);
#endif
}


return 0;
}

void intro(void)
{
#ifdef _WINDOW
system("cls");
#endif
#ifdef _ANDROID
clrscr();
#endif
printf("==[ C로 만든 텍스트 스네이크 게임 ]==\n");
printf("\n아무 키나 누르면 시작합니다.\n");
#ifdef _WINDOW
_getch();
#endif
#ifdef _ANDROID
getch();
#endif
}
/*Pos 관련 함수 정의*/
Pos setPos(int x, int y)
{
Pos pos;
pos.x = x;
pos.y = y;

return pos;
}

/***************************
* 맵 관련 함수 정의
****************************/
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 _ANDROID
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 _ANDROID
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);
}


다음과 같은 소스 코드이며, 제일 상단 #define _ANDROID를 #define _WINDOW로 바꿔주시고 컴파일하시면 윈도우용입니다.

뭐 C4Droid에서 내보내기 한 파일이긴한데.


실행은 정말 장담 못합니다. 개인적으로 C4Droid 설치해서 해보세요.




안드로이드의 키보드로 해야되는 것이라서 조작감이 정말.... 안경에 습기찰 정도고.


조작법


이동 : WASD

일시정지 : P

재 시작 : Enter






댓글 작성