«   2022/07   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
Tags
more
Archives
Today
0
Total
33,758
관리 메뉴

보안을 꿈꾸는 학생

C++ 뱀게임 프로젝트 본문

C, C++ 프로젝트

C++ 뱀게임 프로젝트

lovelyoverflow 2017. 6. 14. 21:41
Util.h
#ifndef __SCORE_H_
#ifndef __UTIL_H_
#define __UTIL_H_

#include "Common.h"
#include "Point.h"

class Util
{
public:
	void CursorUtil_Set(int x, int y);		// 커서 위치를 x, y 좌표로 이동
	Point CursorUtil_Get(void);				// 현재 커서 위치를 불러옴
	void CursorUtil_Hide(void);				// 커서를 노출하지 않게 함
};

#endif
 


Util.cpp
#ifndef __SCORE_H_
#include "Common.h"
#include "Util.h"

void Util::CursorUtil_Set(int x, int y)
{
	COORD pos = { x, y };
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

void Util::CursorUtil_Hide(void)
{
	CONSOLE_CURSOR_INFO curInfo;
	GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &curInfo);
	curInfo.bVisible = 0;
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &curInfo);
}

Point Util::CursorUtil_Get(void)
{
	CONSOLE_SCREEN_BUFFER_INFO curInfo;
	GetConsoleScreenBufferInfo(
		GetStdHandle(STD_OUTPUT_HANDLE), &curInfo);

	Point point(curInfo.dwCursorPosition.X, curInfo.dwCursorPosition.Y);
	return point;
}
 


Common.h
#ifndef __SCORE_H_
#ifndef __COMMON_H_
#define __COMMON_H_

#include 
#include 
#include 
#include 

#endif
 


Constant.h
#ifndef __SCORE_H_
#ifndef __CONSTANT_H_
#define __CONSTANT_H_

enum Direction {
	UP, DOWN, LEFT, RIGHT
};

enum KeyCode {
	UP_KEY_CODE = 72, LEFT_KEY_CODE = 75,
	RIGHT_KEY_CODE = 77, DOWN_KEY_CODE = 80,
	SPACE_BAR_KEY_CODE = 32
};

#endif

 


Point.h
#ifndef __SCORE_H_
#ifndef __POINT_H_
#define __POINT_H_

class Point
{
public:
	int x;
	int y;
public:
	Point(int X = 0, int Y = 0);

	bool operator==(Point pos);
	void operator=(Point& pos);
};

#endif

 


Point.cpp
#ifndef __SCORE_H_
#include "Point.h"

Point::Point(int X = 0, int Y = 0)
	:x(X), y(Y)
{}

bool Point::operator==(Point pos)
{
	if (x == pos.x && y == pos.y)
		return true;

	return false;
}

void Point::operator=(Point& pos)
{
	x = pos.x;
	y = pos.y;
}

 


Snake.h
#ifndef __SCORE_H_
#ifndef __SNAKE_H_
#define __SNAKE_H_

#include 
#include "Point.h"

#define START_SNAKE_POS_X	20
#define START_SNAKE_POS_Y	5

class Snake
{
private:
	std::list body;
	Point starPos;
	int direction;
private:
	void Move_UP();
	void Move_Down();
	void Move_Left();
	void Move_Right();
public:
	Snake();

	void Init();
	void Set_Direction(int key);
	void Move();
	bool Is_Bitten();
	bool Is_Collistion();
	int GetDirection();
	void SetStarPos();
	Point GetStarPos();
	std::list* GetBody();
	Point EraseTail();

	Point head();
	Point tail();
};

#endif
 


Snake.cpp
#ifndef __SCORE_H_
#include "Constant.h"
#include "Snake.h"
#include "Display.h"
#include "Util.h"
#include 
#include 

Snake::Snake()
{
}

void Snake::Init()
{
	body.clear();

	Point pos[2] = {
		{ START_SNAKE_POS_X, START_SNAKE_POS_Y },
		{ START_SNAKE_POS_X, START_SNAKE_POS_Y + 1 }
	};

	body.push_front(pos[0]);
	body.push_back(pos[1]);

	direction = KeyCode::RIGHT_KEY_CODE;
}

void Snake::Set_Direction(int key)
{
	if (direction == KeyCode::UP_KEY_CODE && key == KeyCode::DOWN_KEY_CODE)
		return;
	if (direction == KeyCode::LEFT_KEY_CODE && key == KeyCode::RIGHT_KEY_CODE)
		return;
	if (direction == KeyCode::RIGHT_KEY_CODE && key == KeyCode::LEFT_KEY_CODE)
		return;
	if (direction == KeyCode::DOWN_KEY_CODE && key == KeyCode::UP_KEY_CODE)
		return;

	direction = key;
}

