프로그래밍/C++언어 2016. 6. 7. 04:49

맨 처음 문제가

1. 포인터

2. 동적할당

3. 파일입출력

4. 텍스트 게임 금지(글로만 된 스토리 게임)


필자는 곰곰히 생각하고 하루만에 구현 할 수 있는 쉽고 재밌는 게임인 오목을 만들기로 했다. 


또한, 규칙은 복잡하니 단 하나 5개이상으로 연결만 되면 승리 라는 소박한 규칙만 만들었다.


맨 처음으로 Define.h / Define.cpp 를 만들었다. 필자의 프로그래밍 습관이기도 한데 #include XXX 이렇게 계속 선언할 것을 그냥 헤더파일 하나로 모았다.

// Define.h

#pragma once

#include<iostream>

#include<Windows.h>

#include<conio.h>

using namespace std;

void gotoxy(int x, int y);  // 이동을 지시해 줄 함수

enum { LEFT = 75, RIGHT = 77, UP = 72, DOWN = 80, SPACE = 32 };


// Define.cpp

#include"Define.h"

void gotoxy(int x, int y)

{

COORD Pos = { x,y };

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);

}


그 다음 게임을 만들기 위해서 이동을 해야되지 않겠는가? 필자는 CPoint.h / CPoint.cpp로 그리는 함수, 움직이게 키를 받는 함수, 승리 조건 체크 함수를 만들었다.


// CPoint.h

#pragma once

#include"map.h"

class CPoint : public MAP

{

int x; // x좌표

int y; // y좌표

public:

CPoint(int x, int y); // 생성자

void screen(); // 그리는 함수

void input(int &p); //키를 입력 받는 함수

bool check(int &p); // 승리 조건 체크 함수

};


// CPoint.cpp

#include"CPoint.h"

CPoint::CPoint(int x, int y)

{

this->x = x;

this->y = y;

}

void CPoint::screen()

{

system("cls");

for (int j = 0; j < Get_height(); j++)

{

for (int i = 0; i < Get_width(); i++)

{

if (xy[j][i] == 1)

cout << "★";

else if (xy[j][i] == 2)

cout << "☆";

else if (xy[j][i] == 0)

cout << "╋";

}

cout << "\n";

}

}

void CPoint::input(int &p)

{

int c;

bool turn = true;

while (turn)

{

c = getch();

switch (c)

{

case RIGHT:

{

++x;

if (x >= Get_width() - 1)

--x;

gotoxy(x * 2, y);

break;

}

case LEFT:

{

--x;

if (x <= 0)

++x;

gotoxy(x * 2, y);

break;

}

case UP:

{

--y;

if (y <= 0)

++y;

gotoxy(x * 2, y);

break;

}

case DOWN:

{

++y;

if (y >= Get_height() - 1)

--y;

gotoxy(x * 2, y);

break;

}

case SPACE:

if (xy[y][x] != 0)

break;

if (p == 2)

{

xy[y][x] = 2;

}

else

{

xy[y][x] = 1;

}

turn = false;

break;

}

}

}

bool CPoint::check(int &p)

{

int j, sum = 0;

for (j = -5; j <= 5; j++) // 좌우 체크

{

if (x + j <= 0 || x + j >= Get_width())

continue;

if (p == xy[y][x + j])

{

sum++;

if (sum == 5)

return false;

}

else

sum = 0;

}

for (j = -5; j <= 5; j++) // 상하 체크

{

if (y + j <= 0 || y + j >= Get_height())

continue;

if (p == xy[y + j][x])

{

sum++;

if (sum == 5)

return false;

}

else

sum = 0;

}

for (j = -5; j <= 5; j++) // 오른쪽 위 왼쪽 아래 체크

{

if (y + j <= 0 || y + j >= Get_height())

continue;

if (x + j <= 0 || x + j >= Get_width())

continue;

if (p == xy[y + j][x + j])

{

sum++;

if (sum == 5)

return false;

}

else

sum = 0;

}

for (j = -5; j <= 5; j++) // 왼쪽 위 오른쪽 아래 체크

{

if (y + j <= 0 || y + j >= Get_height())

continue;

if (x + j <= 0 || x + j >= Get_width())

continue;

if (p == xy[y + j][x - j])

{

sum++;

if (sum == 5)

return false;

}

else

sum = 0;

}

return true;

}


그 다음 맵을 만들려고 했다. 그런데 아까 문제중 파일 입출력을 사용하라고 했는데 오목에서 파일 입출력을 받을 것이라고는 맵 / 랭킹정도 밖에 없다고 생각했다. 하지만 필자는 하루동안 (4시간) 만들어야하는 사명을 가지고 있으므로 맵만 파일입출력을 받기로 했다. 맵 받는게 무진장 쉽다고 생각한 것은 내 착오였다. 

일단 텍스트로 맵 정보를 받는데, 그 크기를 자유자제로 조정할 수 있어야 하므로 맵을 읽어 드리는 2차원 배열또한 크기가 자유자제로 바뀌어야한다. 하지만 여러분들은 (필자포함) 배열의 인덱스는 변경될 수 없다고 배웠을 것이다. 실제로 배열 인덱스에 변수를 넣으면 "변수 넣지마 꺼져" 라는 컴파일 에러를 발견하게 될 것이다 (VS2015기준 / C99였나부터 잘 모르겠지만 가변변수가 배열 인덱스에 허용된다고 한다.) 


따라서 필자는 동적할당으로 배열을 만들겠다는 망상을 가지고 map.h / map.cpp를 만들었다.


//map.h

#pragma once

#include"Define.h"

class MAP

{

private:

int width; // 넓이

int height; // 높이

public:

int **xy=NULL; // 동적할당을 위한 더블포인터 xy

void Init(); // 초기화

void Release(); // 메모리 해제

int Get_width(); // 넓이 가져오기

int Get_height(); // 높이 가져오기

};


//map.cpp

#include"map.h"

void MAP::Init()

{

FILE *fp = fopen("mapsize.txt", "r");

int ret = 0;

while (ret != EOF)

ret = fscanf(fp, "%d %d", &width, &height);

xy = new int*[height];

for (int i = 0; i < height; i++)

{

xy[i] = new int[width];

memset(xy[i], 0, sizeof(int)*width);

}

}

void MAP::Release()

{

for (int i = 0; i < height; i++)

delete xy[i];

}

int MAP::Get_height() { return height; }

int MAP::Get_width() { return width; }



마지막으로 대망의 main.cpp를 만들 차례이다!


//main.cpp

#include"Define.h"

#include"CPoint.h"

int main()

{

CPoint cpt(1, 1);

cpt.Init();

int user = 1;

bool check = true;

char name[2][256];

for (int i = 0; i < 2; i++)

{

cout << i + 1 << "번째 님의 이름을 입력:\n";

cin >> name[i];

}

for (int j = 0; j < cpt.Get_height(); j++)

for (int i = 0; i < cpt.Get_width(); i++)

cpt.xy[j][i] = 0;

cpt.screen();

while (check)

{

gotoxy(0, 20);

cout << name[user - 1] << "님 차례";

cpt.input(user);

cpt.screen();

check = cpt.check(user);

if (user == 1)

user = 2;

else

user = 1;

}

gotoxy(0, 20);

cout << name[user - 2] << "님의 승리" << endl;

cpt.Release();

}


이것으로 오목을 4시간(실제 작업시간은 7시간) 만에 만들고 잤다. 사실 시간이 가장 걸렸던건 2차원 배열을 동적으로 받는것에서 3시간을 날렸다. 후... 다시는 하기 싫은 노가다였다.

posted by 천마서생
: