빙수달 게임 개발 노트
[C 언어] X-Creature Hunter(C언어를 이용한 머드 게임 Text RPG) 본문
C언어로 코딩을 배우기 시작한지 3주만에 만들어본 텍스트RPG 게임이다. 우리가 생각하는 기본적인 머드 게임 텍스트 RPG와 내가 좋아하는 게임인 몬스터 헌터의 컨셉을 합쳐 봤다. 이제 코딩 입문자이기도 하고, 1주일 안에 만든 게임이라 아쉬움이 있지만, 그래도 게임을 완성해봤다는 것에 의의를 두고 있다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#define Nepenthes_HP 50 // 매크로 쓰는 이유 다시 한 번! 전투 후 잡몸 초기화 할 때!
#define Devilmonkey_HP 150 // 데블몽키 HP
#define Deathworm_HP 100 // 데스웜 HP
#define Yeti_HP 300 // 예티 HP
#define Kraken_HP 400 // 크라켄 HP
#define Gargoyle_HP 600 // 가고일 HP
/*#define PRINT(s) (printf("%s\n", &s), Sleep(2000))*/ // 매크로 함수 이후에 활용, 출력 할 때마다 sleep이 되는 함수
int swordCount = 0; // 검 내구력
int swordDamage = 0; // 검 공격력
int armorDefense = 0; // 갑옷 방어력
int playerHP = 200; // 플레이어 체력
int playerTotalMoney = 50; // 은행에 예금된 금액
int playerNowMoney = 150; // 현재 소지 금액
int swordWoodPrice = 50; // 나무검 가격
int swordIronPrice = 100; // 철검 가격
int swordBronzePrice = 200; // 청동검 가격
int swordGoldPrice = 500; // 황금검 가격
int armorLeatherPrice = 100; // 가죽갑옷 가격
int armorChainPrice = 200; // 사슬갑옷 가격
int armorPlatePrice = 300; // 플라이트갑옷 가격
int Nepenthes_monsterHP = Nepenthes_HP; // 네펜데스 HP, 그냥 상수로 넣으면 왜 안되는지?
int Nepenthes_reward = 40; // 네펜데스 보상
int Nepenthes_damage = 20; // 네벤데스 공격력
int Devilmonkey_monsterHP = Devilmonkey_HP; // 데블몽키 HP
int Devilmonkey_reward = 100; // 데블몽키 보상
int Devilmonkey_damage = 40; // 데블몽키 공격력
int Deathworm_monsterHP = Deathworm_HP; // 데스웜 HP
int Deathworm_reward = 70; // 데스웜 보상
int Deathworm_damage = 30; // 데스웜 공격력
int Yeti_monsterHP = Yeti_HP; // 예티 HP
int Yeti_reward = 300; // 예티 보상
int Yeti_damage = 50; // 예티 공격력
int Kraken_monsterHP = Kraken_HP; // 크라켄 HP
int Kraken_reward = 500; // 크라켄 보상
int Kraken_damage = 70; // 크라켄 공격력
int Gargoyle_monsterHP = Gargoyle_HP; // 가고일 HP
int Gargoyle_reward = 1000; // 가고일 보상
int Gargoyle_damage = 100; // 가고일 공격력
int Nephenthes_alive = 1; // 네펜데스 다시 살리는 flag 변수
int Devilmonkey_alive = 1; // 데블몽키 다시 살리는 flag 변수
int Deathworm_alive = 1; // 데스웜 다시 살리는 flag 변수
int Yeti_alive = 1; // 예티는 한 번 처치하면 없어져야한다.
int Kraken_alive = 1; // 크라켄은 한 번 처치하면 없어져야한다.
int Gargoyle_alive = 1; // 가고일은 한 번 처치하면 없어져야한다.
int Sam_can_go = 1; // 신비의 샘은 일회용 flag 변수
int Yeti_Blood = 0; // 예티의 혈액
int Kraken_Tentacle = 0; // 크라켄의 촉수
int Gargoyle_Horn = 0; // 가고일의 뿔
void LOGO();
void opening();
void village();
void area01();
void area02noBattle(); // 네펜데스를 쓰러트릴 경우
void area02(); // 네펜데스를 마주했을 경우
void area03();
void area04noBattle(); // Boss2 크라켄을 쓰러트렸을 경우
void area04(); // Boss2 크라켄과의 전투
void area05();
void area06();
void area07noBattle(); // 데블몽키를 쓰러트릴 경우
void area07(); // 데블몽키를 마주했을 경우
void area08noItem(); // 신비의 샘을 한 번 사용했을 경우
void area08(); // 신비의 샘이 있는 경우
void area09noBattle(); // Boss1 예티를 쓰러트렸을 경우
void area09(); // Boss1 예티와의 전투
void area10noBattle(); // 데쓰웜을 쓰러트릴 경우
void area10(); // 데쓰웜을 마주했을 경우
void area11();
void area12noBattle(); // FinalBoss 가고일을 쓰러트렸을 경우
void area12(); // FinalBoss 가고일과의 전투
void MySleep();
void Ending(); // 미션 클리어
// 함수 끝 int main 함수 시작
int main(void)
{
LOGO();
opening();
village();
}
void LOGO() // 게임 시작 화면
{
printf(" //////////////////////////////////////////////////\n");
printf(" //////////////////////////////////////////////////\n");
printf(" --------------------------------------------------\n");
printf(" X - CREATURE HUNTER \n");
printf(" --------------------------------------------------\n");
printf(" //////////////////////////////////////////////////\n");
printf(" //////////////////////////////////////////////////\n\n\n\n");
}
void opening()
// 오프닝 멘트, 설정과 스토리가 들어간다.
{
FILE* fp; // 파일 포인터 선언
int ch; // 입력한 문자를 저장할 변수
fp = fopen("opening.txt", "r"); // 읽기 전용으로 파일 개방
while (1)
{
ch = fgetc(fp);
if (ch == EOF)
{
break;
}
putchar(ch);
}
fclose(fp);
return 0;
}
void Ending()
{
FILE* fp; // 파일 포인터 선언
int ch; // 입력한 문자를 저장할 변수
fp = fopen("ending.txt", "r"); // 읽기 전용으로 파일 개방
while (1)
{
ch = fgetc(fp);
if (ch == EOF)
{
break;
}
putchar(ch);
}
fclose(fp);
}
void village() // village 함수
{
printf("\n당신은 지금 마을 안에 있습니다.\n");
printf("북쪽에는 은행이 있고, 동쪽에는 상점이, ");
printf("서쪽에는 쉴 수 있는 베이스캠프가 있습니다.\n");
printf("그리고 마을 밖으로 나가려면 남쪽으로 가면 됩니다.\n\n");
printf("현재 소지금은 %d입니다.\n", playerNowMoney);
printf("어디로 이동하시겠습니까?\n\n");
printf("1.상점 2.베이스캠프 3.은행 4.마을나가기(번호를 입력후 엔터를 쳐주세요.)\n");
int i = 0;
scanf("%d", &i);
printf("당신은 %d번을 누르셨습니다.\n", i);
switch (i)
{
case 1:
{
printf("당신은 지금 상점 안에 있습니다.\n");
printf("상점 안에서는 각종 무기와 방어구를 구입할 수 있습니다.\n");
printf("현재 소지금은 %d입니다.\n", playerNowMoney);
printf("무엇을 구입하시겠습니까?\n");
printf("1.나무검(50) : 공격력 10 증가, 내구성 10\n2.철검(100) : 공격력 20 증가, 내구성 20\n3.청동검(200) : 공격력 30 증가, 내구성 30\n4.황금검(500) : 공격력 100 증가 , 내구성 100\n5.가죽갑옷(100) : 방어력 10 증가\n6.사슬갑옷(200) : 방어력 15 증가\n7.플레이트아머(300) : 방어력 20 증가\n8.구입하지 않고 나간다.\n");
int item = 0;
scanf("%c", &item);
item -= '0';
switch (item)
{
case 1:
if (swordWoodPrice > playerNowMoney)
{
printf("소지금이 부족합니다.\n");
}
else
{
swordCount = 10;
swordDamage = 10;
playerNowMoney -= swordWoodPrice;
printf("당신은 나무검으로 장착합니다.\n소지금이 %d 줄었습니다.남은 금액은 %d입니다.\n", swordWoodPrice, playerNowMoney);
}
break;
case 2:
if (swordIronPrice > playerNowMoney)
{
printf("소지금이 부족합니다.\n");
}
else
{
swordCount = 20;
swordDamage = 20;
playerNowMoney -= swordIronPrice;
printf("당신은 철검으로 장착합니다. 소지금이 %d 줄었습니다. 남은 금액은 %d입니다.\n", swordIronPrice, playerNowMoney);
}
break;
case 3:
if (swordBronzePrice > playerNowMoney)
{
printf("소지금이 부족합니다.\n");
}
else
{
swordCount = 30;
swordDamage = 30;
playerNowMoney -= swordBronzePrice;
printf("당신은 청동검으로 장착합니다. 소지금이 %d 줄었습니다. 남은 금액은 %d입니다.\n", swordBronzePrice, playerNowMoney);
}
break;
case 4:
if (swordGoldPrice > playerNowMoney)
{
printf("소지금이 부족합니다.\n");
}
else
{
swordCount = 100;
swordDamage = 100;
playerNowMoney -= swordGoldPrice;
printf("당신은 황금검으로 장착합니다. 소지금이 %d 줄었습니다. 남은 금액은 %d입니다.\n", swordGoldPrice, playerNowMoney);
}
break;
case 5:
if (armorLeatherPrice > playerNowMoney)
{
printf("소지금이 부족합니다.\n");
}
else
{
armorDefense = 10;
playerNowMoney -= armorLeatherPrice;
printf("당신은 가죽갑옷을 장착합니다. 소지금이 %d 줄었습니다. 남은 금액은 %d입니다.\n", armorLeatherPrice, playerNowMoney);
}
break;
case 6:
if (armorChainPrice > playerNowMoney)
{
printf("소지금이 부족합니다.\n");
}
else
{
armorDefense = 15;
playerNowMoney -= armorChainPrice;
printf("당신은 사슬갑옷을 장착합니다. 소지금이 %d 줄었습니다. 남은 금액은 %d입니다.\n", armorChainPrice, playerNowMoney);
}
break;
case 7:
if (armorPlatePrice > playerNowMoney)
{
printf("소지금이 부족합니다.\n");
}
else
{
armorDefense = 20;
playerNowMoney -= armorPlatePrice;
printf("당신은 플레이트아머를 장착합니다. 소지금이 %d 줄었습니다. 남은 금액은 %d입니다.\n", armorPlatePrice, playerNowMoney);
}
break;
case 8:
printf("아무 것도 안사셨습니다.\n");
break;
}
village();
}
break;
case 2:
{
printf("당신은 지금 베이스캠프 안에 있습니다.\n");
printf("쉬시겠습니까? (1번은 예 / 다른번호는 아니요).\n");
int rest = 0;
scanf("%d", &rest);
if (rest == 1)
{
printf("체력이 전부 회복되었습니다.\n");
playerHP = 200;
}
else if (rest != 1)
{
printf("쉬지 않고 나갑니다.\n");
}
printf("안녕히 가십시오.\n");
}
village();
break;
case 3:
{
printf("당신은 지금 은행 안에 있습니다.\n");
printf("무엇을 하시겠습니까?(1.예금 2.인출 3.그 외 번호는 나가기).\n");
int money = 0; // money 변수 초기화
scanf("%d", &money);
if (money == 1)
{
printf("얼마를 예금하시곘습니까?\n");
int moneyIn = 0;
scanf("%d", &moneyIn);
if (playerTotalMoney <= moneyIn) // 등호 위치 헷갈림
{
playerNowMoney -= moneyIn;
if (playerNowMoney < 0)
{
playerNowMoney += moneyIn;
printf("예금할 수 있는 금액이 부족합니다.\n");
}
else
{
playerTotalMoney += moneyIn;
}
}
/*playerTotalMoney += playerNowMoney;
playerNowMoney = 0;
printf("가지고 있는 돈을 전부 예금하였습니다.\n");
*/
}
else if (money == 2)
{
printf("얼마를 인출하시겠습니까?\n");
printf("현재 %d원 예금되어 있습니다.\n", playerTotalMoney);
int moneyOut = 0;
scanf("%d", &moneyOut);
if (playerTotalMoney >= moneyOut)
{
playerTotalMoney -= moneyOut;
playerNowMoney += moneyOut;
}
}
else
{
printf("잘못 누르셨습니다.\n");
}
printf("당신이 가지고 있는 돈은 %d원이고,\n", playerNowMoney);
printf("은행에 예금된 돈은 전부 %d원입니다.\n\n", playerTotalMoney);
printf("안녕히 가십시오.\n");
}
village();
break;
case 4:
{
if (swordCount > 0)
{
printf("당신은 지금 마을 밖에 있습니다.\n");
area01();
}
else
{
printf("마을 밖으로 나갈 수 없습니다. 상점에서 무기를 구입하십시오.\n\n");
village();
}
break;
}
default:
village();
break;
}
}
void area01() // area01 함수
{
printf("\n\n-체력 %d, 검내구력 %d, 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n주변엔 아무것도 없습니다.\n");
printf("이곳은 북쪽과 동쪽, 남쪽으로 이동이 가능합니다.\n");
printf("어느쪽으로 이동하시겠습니까?\n");
printf("1.북쪽 2.동쪽 3.남쪽\n");
int course1 = 0;
scanf("%d", &course1);
switch (course1)
{
case 1:
printf("북쪽으로 이동합니다.\n\n");
village();
break;
case 2:
printf("동쪽으로 이동합니다.\n\n");
area02();
break;
case 3:
printf("남쪽으로 이동합니다.\n\n");
area05();
break;
default:
printf("다시 입력하세요.\n");
area01();
break;
}
}
void area02noBattle() // area02 함수, 전투가 끝났을 시
{
printf("\n\n-체력 %d, 검내구력 %d. 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n주변엔 아무것도 없습니다.\n");
printf("이곳은 서쪽과 동쪽, 남쪽으로 이동이 가능합니다.\n");
printf("어느 쪽으로 이동하시겠습니까?\n");
printf("1.서쪽 2.동쪽 3.남쪽\n");
int course2 = 0;
scanf("%d", &course2);
switch (course2)
{
case 1:
printf("서쪽으로 이동합니다.\n\n");
area01();
break;
case 2:
printf("동쪽으로 이동합니다.\n\n");
area03();
break;
case 3:
printf("남쪽으로 이동합니다.\n\n");
area06();
break;
default:
printf("다시 입력하세요.\n");
area02noBattle();
break;
}
}
void area02() // area02 함수, 네펜데스를 만났을 시
{
if (playerHP <= 0)
{
playerHP = 0;
}
printf("\n\n-체력 %d, 검내구력 %d, 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
if (Nephenthes_alive == 1) // Nephenthes를 조우 시 "네펜데스가 나타났다" 그 이후 출력 x flag함수
{
printf("네펜데스가 나타났습니다!!\n");
FILE* fp; // 파일 포인터 선언
int ch; // 입력한 문자를 저장할 변수
fp = fopen("nephenthes.txt", "r"); // 읽기 전용으로 파일 개방
while (1)
{
ch = fgetc(fp);
if (ch == EOF)
{
break;
}
putchar(ch);
}
fclose(fp);
Nephenthes_alive = 0;
}
int course2 = 0;
if (playerHP <= 0)
{
printf("당신은 네펜데스에게 패배했습니다.\n");
printf("당신이 가진 소지금을 전부 잃어버렸습니다.\n");
playerNowMoney = 0;
playerHP = 50; // 전투에서 패배했을 경우 체력 50으로 초기화 한 뒤, 마을로 돌아간다.
printf("힘이 다했습니다. 마을로 돌아갑니다.\n");
Nephenthes_alive = 1; // 다음에 네펜데스를 다시 조우 시 "네펜데스가 나타났습니다!!" 출력
Nepenthes_monsterHP = Nepenthes_HP; // 다음에 네펜데스 다시 조우 시 네펜데스 풀피
village();
}
printf("어떻게 하시겠습니까?\n");
printf("1.싸운다 2.후퇴한다\n");
scanf("%d", &course2);
switch (course2)
{
case 1:
printf("당신은 네펜데스를 공격합니다.\n");
if (swordCount > 0)
{
Nepenthes_monsterHP = Nepenthes_monsterHP - swordDamage;
}
else
{
Nepenthes_monsterHP = Nepenthes_monsterHP;
}
if (Nepenthes_monsterHP > 0)
{
Nepenthes_monsterHP - swordDamage;
printf("네펜데스의 체력은 %d 되었습니다.\n", Nepenthes_monsterHP);
if (swordCount > 0)
{
swordCount = swordCount - 1;
}
else
{
swordCount = 0;
}
printf("무기의 내구도가 %d 남았습니다.\n", swordCount);
printf("네펜데스가 산성액으로 공격합니다.\n");
playerHP = playerHP - Nepenthes_damage + armorDefense;
printf("당신의 체력은 %d 되었습니다.\n", playerHP);
area02();
}
else
{
swordCount = swordCount - 1;
printf("네펜데스가 쓰러졌습니다.\n");
printf("네펜데스로부터 %d원을 얻었습니다.\n", Nepenthes_reward);
playerNowMoney = playerNowMoney + Nepenthes_reward;
Nephenthes_alive = 1;
Nepenthes_monsterHP = Nepenthes_HP; // 다시 area02를 찾아올 때 네펜데스와 다시 붙을 수 있도록 초기화
area02noBattle();
}
break;
case 2:
printf("후퇴합니다.\n\n");
Nephenthes_alive = 1;
area01();
break;
default:
printf("다시 입력하세요.\n");
area02();
break;
}
}
void area03() // area03 함수
{
printf("\n\n-체력 %d, 검내구력 %d. 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n해안가에 도착하였습니다. 잔잔한 파도가 칩니다.\n");
printf("이곳은 서쪽과 동쪽, 남쪽으로 이동이 가능합니다.\n");
printf("어느 쪽으로 이동하시겠습니까?\n");
printf("1.서쪽 2.동쪽 3.남쪽\n");
int course3 = 0;
scanf("%d", &course3);
switch (course3)
{
case 1:
printf("서쪽으로 이동합니다.\n\n");
area02();
break;
case 2:
printf("동쪽으로 이동합니다.\n\n");
if (Kraken_alive == 1) // 크라켄이 살아있을 경우에는
{
area04(); // 크라켄과 전투할 수 있는 area04로
}
else if (Kraken_alive == 0) // 만약 크라켄을 처치했다면 크라켄은 다시 살아나지 않으므로
{
area04noBattle(); // 비전투 area04noBattle로 가게된다.
}
break;
case 3:
printf("남쪽으로 이동합니다.\n\n");
area07();
break;
default:
printf("다시 입력하세요.\n");
area03();
break;
}
}
void area04noBattle() // area04noBattle 함수
{
printf("\n\n-체력 %d, 검내구력 %d. 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n주변엔 아무것도 없습니다.\n");
printf("이곳은 서쪽과 남쪽으로 이동이 가능합니다.\n");
printf("어느 쪽으로 이동하시겠습니까?\n");
printf("1.서쪽 2.남쪽\n");
int course4 = 0;
scanf("%d", &course4);
switch (course4)
{
case 1:
printf("서쪽으로 이동합니다.\n\n");
area03();
break;
case 2:
printf("남쪽으로 이동합니다.\n\n");
area08();
break;
default:
printf("다시 입력하세요.\n");
area04noBattle();
break;
}
}
void area04() // Boss2 크라켄을 만났을 시
{
if (playerHP <= 0)
{
playerHP = 0;
}
printf("\n\n-체력 %d, 검내구력 %d, 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
if (Kraken_alive == 1) // 크라켄을 조우 시 "크라켄이 나타났다" 그 이후 출력 x flag함수
{
printf("해일이 일어납니다.\n\n======================크라켄이 나타났습니다!!=========================\n");
FILE* fp; // 파일 포인터 선언
int ch; // 입력한 문자를 저장할 변수
fp = fopen("kraken.txt", "r"); // 읽기 전용으로 파일 개방
while (1)
{
ch = fgetc(fp);
if (ch == EOF)
{
break;
}
putchar(ch);
}
fclose(fp);
Kraken_alive = 0;
}
int course4 = 0;
if (playerHP <= 0)
{
printf("당신은 크라켄에게 패배했습니다.\n");
printf("당신이 가진 소지금을 전부 잃어버렸습니다.\n");
playerNowMoney = 0;
playerHP = 50; // 전투에서 패배했을 경우 체력 50으로 초기화 한 뒤, 마을로 돌아간다.
printf("힘이 다했습니다. 마을로 돌아갑니다.\n");
Kraken_alive = 1; // 플레이어가 죽으면 크라켄은 다시 자리를 지켜야 한다.
Kraken_monsterHP = Kraken_HP; // 다음에 크라켄 조우시 크라켄은 풀피
village();
}
printf("어떻게 하시겠습니까?\n");
printf("1.싸운다 2.후퇴한다\n");
scanf("%d", &course4);
switch (course4)
{
case 1:
printf("당신은 크라켄을 공격합니다.\n");
if (swordCount > 0)
{
Kraken_monsterHP = Kraken_monsterHP - swordDamage;
}
else
{
Kraken_monsterHP = Kraken_monsterHP;
}
if (Kraken_monsterHP > 0)
{
Kraken_monsterHP - swordDamage;
printf("크라켄의 체력은 %d 되었습니다.\n", Kraken_monsterHP);
if (swordCount > 0)
{
swordCount = swordCount - 1;
}
else
{
swordCount = 0;
}
printf("무기의 내구도가 %d 남았습니다.\n", swordCount);
printf("크라켄이 촉수로 몸을 휘감습니다.\n");
playerHP = playerHP - Kraken_damage + armorDefense;
printf("당신의 체력은 %d 되었습니다.\n", playerHP);
area04();
}
else
{
Kraken_Tentacle = 1;
swordCount = swordCount - 1;
printf("크라켄이 쓰러졌습니다.\n");
printf("크라켄의 촉수를 획득하였습니다.\n");
printf("크라켄으로부터 %d원을 얻었습니다.\n", Kraken_reward);
playerNowMoney = playerNowMoney + Kraken_reward;
Kraken_alive = 0; // 크라켄을 처치하면 다시 되살아 나지 않는다.
if (Yeti_Blood == 1 && Kraken_Tentacle == 1 && Gargoyle_Horn == 1)
{
Ending();
}
else
{
area04noBattle();
}
}
break;
case 2:
printf("후퇴합니다.\n\n");
Kraken_alive = 1;
area03();
break;
default:
printf("다시 입력하세요.\n");
area04();
break;
}
}
void area05() // area05 함수
{
printf("\n\n-체력 %d, 검내구력 %d. 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n설원에 도착하였습니다. 눈이 쌓이고 있습니다.\n");
printf("이곳은 북쪽과 동쪽, 남쪽으로 이동이 가능합니다.\n");
printf("어느 쪽으로 이동하시겠습니까?\n");
printf("1.북쪽 2.동쪽 3.남쪽\n");
int course5 = 0;
scanf("%d", &course5);
switch (course5)
{
case 1:
printf("북쪽으로 이동합니다.\n\n");
area01();
break;
case 2:
printf("동쪽으로 이동합니다.\n\n");
area06();
break;
case 3:
printf("남쪽으로 이동합니다.\n\n");
if (Yeti_alive == 1) // 예티가 살아있을 경우에는
{
area09(); // 예티와 전투할 수 있는 area09로
}
else if (Yeti_alive == 0) // 만약 예티를 처치했다면 예티는 다시 살아나지 않으므로
{
area09noBattle(); // 비전투 area09noBattle로 가게된다.
}
break;
default:
printf("다시 입력하세요.\n");
area05();
break;
}
}
void area06() // area06 함수
{
printf("\n\n-체력 %d, 검내구력 %d. 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n주변엔 아무것도 없습니다.\n");
printf("이곳은 동서남북으로 이동이 가능합니다.\n");
printf("어느 쪽으로 이동하시겠습니까?\n");
printf("1.동쪽 2.서쪽 3.남쪽 4.북쪽\n");
int course6 = 0;
scanf("%d", &course6);
switch (course6)
{
case 1:
printf("동쪽으로 이동합니다.\n\n");
area07();
break;
case 2:
printf("서쪽으로 이동합니다.\n\n");
area05();
break;
case 3:
printf("남쪽으로 이동합니다.\n\n");
area10();
break;
case 4:
printf("북쪽으로 이동합니다.\n\n");
area02();
break;
default:
printf("다시 입력하세요.\n");
area06();
break;
}
}
void area07noBattle() // area07 함수, 데블몽키와 전투가 끝났을 시
{
printf("\n\n-체력 %d, 검내구력 %d. 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n주변엔 아무것도 없습니다.\n");
printf("이곳은 동서남북으로 이동이 가능합니다.\n");
printf("어느 쪽으로 이동하시겠습니까?\n");
printf("1.동쪽 2.서쪽 3.남쪽 4.북쪽\n");
int course7 = 0;
scanf("%d", &course7);
switch (course7)
{
case 1:
printf("동쪽으로 이동합니다.\n\n");
area08();
break;
case 2:
printf("서쪽으로 이동합니다.\n\n");
area06();
break;
case 3:
printf("남쪽으로 이동합니다.\n\n");
area11();
break;
case 4:
printf("북쪽으로 이동합니다.\n\n");
area03();
break;
default:
printf("다시 입력하세요.\n");
area07noBattle();
break;
}
}
void area07() // area07 함수, 데빌몽키를 만났을 시
{
if (playerHP <= 0)
{
playerHP = 0;
}
printf("\n\n-체력 %d, 검내구력 %d, 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
if (Devilmonkey_alive == 1) // 데빌몽키를 조우 시 "데빌몽키가 나타났다" 그 이후 출력 x flag함수
{
printf("데빌몽키가 나타났습니다!!\n");
FILE* fp; // 파일 포인터 선언
int ch; // 입력한 문자를 저장할 변수
fp = fopen("devilmonkey.txt", "r"); // 읽기 전용으로 파일 개방
while (1)
{
ch = fgetc(fp);
if (ch == EOF)
{
break;
}
putchar(ch);
}
fclose(fp);
Devilmonkey_alive = 0;
}
int course2 = 0;
if (playerHP <= 0)
{
printf("당신은 데빌몽키에게 패배했습니다.\n");
printf("당신이 가진 소지금을 전부 잃어버렸습니다.\n");
playerNowMoney = 0;
playerHP = 50; // 전투에서 패배했을 경우 체력 50으로 초기화 한 뒤, 마을로 돌아간다.
printf("힘이 다했습니다. 마을로 돌아갑니다.\n");
Devilmonkey_alive = 1; // 다음에 데빌몽키를 다시 조우 시 "데빌몽키가 나타났습니다!!" 출력
Devilmonkey_monsterHP = Devilmonkey_HP; // 다음에 데빌몽키 다시 조우 시 데빌몽키 풀피
village();
}
printf("어떻게 하시겠습니까?\n");
printf("1.싸운다 2.후퇴한다\n");
scanf("%d", &course2);
switch (course2)
{
case 1:
printf("당신은 데빌몽키를 공격합니다.\n");
if (swordCount > 0)
{
Devilmonkey_monsterHP = Devilmonkey_monsterHP - swordDamage;
}
else
{
Devilmonkey_monsterHP = Devilmonkey_monsterHP;
}
if (Devilmonkey_monsterHP > 0)
{
Devilmonkey_monsterHP - swordDamage;
printf("데빌몽키의 체력은 %d 되었습니다.\n", Devilmonkey_monsterHP);
if (swordCount > 0)
{
swordCount = swordCount - 1;
}
else
{
swordCount = 0;
}
printf("무기의 내구도가 %d 남았습니다.\n", swordCount);
printf("데빌몽키가 사나운 이빨로 공격합니다.\n");
playerHP = playerHP - Devilmonkey_damage + armorDefense;
printf("당신의 체력은 %d 되었습니다.\n", playerHP);
area07();
}
else
{
swordCount = swordCount - 1;
printf("데빌몽키가 쓰러졌습니다.\n");
printf("데빌몽키로부터 %d원을 얻었습니다.\n", Devilmonkey_reward);
playerNowMoney = playerNowMoney + Devilmonkey_reward;
Devilmonkey_alive = 1;
Devilmonkey_monsterHP = Devilmonkey_HP; // 다시 area07를 찾아올 때 데블몽키와 다시 붙을 수 있도록 초기화
area07noBattle();
}
break;
case 2:
printf("후퇴합니다.\n\n");
Devilmonkey_alive = 1;
area06();
break;
default:
printf("다시 입력하세요.\n");
area07();
break;
}
}
void area08noItem() // area08 함수
{
printf("\n\n-체력 %d, 검내구력 %d. 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n주변엔 아무것도 없습니다.\n");
printf("이곳은 북쪽과 서쪽, 남쪽으로 이동이 가능합니다.\n");
printf("어느 쪽으로 이동하시겠습니까?\n");
printf("1.북쪽 2.서쪽 3.남쪽\n");
int course8 = 0;
scanf("%d", &course8);
switch (course8)
{
case 1:
printf("북쪽으로 이동합니다.\n\n");
if (Kraken_alive == 1) // 크라켄이 살아있을 경우에는
{
area04(); // 크라켄과 전투할 수 있는 area04로
}
else if (Kraken_alive == 0) // 만약 크라켄을 처치했다면 크라켄은 다시 살아나지 않으므로
{
area04noBattle(); // 비전투 area04noBattle로 가게된다.
}
break;
case 2:
printf("서쪽으로 이동합니다.\n\n");
area07();
break;
case 3:
printf("남쪽으로 이동합니다.\n\n");
if (Gargoyle_alive == 1) // 가고일이 살아있을 경우에는
{
area12(); // 가고일과 전투할 수 있는 area12로
}
else if (Gargoyle_alive == 0) // 만약 가고일을 처치했다면 가고일은 다시 살아나지 않으므로
{
area12noBattle(); // 비전투 area12noBattle로 가게된다.
}
break;
default:
printf("다시 입력하세요.\n");
area08();
break;
}
}
void area08() // 신비의샘이 존재할 경우
{
if (Sam_can_go == 1) // 신비의 샘은 1회성이다.
{
printf("\n\n-체력 %d, 검내구력 %d, 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("신비의 힘이 당신의 체력을 전부 회복시켜줍니다.\n");
playerHP = 200;
Sam_can_go = 0; //신비의 샘을 한 번 이용하면 다시는 이용할 수 없다.
}
area08noItem();
}
void area09noBattle() // area09 함수 예티를 쓰러트렸을 경우
{
printf("\n\n-체력 %d, 검내구력 %d. 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n주변엔 아무것도 없습니다.\n");
printf("이곳은 북쪽과 동쪽으로 이동이 가능합니다.\n");
printf("어느 쪽으로 이동하시겠습니까?\n");
printf("1.북쪽 2.동쪽\n");
int course9 = 0;
scanf("%d", &course9);
switch (course9)
{
case 1:
printf("북쪽으로 이동합니다.\n\n");
area05();
break;
case 2:
printf("동쪽으로 이동합니다.\n\n");
area10();
break;
default:
printf("다시 입력하세요.\n");
area09noBattle();
break;
}
}
void area09() // area02 함수, Boss1 예티를 만났을 시
{
if (playerHP <= 0)
{
playerHP = 0;
}
printf("\n\n-체력 %d, 검내구력 %d, 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
if (Yeti_alive == 1) // 예티를 조우 시 "예티가 나타났다" 그 이후 출력 x flag함수
{
printf("눈보라가 몰아치기 시작했습니다.\n\n======================예티가 나타났습니다!!=========================\n");
FILE* fp; // 파일 포인터 선언
int ch; // 입력한 문자를 저장할 변수
fp = fopen("yeti.txt", "r"); // 읽기 전용으로 파일 개방
while (1)
{
ch = fgetc(fp);
if (ch == EOF)
{
break;
}
putchar(ch);
}
fclose(fp);
Yeti_alive = 0;
}
int course9 = 0;
if (playerHP <= 0)
{
printf("당신은 예티에게 패배했습니다.\n");
printf("당신이 가진 소지금을 전부 잃어버렸습니다.\n");
playerNowMoney = 0;
playerHP = 50; // 전투에서 패배했을 경우 체력 50으로 초기화 한 뒤, 마을로 돌아간다.
printf("힘이 다했습니다. 마을로 돌아갑니다.\n");
Yeti_alive = 1; // 플레이어가 죽으면 예티는 다시 자리를 지켜야 한다.
Yeti_monsterHP = Yeti_HP; // 다음에 예티 조우시 예티는 풀피
village();
}
printf("어떻게 하시겠습니까?\n");
printf("1.싸운다 2.후퇴한다\n");
scanf("%d", &course9);
switch (course9)
{
case 1:
printf("당신은 예티를 공격합니다.\n");
if (swordCount > 0)
{
Yeti_monsterHP = Yeti_monsterHP - swordDamage;
}
else
{
Yeti_monsterHP = Yeti_monsterHP;
}
if (Yeti_monsterHP > 0)
{
Yeti_monsterHP - swordDamage;
printf("예티의 체력은 %d 되었습니다.\n", Yeti_monsterHP);
if (swordCount > 0)
{
swordCount = swordCount - 1;
}
else
{
swordCount = 0;
}
printf("무기의 내구도가 %d 남았습니다.\n", swordCount);
printf("예티가 고드름을 던집니다.\n");
playerHP = playerHP - Yeti_damage + armorDefense;
printf("당신의 체력은 %d 되었습니다.\n", playerHP);
area09();
}
else
{
swordCount = swordCount - 1;
Yeti_Blood = 1;
printf("예티가 쓰러졌습니다.\n");
printf("예티의 혈액을 채취했습니다.\n");
printf("예티로부터 %d원을 얻었습니다.\n", Yeti_reward);
playerNowMoney = playerNowMoney + Yeti_reward;
Yeti_alive = 0; // 예티를 처치하면 다시 되살아 나지 않는다.
if (Yeti_Blood == 1 && Kraken_Tentacle == 1 && Gargoyle_Horn == 1)
{
Ending();
}
else
{
area09noBattle();
}
}
break;
case 2:
printf("후퇴합니다.\n\n");
Yeti_alive = 1;
area05();
break;
default:
printf("다시 입력하세요.\n");
area09();
break;
}
}
void area10noBattle() // area10 함수, 데쓰웜을 쓰러트렸을 경우
{
printf("\n\n-체력 %d, 검내구력 %d. 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n주변엔 아무것도 없습니다.\n");
printf("이곳은 북쪽과 서쪽, 동쪽으로 이동이 가능합니다.\n");
printf("어느 쪽으로 이동하시겠습니까?\n");
printf("1.북쪽 2.서쪽 3.동쪽\n");
int course10 = 0;
scanf("%d", &course10);
switch (course10)
{
case 1:
printf("북쪽으로 이동합니다.\n\n");
area06();
break;
case 2:
printf("서쪽으로 이동합니다.\n\n");
if (Yeti_alive == 1) // 데쓰웜을 쓰르트린 상태인 area10noBattle에서 예티를 아직 처지하지 못하였다면
{
area09(); // 예티와 전투할 수 있는 area09로 가야할 것이고
}
else if (Yeti_alive == 0) // 만약 예티를 처치한 상태라면
{
area09noBattle(); // 비전투 상태인 area09noBattle로 진입하게 된다.
}
break;
case 3:
printf("동쪽으로 이동합니다.\n\n");
area11();
break;
default:
printf("다시 입력하세요.\n");
area10noBattle();
break;
}
}
void area10() // area10 함수, 데쓰웜을 만났을 시
{
if (playerHP <= 0)
{
playerHP = 0;
}
printf("\n\n-체력 %d, 검내구력 %d, 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
if (Deathworm_alive == 1) // 데쓰웜을 조우 시 "데쓰웜이 나타났다" 그 이후 출력 x flag함수
{
printf("데쓰웜이 나타났습니다!!\n");
FILE* fp; // 파일 포인터 선언
int ch; // 입력한 문자를 저장할 변수
fp = fopen("deathworm.txt", "r"); // 읽기 전용으로 파일 개방
while (1)
{
ch = fgetc(fp);
if (ch == EOF)
{
break;
}
putchar(ch);
}
fclose(fp);
Deathworm_alive = 0; // 전투 시에는 "데쓰웜이 나타났다" 나타내지 않기 위함
}
int course2 = 0;
if (playerHP <= 0)
{
printf("당신은 데쓰웜에게 패배했습니다.\n");
printf("당신이 가진 소지금을 전부 잃어버렸습니다.\n");
playerNowMoney = 0;
playerHP = 50; // 전투에서 패배했을 경우 체력 50으로 초기화 한 뒤, 마을로 돌아간다.
printf("힘이 다했습니다. 마을로 돌아갑니다.\n");
Deathworm_alive = 1; // 다음에 데쓰웜 다시 조우 시 "데쓰웜이 나타났습니다!!" 출력
Deathworm_monsterHP = Deathworm_HP; // 다음에 데쓰웜 다시 조우 시 데쓰웜 풀피
village();
}
printf("어떻게 하시겠습니까?\n");
printf("1.싸운다 2.후퇴한다\n");
scanf("%d", &course2);
switch (course2)
{
case 1:
printf("당신은 데쓰웜을 공격합니다.\n");
if (swordCount > 0)
{
Deathworm_monsterHP = Deathworm_monsterHP - swordDamage;
}
else
{
Deathworm_monsterHP = Deathworm_monsterHP;
}
if (Deathworm_monsterHP > 0)
{
Deathworm_monsterHP - swordDamage;
printf("데쓰웜의 체력은 %d 되었습니다.\n", Deathworm_monsterHP);
if (swordCount > 0)
{
swordCount = swordCount - 1;
}
else
{
swordCount = 0;
}
printf("무기의 내구도가 %d 남았습니다.\n", swordCount);
printf("데쓰웜의 가시 꼬리에 공격당했습니다.\n");
playerHP = playerHP - Deathworm_damage + armorDefense;
printf("당신의 체력은 %d 되었습니다.\n", playerHP);
area10();
}
else
{
swordCount = swordCount - 1;
printf("데쓰웜이 쓰러졌습니다.\n");
printf("데쓰웜으로부터 %d원을 얻었습니다.\n", Deathworm_reward);
playerNowMoney = playerNowMoney + Deathworm_reward;
Deathworm_alive = 1;
Deathworm_monsterHP = Deathworm_HP; // 다시 area10를 찾아올 때 데쓰웜과 다시 붙을 수 있도록 초기화
area10noBattle();
}
break;
case 2:
printf("후퇴합니다.\n\n");
Deathworm_alive = 1;
area06();
break;
default:
printf("다시 입력하세요.\n");
area10();
break;
}
}
void area11() // area11 함수
{
printf("\n\n-체력 %d, 검내구력 %d. 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n고성에 도착하였습니다. 박쥐 떼가 몰려옵니다.\n");
printf("이곳은 북쪽과 서쪽, 동쪽으로 이동이 가능합니다.\n");
printf("어느 쪽으로 이동하시겠습니까?\n");
printf("1.북쪽 2.서쪽 3.동쪽\n");
int course11 = 0;
scanf("%d", &course11);
switch (course11)
{
case 1:
printf("북쪽으로 이동합니다.\n\n");
area07();
break;
case 2:
printf("서쪽으로 이동합니다.\n\n");
area10();
break;
case 3:
printf("동쪽으로 이동합니다.\n\n");
if (Gargoyle_alive == 1) // 가고일이 살아있을 경우에는
{
area12(); // 가고일과 전투할 수 있는 area12로
}
else if (Gargoyle_alive == 0) // 만약 가고일을 처치했다면 가고일은 다시 살아나지 않으므로
{
area12noBattle(); // 비전투 area12noBattle로 가게된다.
}
break;
default:
printf("다시 입력하세요.\n");
area11();
break;
}
}
void area12noBattle() // area12 함수
{
printf("\n\n-체력 %d, 검내구력 %d. 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
printf("\n주변엔 아무것도 없습니다.\n");
printf("이곳은 북쪽과 서쪽으로 이동이 가능합니다.\n");
printf("어느 쪽으로 이동하시겠습니까?\n");
printf("1.북쪽 2.서쪽\n");
int course12 = 0;
scanf("%d", &course12);
switch (course12)
{
case 1:
printf("북쪽으로 이동합니다.\n\n");
area08();
break;
case 2:
printf("서쪽으로 이동합니다.\n\n");
area11();
break;
default:
printf("다시 입력하세요.\n");
area12();
break;
}
}
void area12() // FinalBoss 가고일을 만났을 시
{
if (playerHP <= 0)
{
playerHP = 0;
}
printf("\n\n-체력 %d, 검내구력 %d, 소지금 %d-\n", playerHP, swordCount, playerNowMoney);
if (Gargoyle_alive == 1) // 가고일을 조우 시 "가고일이 나타났다" 그 이후 출력 x flag함수
{
printf("고성의 석상이 움직이기 시작했습니다.\n\n======================가고일이 깨어났습니다!!=========================\n");
FILE* fp; // 파일 포인터 선언
int ch; // 입력한 문자를 저장할 변수
fp = fopen("gargoyle.txt", "r"); // 읽기 전용으로 파일 개방
while (1)
{
ch = fgetc(fp);
if (ch == EOF)
{
break;
}
putchar(ch);
}
fclose(fp);
Gargoyle_alive = 0;
}
int course12 = 0;
if (playerHP <= 0)
{
printf("당신은 가고일에게 패배했습니다.\n");
printf("당신이 가진 소지금을 전부 잃어버렸습니다.\n");
playerNowMoney = 0;
playerHP = 50; // 전투에서 패배했을 경우 체력 50으로 초기화 한 뒤, 마을로 돌아간다.
printf("힘이 다했습니다. 마을로 돌아갑니다.\n");
Gargoyle_alive = 1; // 플레이어가 죽으면 가고일은 다시 자리를 지켜야 한다.
Gargoyle_monsterHP = Gargoyle_HP; // 다음에 가고일 조우시 가고일은 풀피
village();
}
printf("어떻게 하시겠습니까?\n");
printf("1.싸운다 2.후퇴한다\n");
scanf("%d", &course12);
switch (course12)
{
case 1:
printf("당신은 가고일을 공격합니다.\n");
if (swordCount > 0)
{
Gargoyle_monsterHP = Gargoyle_monsterHP - swordDamage;
}
else
{
Gargoyle_monsterHP = Gargoyle_monsterHP;
}
if (Gargoyle_monsterHP > 0)
{
Gargoyle_monsterHP - swordDamage;
printf("가고일의 체력은 %d 되었습니다.\n", Gargoyle_monsterHP);
if (swordCount > 0)
{
swordCount = swordCount - 1;
}
else
{
swordCount = 0;
}
printf("무기의 내구도가 %d 남았습니다.\n", swordCount);
printf("가고일의 석화광선에 맞았습니다. 몸을 경화되기 시작합니다.\n");
playerHP = playerHP - Gargoyle_damage + armorDefense;
printf("당신의 체력은 %d 되었습니다.\n", playerHP);
area12();
}
else
{
swordCount = swordCount - 1;
Gargoyle_Horn = 1;
printf("가고일이 쓰러졌습니다.\n");
printf("가고일의 뿔을 획득하였습니다.\n");
printf("가고일으로부터 %d원을 얻었습니다.\n", Gargoyle_reward);
playerNowMoney = playerNowMoney + Gargoyle_reward;
Gargoyle_alive = 0; // 가고일을 처치하면 다시 되살아 나지 않는다.
if (Yeti_Blood == 1 && Kraken_Tentacle == 1 && Gargoyle_Horn == 1)
{
Ending();
}
else
{
area12noBattle();
}
}
break;
case 2:
printf("후퇴합니다.\n\n");
Gargoyle_alive = 1;
area11();
break;
default:
printf("다시 입력하세요.\n");
area12();
break;
}
}
차마 눈뜨고는 못 볼 명존쎄 마려운 코드..
아쉬운 점
(1) 구조적 문제
1. struct 구조체와 열거법 enum형을 배우기 전이라, 플레이어와 각 몬스터의 스탯을 일일이 변수로 지정했다.(하드 코딩...)
2. switch-case로 각 맵을 이동할 때, 함수 안으로 계속 파고든다... 무슨 말이냐 하면 함수 안에 함수 안에 함수 안에 함수...가 계속 반복된다는 것이다. 때문에 무한히 반복한다고 가정시 스택오버플로우가 발생할 수 있다.
ex) area1() 안에 area2() 안에 area3() 안에 area4() 안에 area3() 안에.... => 함수 포인터로 해결할 수 있나?
(2) 기획적 문제
1. 시간이 부족해 전체 맵이 협소하다. 때문에 몬스터를 만날 확률이 높아 난이도가 꽤 높게 느껴질 수 있다.
2. 인벤토리의 부재. 때문에 상점에서 철검을 사고 난 뒤, 나무검을 구입하면 나무검을 장착하게 된다... 구입한 장비를 바꿀 수 있도록 인벤토리를 만든다.
3. rand() 함수, 난수를 활용해 랜덤 요소를 넣는다. ex) 공격 시 회피, 몬스터 랜덤 보상, 크리티컬 데미지 등
4. 포션의 부재. 체력이 부족하면 마을의 베이스 캠프로 돌아와서 체력을 회복하는 수 밖에 없다. 길치가 되면 곤란해진다..
5. 스킬이 없다. 각 무기와 몬스터의 공격력은 정해져 있기 때문에 데미지가 얼마나 들어갈 지 예상되어 단조롭다.
혹시 시간 많으신 분들은 플레이 한 번 해주시고, 화살 날려 주세요들..
