C# 문법 팀과제 - 3 ★★

이준호·2023년 11월 21일
0

C# 문법 팀과제 3일차



📌 추가된 점

나레이션 기능

// 나레이션 초기화 값
string tex = " 139번 훈련병! \n\n 너 이름이 뭐야? \n\n 이름을 입력 하세요... \n\n >>";
char[] texs = tex.ToCharArray();
        
foreach (char index in texs)
	{
		Console.Write(index);
		Thread.Sleep(100);
	}
player.Name = Console.ReadLine();
// 화면 초기화
Console.Clear();

문자열을 Char로 변환하면서 Char배열에 넣은 뒤에 foreach문으로 한글자씩 찍으면서 Thread.Sleep으로 딜레이를 줘서 채팅을 치는것 처럼 나레이션 방식으로 바꿔보았다.

선입력 방지

#region 선입력 방지
static void InputPrevention()
{
	bool inputPrevent = true;

	while (inputPrevent)
	{
		e = Console.ReadKey(true);
		switch (e.Key)
		{
			case ConsoleKey.Tab:
			inputPrevent = false;
			break;
			default:
			break;
		}
	}
}
#endregion

나레이션이나 게임을 할 때에 Console.ReadKey를 이용하여 받아서 넘기게 하였는데 그 부작용으로 아무키나 막 누르면서 넘길라고 하다보면 선입력이 발생하여 씬이 막 넘어가버리는 경우가 생겼다.
그래서 위와 같은 메서드를 만들어 캡슐화 시켜두어서 선입력 방지가 필요한 곳에 불러서 사용하게 하고 사용한 위에는 Console.WriteLine으로 Tap키를 눌러달라고 쓰게 하도록 했다.

📌 수정된 점

  • 스타트 ~ 메인 커서 선택으로 변경
    다른 팀원들의 메서드에 내가 캡슐화를 시켜놨던 메서드들로 번호로 선택하던 방식을 커서를 움직이며 선택하는 방식으로 바꾸었다.

  • 스타트 ~ 메인 메서드 위치 순서대로 변경
    메서드들이 진행 순서대로 있지 않고 여기저기 흩어져 있기에 순서대로 옮겼다.

  • 이등병 스토리(Basic) 및 훈련소(TrainingSchool) 텍스트 나레이션 방식으로 변경
    추가된 점에 적었던 나레이션 기능을 다른 글을 읽는 메서드들에 적용했다.

  • 스타트 ~ 메인 ~ 일과 텍스트 위치 조정
    맨 윗줄은 한줄 띄고 매 시작 글마다 한칸을 띄우고 글을 적자고 통일하여 전체적으로 돌아다니며 코드를 통일시켰다.

  • Item Class의 Food 공격력 삭제
    음식을 먹으면 공격력도 오르는 몇 아이템도 넣으려 했으나 시간이 부족할듯 하여 공격력은 뺏다.
    그에 따른 Food Class로 찍어낸 객체들도 수정했다.

  • 전투 메서드 텍스트 보정 및 Cursor선택으로 변경
    팀원이 만들어둔 전투 메서드에 번호 선택 방식을 커서 방식으로 바꾸었다.

    private static void AttackAction(Character player1, params Enemy[] enemies)
    {
    	// 초기 설정값
        int cursor = 0;
        bool onScene = true;
        string[] text = new string[enemies.Length];
        // 파라미터로 받은 몬스터들 텍스트에 추가
        for (int i = 0; i < enemies.Length; i++)
        {
            text[i] += " =" + enemies[i].EnemyName + "=\n";
        }

        while (onScene)
        {
            Console.Clear();
            Console.WriteLine("\n 어떤 몬스터를 공격하시겠습니까? \n ");

            TextChoice(cursor, text);
            e = Console.ReadKey();
            cursor = CursorChoice(e, cursor, text, ref onScene);
        }

        int playerDamage = player1.Attack();
        enemies[cursor].EnemyHp -= playerDamage;
        Console.WriteLine($" \n 플레이어가 {enemies[cursor].EnemyName}에게 {playerDamage}의 데미지를 입혔습니다.");
    }

📌 문제와 해결

Scene이동 구조에 따른 오류 ★★★

지금 우리의 게임 방식을 보면 처음 Start Scene메서드 부터 시작해서 각 메서드Scene이 끝날 때 마다 계속해서 다른 Scene메서드를 부르는 방식으로 만들어져 있다.

