본문 바로가기
강의/나 혼자 C언어 : 기초

만들면서 배우는 나 혼자 C언어 : 05. 기초 활용 - 전투 시스템 만들기

by dongglessam 2022. 12. 8.
728x90
반응형
728x170

안녕하세요. 동글쌤 입니다.

연말이 되니 본업이 바빠 정신이 없네요. 맨날 C언어 강의 써야지 해놓고선 항상 뒷전으로 밀려납니다. ㅠㅠ

지난 강의에서 반복문을 통해 로그인 기능을 좀더 상세히 구현해봤습니다.

이전 글 : 2022.11.15 - [강의/나 혼자 C언어 : 기초] - 만들면서 배우는 나 혼자 C언어 : 04. 반복문

 

만들면서 배우는 나 혼자 C언어 : 04. 반복문

안녕하세요. 동글쌤 입니다. 지난 강의에서 조건문을 통해 게임 메뉴를 만들어봤습니다. 이전 글 : 2022.11.08 - [강의/나 혼자 C언어 : 기초] - 만들면서 배우는 나 혼자 C언어 : 03. 조건문 만들면서

choisdevil.tistory.com

 

이번 시간에는 지금까지 배운 것(입출력, 변수, 조건문, 반복문 등)을 활용해서 간단하게 전투 시스템을 만들어보도록 하겠습니다.

 

 

 

01. 전투 시스템 개요

 

요즘 나오는 게임들은 다양한 2D/3D 그래픽 요소로 HP, 데미지, 캐릭터, UI/UX 등을 표현하지만 과거에는 텍스트로만 표현한 적도 있었습니다. 정확하게 말하면 텍스트로밖에 표현할 수 없었죠. 그 당시의 컴퓨터 기술과 통신 속도로는 지금과 같은 그래픽 요소를 구현하기 어려웠기 때문입니다.

출처 : MUD게임 '천명', https://juawesome.com/post/67348506375/mud게임과-상상력

하지만 시대가 발전하고 컴퓨터 기술이 진보하면서 우리가 현재 알고있는 형태의 게임, 즉 2D/3D 그래픽 요소로 표현한 게임들이 나오기 시작했습니다. 이와 함께 전투 과정도 화려한 이펙트와 그래픽 요소로 뒤덮였지만 본질은 텍스트 게임의 그것과 다르지 않습니다.

출처 : 게임인사이트, http://m.gameinsight.co.kr/news/articleView.html?idxno=11138

즉, 상대방과 내가 각각 가지고 있는 공격력을 가지고 서로의 HP(체력)을 먼저 0으로 만드는 사람이 승리하는 것이 전투 시스템의 기본이죠. 결국 아무리 화려하게 그래픽으로 포장했다고 하더라도 이 원리를 알고 있다면 누구나 게임을 만들 수 있는 것입니다.

 

 

02. 전투 시스템 설계

 

우리는 아래와 같은 형태의 전투 시스템을 텍스트로 구현해볼 것입니다. 어려워 보이지만 변수, 조건문, 반복문만 가지고도 충분히 전투를 하는 것'처럼' 표현할 수 있습니다.

[전투 시스템 시뮬레이터]

플레이어1 공격력 입력 : 50
몬스터 공격력 입력 : 30


[플레이어1 vs 몬스터 전투 시작]

플레이어1 공격! 50 데미지 적중!
플레이어 HP : 100/100
몬스터 HP : 50/100

몬스터 공격! : 30 데미지 적중!
플레이어1 HP : 70/100
몬스터 HP : 50/100

플레이어1 공격! 50 데미지 적중!
플레이어1 HP : 70/100
몬스터 HP : 0/100

플레이어1 승리!

 

1. 전투 종료 조건

전투가 종료되기 위한 조건은 어느 한 쪽의 HP가 0이 될때까지로 설정할 수 있고, 이에 따라 승리조건과 패배조건은 다음과 같습니다.

승리조건 : 플레이어1의 HP가 0이 되기 전에 몬스터의 HP를 0으로 만든다.
패배조건 : 몬스터의 HP가 0이 되기 전에 플레이어1의 HP를 0으로 만든다.

 

2. 플레이어1, 몬스터 속성 설정

1) 스킬이나 마법은 프로그램이 복잡해지기 때문에 지금 단계에서는 구현하지 않습니다.
2) 공격력은 변수 선언 시 입력할수도 있지만 지금은 전투 시스템 시뮬레이터기 때문에 공격력은 사용자가 입력할 수 있도록 구현합니다.
3) 공격력 범위(ex. 공격력 10~15)는 구현하지 않고 단일 공격력으로만 입력하도록 합니다. 