void Snake::Move()
{
	switch (direction)
	{
	case KeyCode::LEFT_KEY_CODE:
		Move_Left();
		break;
	case KeyCode::RIGHT_KEY_CODE:
		Move_Right();
		break;
	case KeyCode::UP_KEY_CODE:
		Move_UP();
		break;
	case KeyCode::DOWN_KEY_CODE:
		Move_Down();
		break;
	}
}

bool Snake::Is_Bitten()
{
	auto i = body.begin();
	i++;

	while (i != body.end())
	{
		if (head() == *i)
			return true;

		i++;
	}

	return false;
}

bool Snake::Is_Collistion()
{
	Point headPos = head();
	Display display;
	int board[GBOARD_HEIGHT + 2][GBOARD_WIDTH + 2];

	display.GetBoard(board);

	switch (direction)
	{
	case KeyCode::LEFT_KEY_CODE:
		if (board[headPos.y][(headPos.x - 2) / 2] == 1)
			return true;
		break;
	case KeyCode::RIGHT_KEY_CODE:
		if (board[headPos.y][(headPos.x + 2) / 2] == 1)
			return true;
		break;
	case KeyCode::UP_KEY_CODE:
		if (board[headPos.y - 1][headPos.x / 2] == 1)
			return true;
		break;
	case KeyCode::DOWN_KEY_CODE:
		if (board[headPos.y + 1][headPos.x / 2] == 1)
			return true;
		break;
	}

	return false;
}

std::list* Snake::GetBody()
{
	return &body;
}

Point Snake::head()
{
	return body.front();
}

Point Snake::tail()
{
	return body.back();
}

void Snake::Move_UP()
{
	if (Is_Collistion() == true || Is_Bitten() == true) {
		Display().Print_Prompt("Game Over~");
		exit(-1);
	}

	Point HeadPos = { head().x, head().y - 1 };

	body.push_front(HeadPos);
}

void Snake::Move_Down()
{
	if (Is_Collistion() == true || Is_Bitten() == true) {
		Display().Print_Prompt("Game Over~");
		exit(-1);
	}

	Point HeadPos = { head().x, head().y + 1 };
	body.push_front(HeadPos);
}

void Snake::Move_Left()
{
	if (Is_Collistion() == true || Is_Bitten() == true) {
		Display().Print_Prompt("Game Over~");
		exit(-1);
	}

	Point HeadPos = { head().x - 2, head().y };
	body.push_front(HeadPos);
}

void Snake::Move_Right()
{
	if (Is_Collistion() == true || Is_Bitten() == true) {
		Display().Print_Prompt("Game Over~");
		exit(-1);
	}

	Point HeadPos = { head().x + 2, head().y };
	body.push_front(HeadPos);
}

int Snake::GetDirection()
{
	return direction;
}

void Snake::SetStarPos()
{
	srand((unsigned int)time(NULL));

	int x = (rand() % GBOARD_WIDTH + 1) * 2;
	int y = rand() % GBOARD_HEIGHT + 1;
	starPos.x = x;
	starPos.y = y;

	for (auto i = body.begin(); i != body.end(); i++)
	{
		if (starPos == *i) {
			int x = (rand() % GBOARD_WIDTH + 1) * 2;
			int y = rand() % GBOARD_HEIGHT + 1;
			starPos.x = x;
			starPos.y = y;
		}
	}
}

Point Snake::GetStarPos()
{
	return starPos;
}

Point Snake::EraseTail()
{
	Util util;
	Point tailPos = tail();

	util.CursorUtil_Set(tailPos.x, tailPos.y);
	std::cout << "  ";

	body.remove(body.back());
	return tailPos;
}

 


Display.h
#ifndef __SCORE_H_
#ifndef __DISPLAY_H_
#define __DISPLAY_H_

#define GBOARD_WIDTH	35
#define GBOARD_HEIGHT	25

#include "Snake.h"
#include 
class Display
{
private:
	static int board[GBOARD_HEIGHT + 2][GBOARD_WIDTH + 2];
public:
	Display();
	void Print_Wall();
	void Print_Food(Point pos);
	void Print_Snake(Snake snake);
	void GetBoard(int(*boa)[GBOARD_WIDTH + 2]);
	void Print_Prompt(std::string str);
	void Print_Score(Snake snake);
};

#endif
 


Display.cpp
#ifndef __SCORE_H_
#include "Common.h"
#include "Display.h"
#include "Constant.h"
#include "Util.h"
#include 
#include 

Display::Display()
{}

int Display::board[GBOARD_HEIGHT + 2][GBOARD_WIDTH + 2] = { 0, };

