스네이크 게임을 그냥 할 것 없을 때 마다 만들어서 드디어 만들었네요.


소스는 따로 분할하지 않고 그냥 하나에 통파일로 만들었습니다.




#include <stdio.h>

#include <conio.h>

#include <stdlib.h>

#include <time.h>

#include <malloc.h>

#include <Windows.h>


/*상수 정의*/

#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 snakeMoveEvent(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)

{

snakeMoveEvent(&snake);

switch (moveSnake(&map, &snake))

{

case -1:

printf("알 수 없는 오류 발생");

break;

case 1:

printf("이런 머리를 박고 사망하였습니다.\n");

_getch();

goto start;

break;

}

placeFood(&map);

mapReflesh(&map, &snake);

printMap(&map, &snake);

Sleep(80);

}


return 0;

}


void intro(void)

{

system("cls");

printf("┌───────────┐\n");

printf("│C로 만든 스네이크 게임│\n");

printf("└───────────┘\n");

printf("│아무 키나 누르면 시작합니다.\n");

_getch();

}

/*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;


system("cls");

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;

}

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 snakeMoveEvent(Snake* snake)

{

if (_kbhit())

{

switch (_getch())

{

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;

}

}

}


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

}


소스코드 전문입니다.


snake, map 이 두가지는 전역 변수로 하면 훨 편했겠지만 그냥 포인터로 넘겨가면서 했습니다.


조작법은 WASD 이 4가지 키로 하며, 일반적인 스네이크 게임과 룰은 같습니다.




하단은 다운로드 파일입니다.


바이러스 있을리가 없습니다. 의심가시면 위에 소스코드 전문 복사하셔서 직접 컴파일하셔도 좋습니다


스네이크 게임.exe