지금까지는 각 Scene 끝이나 조건이 달성되면 다른 Scene을 계속해서 불러 문제를 몰랐다. 하지만 그렇게 Scene을 계속 타고다니다가 다른 Scene을 부르지 않는 Scene을 만났을 때 문제가 발생했다.

Scene이 끝나면 그 Scene을 호출한 이전 Scene으로 이동하게 된다.
이러한 성질을 몰랐기에 심각한 오류가 발생한 것이다. Scene에서 Scene을 부르며 가게되면 점점 그 Scene에 Scene을 물어 쌓여가며 게임이 진행되면 진행될수록 콜스택(CallStack)이 쌓이게 되는 것이다.

이러한 성질을 알았다면 코드를 좀 더 깔끔하고 최적화도 잘 진행될수 있게 했을테지만 이미 과제의 시간이 얼마 남지 않았고 너무나 많이 와버렸기에 일단 최소한의 버그만 잡아보려고 했다.

while (true)
{
    string space = "";

    // 타이머 차감 및 남은 시간 텍스트
    time -= 0.1f;
    Console.SetCursorPosition(30, 5);
    Console.Write($"남은 시간 : {time.ToString("F")}");

    // player 위치 표시
    Console.SetCursorPosition(0, 1);
    for (int i = 0; i < x; i++)
    {
        space += " ";
    }
    Console.WriteLine(space + "O");

    // 이동 로직
    if (Console.KeyAvailable)
    {
        x++;
        Console.ReadKey(true);
    }
    // 완주시 반복문 정지
    if (x >= 80) break;
    // 타임 오버시
    if (time <= 0)
    {
        Console.Clear();
        Console.WriteLine("완주 실패....");
        Thread.Sleep(2000);
        Home();
    }
    Thread.Sleep(10);
}
Console.Clear();
Console.WriteLine("\n 완주 완료!!");
Console.WriteLine("\n 보상 계산중.... 잠시만 기다려주십시오.");
Thread.Sleep(2000);

Console.WriteLine("\n 남은 시간 : {0}", time.ToString("F"));
Console.WriteLine("\n 남은 시간에 따른 보상 ( 보상목록 )");
Console.WriteLine("\n >> Press the \"TAP\" key to proceed <<");
//선입력 방지 메서드
InputPrevention();
Home();

위 코드를 보면 완주에 실패하게 되어 타임오버가 되면 While문이 끝나기도 전에 Home(); 으로 가는 코드가 있다. 그렇기에 위에 설명해놓은 문제가 생기면 다시 Home을 호출한 Scene메서드인 이곳으로 돌아와 저 if문 안에서 왔다갔다 하게 되는 것이다.



while (true)
{
    string space = "";

    // 타이머 차감 및 남은 시간 텍스트
    time -= 0.1f;
    Console.SetCursorPosition(30, 5);
    Console.Write($"남은 시간 : {time.ToString("F")}");

    // player 위치 표시
    Console.SetCursorPosition(0, 1);
    for (int i = 0; i < x; i++)
    {
        space += " ";
    }
    Console.WriteLine(space + "O");

    // 이동 로직
    if (Console.KeyAvailable)
    {
        x++;
        Console.ReadKey(true);
    }
    // 완주시 반복문 정지
    if (x >= 80)
    {
        Console.Clear();
        Console.WriteLine("\n 완주 완료!!");
        Console.WriteLine("\n 보상 계산중.... 잠시만 기다려주십시오.");
        Thread.Sleep(2000);

        Console.WriteLine("\n 남은 시간 : {0}", time.ToString("F"));
        Console.WriteLine("\n 남은 시간에 따른 보상 ( 보상목록 )");
        Console.WriteLine("\n >> Press the \"TAP\" key to proceed <<");
        break;
    }
    // 타임 오버시
    if (time <= 0)
    {
        Console.Clear();
        Console.WriteLine("완주 실패....");
        Console.WriteLine("\n >> Press the \"TAP\" key to proceed <<");
        break;
    }
    Thread.Sleep(10);
}

//선입력 방지 메서드
InputPrevention();
Home();

Scene에서 Scene으로 이동하는 방식을 고치고 싶었지만 시간이 부족하여 위 코드처럼 최소한의 조치를 해두었다. While문 안에 있던 Scene의 이동을 While문이 종료되고 이동하는 방식으로 바꾸었다.

다음 프로젝트 부터는 이번에 경험했던 문제를 기억하고 초반에 기획에 집중하며 틀을 짜볼것 이다.

profile
No Easy Day

0개의 댓글