에디의 우당탕탕 코딩공장

[객체지향프로그래밍(2)] Midterm Test Report #2번 풀이

by 인턴 에디
2️⃣ You will  provide a map editing functionality. This utility is provided as a separate program. When you start a program, it shows an empty map and two buttons below the map showing "Save" or "Exit" only. Inside the map space, a user can click to any of the cells to add an obstacle  on it . If you click again on the cell marked with the obstacle, the cell will be marked back with no obstacle. After adding obstacles on the map, you may click to save the map obstacles to a file, which will then be used for your next Tetris game, which loads the map obstacle information from the file and start from it automatically. If you remove the file from the file system manually, the Tetris game will start with no obstacles.

 

1. Shows an empty map and two buttons.

//TetrisMapMaker.h
class TetrisMapMaker :
    public Panel
{
    bool        isCompleted;
    Map*        map;    // cache
    
public:
    TetrisMapMaker() 
        : Panel("", Position{ 1, 1 }, 77, 30, nullptr), 
        isCompleted(false)
    {      
        map = new Map{ Position{5,5}, 10, 20, this };
        
        new Button{ Position{0,0},EventType::continueGame,new Panel{"Save", Position{20,2}, 10, 2, this} };
        new Button{ Position{0,0},EventType::exitGame,new Panel{"Exit", Position{20,7}, 10,2, this} };
    }

 

2. Make user can click to any of the cells to add an obstacle on it. If user clicks again on the cell marked with the obstacle, the cell will be marked back with no obstacle.

//map.h
//클릭했을때 이미 장애물이 설치되어있으면 true 반환
bool isObstacleExist(Position pos) const {
	if (getShape(pos) == ' ') return false;
	return true;
}

//장애물이 설치되어있으면 장애물 삭제
bool deleteObstacle(Position pos) {
	if (!isObstacleExist(screen2local(pos))) return false;	
	setShape(' ', screen2local(pos));
	return true;
}


//클릭한 장소에 장애물 설치
void place(const Position& pos) { setShape(rect, screen2local(pos));}
//TetrisMapMaker
 void update() override {
EventType eventType = eventsystem->getCurrentEvenetType();
Position mousepos = input->getMousePosition();

if (input->getMouseButtonDown(0))
{
            if (!map->isValidRange(mousepos)) return;
            if (map->deleteObstacle(mousepos)) return;
            map->place(mousepos);
}             
}

 

3. After adding obstacles on the map, user can click to save the map obstacles to a file.

데이터 클래스를 따로 만들었다. 객체를 생성해야 할 필요성을 느끼지 못해서 전역함수로 선언 및 정의하였다.

static void saveMapdata(const char* data,int sz)
{
//16바이트 문자처리 때문에, 파일을 저장 할때는 0,1로 변환하여 저장하였다.
    string dt="";
    dt.append(data);
    char from = '\xdb';
    char to = '1';
    replace(dt.begin(), dt.end(), from, to);
    from = ' ';
    to = '0';
    replace(dt.begin(), dt.end(), from, to);

    dt.resize(sz);

    const char* result = dt.c_str();
    
    ofstream fout;

    fout.open("mapdata.txt");

    fout << result << endl;

    fout.close();
}
tatic bool isValidFile()
{
    ifstream fin("mapdata.txt");//입력스트림을 관리하기 위한 객체를 선언 및 파일 열기
    if (fin.fail()) {
        Borland::gotoxy(2, 30);
        cout << "파일 오픈에 실패했습니다." << endl;
        return false;
    }

    return true;
}

static const char* loadMapdata()
{
    char* result = new char[200];

    ifstream fin("mapdata.txt");//입력스트림을 관리하기 위한 객체를 선언 및 파일 열기
   
    fin >> result;
    
    //0,1로 저장된 데이터를 16바이트 char로 변환하는 과정을 거친후 반환하도록 했다.
    for (int i = 0; i < 200; i++)
    {
        if (result[i] == '0') result[i] = ' ';
        else if (result[i] == '1') result[i] = '\xdb';
    }

    return result;
}

 

map 클래스의 멤버함수가 맵파일을 로드하도록 하였다.

void loadMapData()
	{
		if (!isValidFile()) return;
		setShape(loadMapdata());
		
		for (int i = 0; i < dim.x * dim.y; i++)
			if (getShape()[i] != ' ')
			{
				map[i] = true;
				cout << map[i] << endl;
			}			
	}

 

그리고 main.cpp에서 게임이 시작전에 맵데이터를 불러오는 시도를 하도록 하고, 데이터가 있을 경우 맵을 불러오지만 데이터가 없을 경우에는 불러오지 않고 실행하도록 하였다.

int main()
{
	.
    .
    .

	tetris->loadData();

	while (tetris->isGameOver() == false) 
	{
		.
        .
	}

	delete tetris;

	return 0;
}

 

블로그의 정보

에디의 우당탕탕 코딩 공장

인턴 에디

활동하기