void Display::Print_Wall()
{
	Util util;
	Point curPos = util.CursorUtil_Get();

	for (int y = 0; y < GBOARD_HEIGHT + 2; y++) {
		board[y][0] = 1;
		board[y][GBOARD_WIDTH + 1] = 1;
	}

	for (int x = 0; x < GBOARD_WIDTH + 2; x++) {
		board[0][x] = 1;
		board[GBOARD_HEIGHT + 1][x] = 1;
	}

	for (int y = 0; y < GBOARD_HEIGHT + 2; y++)
	{
		for (int x = 0; x < GBOARD_WIDTH + 2; x++)
		{
			if (board[y][x] == 1)
			{
				util.CursorUtil_Set(curPos.x + x * 2, curPos.y + y);
				std::cout << "▩";
			}
		}
	}

	util.CursorUtil_Set(curPos.x, curPos.y);
}

void Display::Print_Food(Point pos)
{
	Util util;
	Point curPos = util.CursorUtil_Get();

	util.CursorUtil_Set(pos.x, pos.y);
	std::cout << "★";

	util.CursorUtil_Set(curPos.x, curPos.y);
}

void Display::Print_Snake(Snake snake)
{
	Util util;
	Point curPos = util.CursorUtil_Get();

	for (auto i = snake.GetBody()->begin(); i != snake.GetBody()->end(); i++)
	{
		util.CursorUtil_Set(i->x, i->y);
		std::cout << "◎";
	}
}

void Display::GetBoard(int(*boa)[GBOARD_WIDTH + 2])
{
	for (int y = 0; y < GBOARD_HEIGHT + 2; y++)
	{
		for (int x = 0; x < GBOARD_WIDTH + 2; x++)
			boa[y][x] = board[y][x];
	}
}

void Display::Print_Prompt(std::string str)
{
	std::cout << str;
}

void Display::Print_Score(Snake snake)
{
	Util util;
	Point curPos = util.CursorUtil_Get();

	util.CursorUtil_Set(80, 5);
	std::cout << "    ";
	util.CursorUtil_Set(80, 6);
	std::cout << "┏━━━━━━━━━";
	util.CursorUtil_Set(80, 7);
	std::cout << "┃ 현재 점수: " << snake.GetBody()->size() - 2;
	util.CursorUtil_Set(80, 8);
	std::cout << "┗━━━━━━━━━" << std::endl;
}

 


SnakeManager.h
#ifndef __SCORE_H_
#ifndef __SNAKE_MANAGER_H_
#define __SNAKE_MANAGER_H_

#include "Snake.h"
#include "Display.h"
#include "Point.h"
#include "Util.h"

class SnakeManager
{
private:
	Snake snake;
	Display display;
	Util util;
private:
	void Print_Tail(Point nextTail);
public:
	SnakeManager();
	void Init();
	void Game();
	void GetStar(Point before);
};

#endif
 


SnakeManager.cpp
#ifndef __SCORE_H_
#include "Common.h"
#include "Display.h"
#include "Snake.h"
#include "Constant.h"
#include "SnakeManager.h"
#include 

SnakeManager::SnakeManager()
{
	snake.Init();
};

void SnakeManager::Init()
{
	snake.Init();
	util.CursorUtil_Hide();

	display.Print_Wall();
	display.Print_Snake(snake);
	snake.SetStarPos();
	display.Print_Food(snake.GetStarPos());
	display.Print_Score(snake);
}

void SnakeManager::Game()
{
	int key;

	while (1)
	{
		if (_kbhit())
		{
			key = _getch();
			
			if (key == 224)
				key = _getch();
			else
				continue;

			snake.Set_Direction(key);
		}

		Point before = snake.EraseTail();
		snake.Move();
		display.Print_Snake(snake);

		if (snake.head() == snake.GetStarPos())
		{
			GetStar(before);
			display.Print_Score(snake);
		}

		Sleep(100);
	}
}

void SnakeManager::Print_Tail(Point nextTail)
{
	Point curPos = util.CursorUtil_Get();

	snake.GetBody()->push_back(nextTail);

	util.CursorUtil_Set(nextTail.x, nextTail.y);
	std::cout << "◎";

	util.CursorUtil_Set(curPos.x, curPos.y);
}

void SnakeManager::GetStar(Point before)
{
	Print_Tail(before);

	snake.SetStarPos();
	display.Print_Food(snake.GetStarPos());
}
 


SnakeMain.cpp
#ifndef __SCORE_H_
#include "Common.h"
#include "Snake.h"
#include "Display.h"
#include "Util.h"
#include "SnakeManager.h"

int main()
{
	SnakeManager snakeManager;
	
	snakeManager.Init();

	while (1)
		snakeManager.Game();

	return 0;
}
 

스네이크 게임 프로젝트는 올해 5월에 완성한 프로젝트 입니다.


저번 테트리스 프로젝트에 비해 Main함수가 엄청 단순해지신 것 보이시나요?

객체를 이용하여 만드니 소스 추가및 수정이 더 편해졌습니다.

 

 

'C, C++ 프로젝트' 카테고리의 다른 글

C++ 뱀게임 프로젝트  (0) 2017.06.14
C언어 테트리스 프로젝트  (1) 2017.06.14
0 Comments
댓글쓰기 폼