(4.4) 학습일지_C언어 if문 활용해 간단한 게임만들기
일명 코딩몬스터 물리치기 게임(가제)입니다.
순서도 그리느라 시간을 다 허비해서 꾸미는데 열중하지 못했다..
하지만 그래도 순서도와 의사의 중요성을 깨달았다. 순서도를 그리고 의사코드를 쓰니까 수월하게 쓸 수 있었다.
오류를 발견하기 전까지는...
문제
1. 개발 진행 및 완료상황, 무엇을 더 하면 좋을지
게임 순서도 -> 의사코드 작성 -> 코드 작성 -> 코드 리뷰 및 수정(ing)
5시 30분에 제작완료하였으나 버그를 찾지 못해 9시까지 헤매어.. 반 동기들이 큰도움을 주셨습니다.
코드는 완료했으나 잘못된 점을 찾으면서 순서도가 조금 잘못되었다는 것을 깨닫게 됨.
순서도 버전 0
게임 순서도 ver1
추가예정 ver.2
여기에 전투할지 묻는 질문을 추가했어야 하더라고요.. 알려주신 반장님 감사합니다.
구현화면
시작 화면
게임 안내 및 엔터를 누르면 게임이 시작됩니다.
유저보다 더 높은 레벨의 몬스터가 나오면
이기기 힘든 상라고 경고합니다.
그리고 유저는 게임 참가와 도망치기 중 하나를 선택합니다.
가위바위보 게임을 진행합니다.
순서도에 나와있는 것처럼 유저보다 높은 레벨의 상대는 두 번 이겨야
이길 수 있습니다..(생각보다 극악 난이도)
그리고 레벨과 경험치를 알려주고 다시 while문이 돌아갑니다.
2. 도망치기를 선택하면
경험치를 얻지 못하고 다시 수련장으로 돌아갑니다.
경험치가 0인 상태에서 몬스터에게 두방 맞으면
게임이 종료됩니다.
파티장은 오타입니다... 수련장입니다...
이긴 경우 세가지 선택지가 있는데
같은 레벨이면 100점을,
더 높은 레벨의 몬스터를 이기면 200점을,
낮은 레벨을 이기면 66점을 얻습니다.
이렇게 말이죠!
그리고 비기면 가위바위보 게임을 계속합니다.
그리고
안타깝게도 진짜 계속 져서
이긴 화면을 캡쳐하지 못했습니다.
2. 고민 및 해결한 내용
이전에 했던 가위바위보 코드를 다른분들은 쉽게 짰길래 나도 빼는 방식으로 해 봤다.
그려서 이렇게 그려보고 생각해본 후 적용했음
이런 오류가 나오는데요
분명 while문에서 안 멈춰서 오류가 나오는 것일텐데
이유를 모르겟습니다...진짜로
난수값이 초기화가 안된건가? -> 아님
else에 break가 없어서? -> 아님
====해결====
유저 레벨이 더 높을 때 다시 할 지 물어보는 부분을 추가
getchar();추가
하니까 해결완
오류가 더 있을지도 모르는 이 기분..
그리고 if문에서 혹시 모르는 가능성을 삭제하기 위해 else문을 쓰지 말라는 조언을 들었다.
해결되기 전 코드
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
// 변수 지정 시작
int battle_cnt=0; //전투 횟수
int win_cnt=0; //이긴 횟수
int lose_cnt=0; //진 횟수
int warning_point=0; //경험치 0일 때 경고주기. 2되면 게임오버
int user_level=1; //사용자 레벨. 1부터 시작하고 50되면 게임 종료(사용자 승리)
float user_exp=0; //사용자 경험치
char test; //게임 시작 함수 -> 필요없는 값
int level_up=100; //임의로 정한 1레벨당 경험치
int game_over=0; //버그수정을 위해 게임종료변수추가_ 제발일해
//게임 시작
printf(" 코딩 수련생\n");
printf(" 몬스터 lv.1\n");
printf(" ( •_•) (•_• )\n");
printf(" ( ง )ง ୧( ୧ )\n");
printf(" /︶\\ /︶\\\n");
printf("==========================================================\n");
printf("게임을 시작합니다! 여기는 코딩 인내의 숲길\n");
printf("C언어 몬스터를 물리쳐야 이곳을 빠져나갈 수 있습니다.\n");
printf("하지만 당신의 현실은 평범한 수련생 1...\n");
printf("열심히 수련해 레벨 50이 되면 던전파티에 껴준다고 합니다.\n");
printf("수련을 위해 수련장으로 이동합니다...\n");
printf("시작하려면 엔터를 눌러 주세요...");
scanf("%c", &test); //형식 지정자를 %c로 하면 엔터(enter)도 하나의 공백 문자로서 입력 받을 수 있다.
system("clear");
while(!game_over){
printf("==========================================================\n");
printf("수련장에 도착했습니다.\n");
//적들 등장
printf("당신의 현재 레벨은 %d입니다.\n", user_level);
printf("가위바위보를 5343422시간동안 마스터한 적들이 등장합니다...\n");
printf("==========================================================\n");
srand(time(NULL)); //타임값으로 시드값 결정
int enemy_level = rand() % 3 + 1; //적의 레벨 난수로 결정
int plus_or_minus = rand() % 2 + 1; //적의 레벨 높낮이 난수로 결정
if(plus_or_minus == 1){ //마이너스(-)
if(user_level - enemy_level <= 0) //유저 레벨 - 몬스터 레벨이 마이너스 값이 나오면
enemy_level = 1; //0을 반환해줌
else{
enemy_level = user_level - enemy_level; //그렇지 않으면 양수값 반환
}
}
else //플러스(+)
{
enemy_level = enemy_level + user_level;
}
// printf("사용자:%d, 적: %d", user_level, enemy_level); #겜제작자 위한 레벨 비교부분
printf("레벨 %d의 몬스터가 등장했습니다!\n", enemy_level);
//적들과 레벨 비교. 유저가 더 높으면 자동 승리
if(enemy_level >= user_level)
{
printf("이기기 조금 힘든 상대 같습니다...\n게임에 응하시겠습니까?\n");
printf("1. 게임 참가, 2. 도망친다: ");
int wanna_game;
scanf("%d", &wanna_game);
system("clear");
if(wanna_game == 1)
{ //유저가 전투에 참가 결정
battle_cnt ++;
int computer_choice = rand() % 3 + 1; //몬스터가 선택하는 가위바위보
int user_choice; //사용자 선택 함수
int win_cnt=0; //사용자가 적보다 레벨이 낮을 때 이긴 횟수 세줌
while(1)
{ //가위바위보 게임 시작
printf("전투를 시작합니다!\n");
printf("1. 가위, 2.주먹, 3.보 \n");
printf("선택하세요: \n");
scanf("%d", &user_choice);
if(user_choice == computer_choice){
printf("비겼습니다...다시 전투를 시작합니다!\n");
continue;
}
else if(user_choice - computer_choice == -2 || user_choice - computer_choice == 1){
printf("이겼습니다!\n");
win_cnt ++;
if(user_level < enemy_level){
if(win_cnt == 2){
printf("당신은 %d레벨만큼 높은 몬스터를 물리쳤습니다!\n", enemy_level - user_level);
printf("보상으로 %d의 경험치가 주어집니다.\n", 2 * level_up);
user_exp = user_exp + 2 * level_up;
break;
}
else{
printf("하지만 상대가 너무 강합니다... 한번 더 전투를 진행합니다!\n");
continue;
}
}
else if(user_level == enemy_level){
printf("당신의 레벨과 같은 상대를 이겼습니다!\n");
printf("보상으로 %d의 경험치가 주어집니다.\n", level_up);
user_exp = user_exp + level_up;
break;
}
else{
printf("test1");
break;
}
}
else
{
printf("졌습니다...");
if(user_exp == 0){
if(warning_point < 2){
warning_point ++;
printf("당신은 경험치가 부족합니다!\n");
printf("%d번 더 패배하면 게임 종료입니다.\n", 2-warning_point);
break;
}
if(warning_point == 2){
game_over = 1;
printf("당신은 패배했습니다.\n조금 더 가위바위보를 수련하세요.
return 0;
}
else{
printf("test2");
break;
}
}
else if(user_exp > 0){
printf("당신은 전투에서 졌지만 소량의 경험치를 얻었습니다!\n");
user_exp = user_exp + level_up * 2/3;
break;
}
else{
break; //설마 여기때문에 오류났나? 그러면 너무고마워 제발 이게마지막이라고해줘
}
}
}
}
else{ //유저가 전투 포기시
printf("당신은 가까스로 몬스터에게서 도망쳤습니다!\n");
printf("하지만 경험치는 얻지 못했습니다...\n");
}
}
else{ //사용자가 승리
//여기에 레벨 넣는 방식 추가
if(user_level > enemy_level){
printf("당신보다 %d레벨 낮은 몬스터를 물리쳤습니다!\n", user_level - enemy_level);
printf("보상으로 %.2f의 경험치가 주어집니다.\n", (double) 2/3 * level_up);
user_exp = user_exp + (2/3 * level_up);
}
else{
printf("test3");
}
}
//경험치 출력
int i=1;
while(1){
if(user_exp <= i*100){
user_level = i;
break;}
else{
i++;
}
}
user_level = i;
printf("현재 %d레벨입니다\n", i);
printf("당신의 경험치는 %.2fexp입니다.\n", (double)user_exp);
//레벨 비교 부분
if(user_level >= 50){
game_over = 1;
printf("YOU WIN !!\n"); //나중에 꾸미기
printf("당신은 %d번 싸우고 2차전직할 준비가 되었습니다.\n", battle_cnt); //나중에 꾸미기
printf("\n"); //나중에 꾸미기
break; //while문 빠져나가기
}
else{
printf("이 던전에서 빠져나가기 위해서는 수련이 필요합니다.\n");
printf("다시 파티장으로 이동합니다...\n");
continue; //게임 반복하기 (이 모든 부분을 while문으로 묶기)
}
}
return 0;
}
해결된 코드
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
// 변수 지정 시작
int battle_cnt = 0; // 전투 횟수
int win_cnt = 0; // 이긴 횟수
int lose_cnt = 0; // 진 횟수
int warning_point = 0; // 경험치 0일 때 경고주기. 2되면 게임오버
int user_level = 1; // 사용자 레벨. 1부터 시작하고 50되면 게임 종료(사용자 승리)
float user_exp = 0; // 사용자 경험치
char test; // 게임 시작 함수 -> 필요없는 값
int level_up = 100; // 임의로 정한 1레벨당 경험치
int game_over = 0; // 버그수정을 위해 게임종료변수추가_ 제발일해
int enemy_level; // 적의 레벨 난수로 결정
int plus_or_minus; // 적의 레벨 높낮이 난수로 결정
int wanna_game; // 다시게임할지 물음
// 게임 시작
printf(" 코딩 수련생\n");
printf(" 몬스터 lv.1\n");
printf(" ( •_•) (•_• )\n");
printf(" ( ง )ง ୧( ୧ )\n");
printf(" /︶\\ /︶\\\n");
printf("==========================================================\n");
printf("게임을 시작합니다! 여기는 코딩 인내의 숲길\n");
printf("C언어 몬스터를 물리쳐야 이곳을 빠져나갈 수 있습니다.\n");
printf("하지만 당신의 현실은 평범한 수련생 1...\n");
printf("열심히 수련해 레벨 50이 되면 던전파티에 껴준다고 합니다.\n");
printf("수련을 위해 수련장으로 이동합니다...\n");
printf("시작하려면 엔터를 눌러 주세요...");
scanf("%c", &test); // 형식 지정자를 %c로 하면 엔터(enter)도 하나의 공백 문자로서 입력 받을 수 있다.
system("clear");
while (game_over != 1)
{
printf("==========================================================\n");
printf("수련장에 도착했습니다.\n");
// 적들 등장
printf("당신의 현재 레벨은 %d입니다.\n", user_level);
printf("가위바위보를 5343422시간동안 마스터한 적들이 등장합니다...\n");
printf("==========================================================\n");
srand(time(NULL)); // 타임값으로 시드값 결정
enemy_level = rand() % 3 + 1; // 적의 레벨 난수로 결정
plus_or_minus = rand() % 2 + 1; // 적의 레벨 높낮이 난수로 결정
if (plus_or_minus == 1)
{ // 마이너스(-)
if (user_level - enemy_level <= 0)
{ // 유저 레벨 - 몬스터 레벨이 마이너스 값이 나오면
enemy_level = 1;
} // 0을 반환해줌
if (user_level - enemy_level > 0)
{
enemy_level = user_level - enemy_level; // 그렇지 않으면 양수값 반환
}
}
if (plus_or_minus == 2) // 플러스(+)
{
enemy_level = enemy_level + user_level;
}
printf("사용자:%d, 적: %d", user_level, enemy_level); // 겜제작자 위한 레벨 비교부분
printf("레벨 %d의 몬스터가 등장했습니다!\n", enemy_level);
// 적들과 레벨 비교. 유저가 더 높으면 자동 승리
if (enemy_level >= user_level)
{
printf("이기기 조금 힘든 상대 같습니다...\n게임에 응하시겠습니까?\n");
printf("1. 게임 참가, 2. 도망친다: ");
scanf("%d", &wanna_game);
system("clear");
if (wanna_game == 1)
{ // 유저가 전투에 참가 결정
battle_cnt++;
int computer_choice = rand() % 3 + 1; // 몬스터가 선택하는 가위바위보
int user_choice; // 사용자 선택 함수
int win_cnt = 0; // 사용자가 적보다 레벨이 낮을 때 이긴 횟수 세줌
while (1)
{ // 가위바위보 게임 시작
printf("전투를 시작합니다!\n");
printf("1. 가위, 2.주먹, 3.보 \n");
printf("선택하세요: \n");
scanf("%d", &user_choice);
getchar();
if (user_choice == computer_choice)
{
printf("비겼습니다...다시 전투를 시작합니다!\n");
continue;
}
else if (user_choice - computer_choice == -2 || user_choice - computer_choice == 1)
{
printf("이겼습니다!\n");
win_cnt++;
if (user_level < enemy_level)
{
if (win_cnt == 2)
{
printf("당신은 %d레벨만큼 높은 몬스터를 물리쳤습니다!\n", enemy_level - user_level);
printf("보상으로 %d의 경험치가 주어집니다.\n", 2 * level_up);
user_exp = user_exp + 2 * level_up;
break;
}
else
{
printf("하지만 상대가 너무 강합니다... 한번 더 전투를 진행합니다!\n");
continue;
}
}
else if (user_level == enemy_level)
{
printf("당신의 레벨과 같은 상대를 이겼습니다!\n");
printf("보상으로 %d의 경험치가 주어집니다.\n", level_up);
user_exp = user_exp + level_up;
break;
}
}
else
{
printf("졌습니다...");
if (user_exp == 0)
{
if (warning_point < 2)
if (user_exp == 0)
{
if (warning_point < 2)
{
warning_point++;
printf("당신은 경험치가 부족합니다!\n");
printf("%d번 더 패배하면 게임 종료입니다.\n", 2 - warning_point);
break;
}
if (warning_point == 2)
{
game_over = 1;
printf("당신은 패배했습니다.\n조금 더 가위바위보를 수련하세요.\n");
break;
}
}
else if (user_exp > 0)
{
printf("당신은 전투에서 졌지만 소량의 경험치를 얻었습니다!\n");
user_exp = user_exp + level_up * 2 / 3;
break;
}
else
{
break; // 설마 여기때문에 오류났나? 그러면 너무고마워 제발 이게마지막이라고해줘
}
}
}
}
else
{ // 유저가 전투 포기시
printf("당신은 가까스로 몬스터에게서 도망쳤습니다!\n");
printf("하지만 경험치는 얻지 못했습니다...\n");
continue;
}
}
if (enemy_level < user_level)
{
printf("이기기 매우 쉬운 상대 같습니다...\n게임에 응하시겠습니까?\n");
printf("1. 게임 참가, 2. 도망친다: ");
scanf("%d", &wanna_game);
getchar();
system("clear");
// 사용자가 승리
// 여기에 레벨 넣는 방식 추가
if (user_level > enemy_level)
{
printf("당신보다 %d레벨 낮은 몬스터를 물리쳤습니다!\n", user_level - enemy_level);
printf("보상으로 %.2f의 경험치가 주어집니다.\n", (double)2 / 3 * level_up);
user_exp = user_exp + (2 / 3 * level_up);
}
}
// 경험치 출력
int i = 1;
while (1)
{
if (user_exp <= i * 100)
{
user_level = i;
break;
}
else
{
i++;
}
}
user_level = i;
printf("현재 %d레벨입니다\n", i);
printf("당신의 경험치는 %.2fexp입니다.\n", (double)user_exp);
// 레벨 비교 부분
if (user_level >= 50)
{
game_over = 1;
printf("YOU WIN !!\n"); // 나중에 꾸미기
printf("당신은 %d번 싸우고 2차전직할 준비가 되었습니다.\n", battle_cnt); // 나중에 꾸미기
printf("\n"); // 나중에 꾸미기
break; // while문 빠져나가기
}
else
{
printf("이 던전에서 빠져나가기 위해서는 수련이 필요합니다.\n");
printf("다시 파티장으로 이동합니다...\n");
continue; // 게임 반복하기 (이 모든 부분을 while문으로 묶기)
}
}
return 0;
}
다시 해보니 while loop 돌아감 없이 잘 구현됩니다.
드디어 이길 수 있었습니다.
60번 이라니 극악난이도의 게임이 분명.
하지만 점수가 소수점이 출력이 잘 안된다
->내일 오전에 수정예정...
특이사항(아이디어 메모 등)
버그 찾다가 반장님이 컨트롤 에스 누르면 자동 정렬되는 기능을 알려줬는데
꿀팁 공유드립니다.
Vscode > code > Preferences > Settings(ctrl + ,)
검색창에 format on save 입력 > Format On Save의 체크박스 체크
검색창에 default foramtter -> c/c++ 체크
회고 / 해야 할 것
아직 순서도 그리는 부분이 많이 미진하다.
최대한 많은 상황을 고려해서 순서도를 짜고 코드에 적용하는 방법이 필요해 보인다.
그리고 오늘 기회가 된다면 함수 여러개로 게임 만들고 싶어졌다.. 메인함수 하나로 하려니까
들여쓰기 + 콤보로 + 굉장히 헷갈린다.
또 수정하고 싶은 부분은
1) 사용자가 지면 경험치가 깎이는 부분 추가하기: 계속 쌓이기만 하니까 이상하다. 겜세계의 먼치킨이 나?
2) 경험치 패치: 레벨업 하기 너무 힘들다. 나같으면 이 게임 안할 듯.. 높은 레벨을 이기면 훨씬 더 많은 경험치를 주는 방향으로 수정해야겠다.
3)아이템 사용하는 기능을 쓴다면,,??
그리고 해야할 것은
내가 만든 코드리뷰와 앞으로의 파이썬 예습!
되도록이면 수업시간에 과제를 다 끝내고 남아서 파이썬 공부를 해야겠다.
그럴 수 있을지 모르겠지만....
'개발공부 > C언어' 카테고리의 다른 글
(4.10) 개발원 27일차 (0) | 2023.04.10 |
---|---|
C언어_나무키우기 게임 만들기(4.5) (0) | 2023.04.09 |
C언어_게임만들기 순서도(1차) (0) | 2023.04.04 |
C언어_숫자야구 만들기 (0) | 2023.04.03 |
C언어_김밥천국 포스기 만들기 (0) | 2023.04.03 |