이를 위해 플레이어1, 몬스터가 각각 가지는 변수는 HP, 공격력 입니다. HP, 공격력은 정수로만 사용하기 때문에 저장하는 자료형은 int형 입니다. 초기값은 HP는 100이지만 공격력은 각각 입력받아서 시뮬레이션을 할 수 있도록 합니다. (HP는 원하는 대로 변경해도 되고, 공격력과 마찬가지로 scanf() 함수로 입력받도록 변경해도 됩니다.)

데이터 자료형 변수명 초기값
플레이어1 HP int userHP 100
플레이어1 공격력 int userATT 입력받음
몬스터 HP int monHP 100
몬스터 공격력 int monATT 입력받음

 

반응형

 

3. 선공 여부 결정

누가 먼저 공격하느냐에 따라 승패가 갈릴 수 있는 만큼 선공 여부가 중요하지만 여기서는 플레이어1이 무조건 선공을 한다고 가정하고 진행합니다. 나중에 난수를 생성하는 rand() 함수를 배우면 랜덤수에 의해 선공 여부를 랜덤하게 결정하도록 개선할 수 있습니다.

 

4. 기본 코드 구현

지금까지 설계한 내용을 바탕으로 기본 코드를 구현해보도록 하겠습니다. 약 50줄 정도 되는 코드지만 최적화를 제외하고 변수, 입출력, 조건문, 반복문으로만 구성한 내용입니다.

#include <stdio.h>
int main() {
	int userHP = 100, userATT;	//플레이어1 속성
	int monHP = 100, monATT;	//몬스터 속성
	int winner; //승자 확인용 변수. 입력값 0:플레이어1, 1:몬스터 
	
	//공격력 입력 
	printf("[전투 시스템 시뮬레이터]\n\n");	//안내문구 출력
	printf("플레이어1 공격력 입력 : ");
	scanf("%d", &userATT);	//플레이어1 공격력 입력 
	printf("몬스터 공격력 입력 : ");
	scanf("%d", &monATT);	//몬스터 공격력 입력 
	
	//전투 시작 
	printf("\n");
	printf("[플레이어1 vs 몬스터 전투 시작]\n\n");
	
	//반복조건 : 플레이어1 HP가 0 이하 or 몬스터 HP가 0 이하일 경우 전투 종료 
	while(1) {	//언제 끝날 지 모르기 때문에 무한 반복 
		//플레이어1 공격 턴 
		printf("플레이어1 공격! %d 데미지 적중!\n", userATT);
		monHP = monHP - userATT;	//몬스터 체력을 플레이어1 공격력만큼 감소 
		//위 문장은 monHP -= userATT; 와 동일함 
		printf("플레이어1 HP : %d/100\n", userHP);
		printf("몬스터 HP : %d/100\n\n", monHP);
		
		//몬스터 HP 확인
		if(monHP <= 0) {	//몬스터 HP가 0 이하일 경우 
			winner = 0;		//승자 = 플레이어1 
			break;			//반복문 종료 
		}
		
		//몬스터 공격 턴 
		printf("플레이어1 공격! %d 데미지 적중!\n", userATT);
		userHP = userHP - monATT;		//플레이어1 체력을 몬스터 공격력만큼 감소 
		//위 문장은 userHP -= monATT; 와 동일함 
		printf("플레이어1 HP : %d/100\n", userHP);
		printf("몬스터 HP : %d/100\n\n", monHP);
		
		//플레이어1 HP 확인
		if(userHP <= 0) {	//플레이어1 HP가 0 이하일 경우 
			winner = 1;		//승자 = 몬스터 
			break;			//반복문 종료 
		}
	}
	
	//전투 결과 출력
	if(winner == 0)  {	//승자가 플레이어1인 경우 
		printf("플레이어1 승리!\n");
	} else {	//승자가 몬스터인 경우 
		printf("몬스터 승리!\n");
	}
	
	return 0;
}

플레이어1 승리 화면(좌측)과 몬스터 승리 화면(우측)

 

5. 예외조건 처리

게임을 설계하다보면 여러가지 예외조건이 필요합니다. 우리의 게임을 즐기는 유저들은 개발자가 생각하지 못하는 별의별 행동들을 하기 때문이죠. 

우리가 추가해야 할 예외조건은 공격력을 입력받을 때 0 혹은 음수가 입력되지 않도록 해야 합니다. 만약 공격력이 음수가 된다면 어떻게 될까요? 체력 계산식에 음수 공격력을 대입해보면 monHP = 100 - (-50) = 100 + 50이 되기 때문에 아래 결과처럼 체력이 오히려 증가되는(!) 결과가 나오기 때문이죠.

공격력이 음수가 되면 공격할수록 체력이 증가되는 마법같은 게임이 됩니다

예외처리 부분은 프로그램을 종료할 수도, 사용자가 양수만 입력할 때까지 계속 반복할 수도 있습니다. 우리는 사용자가 양수만 입력할 수 있도록 예외처리를 추가하여 구현해보도록 하겠습니다. (나중에 함수를 배우게 되면 예외처리 부분을 하나의 함수로 만들어줄 수도 있지만 지금은 고려하지 않습니다.)

#include <stdio.h>
int main() {
	int userHP = 100, userATT;	//플레이어1 속성
	int monHP = 100, monATT;	//몬스터 속성
	int winner; //승자 확인용 변수. 입력값 0:플레이어1, 1:몬스터 
	
	//공격력 입력 
	printf("[전투 시스템 시뮬레이터]\n\n");	//안내문구 출력
	
	//플레이어1 공격력 입력 예외처리 
	while(1) {
		printf("플레이어1 공격력 입력 : ");
		scanf("%d", &userATT);	//플레이어1 공격력 입력 
		if(userATT > 0)	{	//입력값이 0보다 큰 양수(최소 1) 
			break;	//반복문 종료 
		} else {	//예외처리 안내 출력 
			printf("# 입력 오류 : 공격력은 1 이상 양수값을 입력해야 합니다.\n");
		}
	}
	
	//몬스터 공격력 입력 예외처리 
	while(1) {
		printf("몬스터 공격력 입력 : ");
		scanf("%d", &monATT);	//몬스터 공격력 입력 
		if(monATT > 0)	{	//입력값이 0보다 큰 양수(최소 1) 
			break;	//반복문 종료 
		} else {	//예외처리 안내 출력 
			printf("# 입력 오류 : 공격력은 1 이상 양수값을 입력해야 합니다.\n");
		}
	}
	
	//전투 시작 
	printf("\n");
	printf("[플레이어1 vs 몬스터 전투 시작]\n\n");
	
	//반복조건 : 플레이어1 HP가 0 이하 or 몬스터 HP가 0 이하일 경우 전투 종료 
	while(1) {	//언제 끝날 지 모르기 때문에 무한 반복 
		//플레이어1 공격 턴 
		printf("플레이어1 공격! %d 데미지 적중!\n", userATT);
		monHP = monHP - userATT;	//몬스터 체력을 플레이어1 공격력만큼 감소 
		//위 문장은 monHP -= userATT; 와 동일함 
		printf("플레이어1 HP : %d/100\n", userHP);
		printf("몬스터 HP : %d/100\n\n", monHP);
		
		//몬스터 HP 확인
		if(monHP <= 0) {	//몬스터 HP가 0 이하일 경우 
			winner = 0;		//승자 = 플레이어1 
			break;			//반복문 종료 
		}
		
		//몬스터 공격 턴 
		printf("플레이어1 공격! %d 데미지 적중!\n", userATT);
		userHP = userHP - monATT;		//플레이어1 체력을 몬스터 공격력만큼 감소 
		//위 문장은 userHP -= monATT; 와 동일함 
		printf("플레이어1 HP : %d/100\n", userHP);
		printf("몬스터 HP : %d/100\n\n", monHP);
		
		//플레이어1 HP 확인
		if(userHP <= 0) {	//플레이어1 HP가 0 이하일 경우 
			winner = 1;		//승자 = 몬스터 
			break;			//반복문 종료 
		}
	}
	
	//전투 결과 출력
	if(winner == 0)  {	//승자가 플레이어1인 경우 
		printf("플레이어1 승리!\n");
	} else {	//승자가 몬스터인 경우 
		printf("몬스터 승리!\n");
	}
	
	return 0;
}

 

예외처리 결과를 확인할 때는 조건의 경계에 있는 값만 넣어서 확인해보면 됩니다. 이 경우에는 0 이하인 경우 오류 메시지가 출력되게 했으니 0, -1, 1 세 가지 경우의 수만 입력해보면 예외처리가 잘 작동하는지 확인할 수 있습니다.

예외처리가 정상적으로 적용된 것을 확인할 수 있다.

 

C언어에서 초반에 배울 수 있는 기초 내용들만 가지고도 여러분은 훌륭하게 텍스트 게임의 전투 시스템을 구현했습니다. 다음 시간에는 데이터를 연속된 공간에 저장할 수 있는 배열에 대해 배우고, 배열을 활용한 인벤토리 시스템을 구현해보도록 하겠습니다.

 

728x90
반응형
그리드형

댓글