no image
내일배움캠프 17일차 TIL [TopDown게임 제작]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:00 : 새로운 팀 배정 및 팀원 자기소개10:00 ~ 10:30 : Unity 입문 챕터 발제 강의 수강10:30 ~ 13:00 : 2D TopDown Shooting 게임 개발 시작🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:30 ~ 16:00 : 이력서 작성 강의 (기본 정보, 자기소개, 프로젝트 항목 포함)16:00 ~ 18:00 : 탑다운 슈팅 게임 디버깅 및 기능 구현Input System 설정 오류 수정Sprite 설정 문제 해결투사체 생성/충돌 디버깅AudioSource 누락 문제 해결🍽️ 저녁시간18:00 ~ 19:00 : 저녁시간✅ 저녁19:00 ~ 21:00 : 깃허브 README 작성 및 프로젝트 업로드, TIL 작..
2025.07.22
no image
내일배움캠프 16일차 TIL [팀프로젝트 발표 + 유니티 개발]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : 프로젝트 회의 및 코드 정리전체 구조 리뷰 및 코드 수정팀원들과 기능 분담 및 로직 개선 방향 논의🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 16:00 : 프로젝트 발표팀 프로젝트 진행 상황 및 주요 구현 기능 발표트러블슈팅 내용 공유 및 발표자료 구성 피드백16:00 ~ 18:00 : Flappy Bird 스타일 게임 제작Player, Obstacle, BgLooper, FollowCamera, GameManager, UIManager 등 구현배경 루핑, 점프 및 장애물 통과 로직, 카메라 이동 구현🍽️ 저녁시간18:00 ~ 19:00 : 저녁시간✅ 저녁19:00 ~ 21:00 : Stack 블록 게임 UI 시스템 ..
2025.07.21
no image
WIL - 본 캠프 3주차(25.07.14~07.18)
25.07.19 TIL🗓️ 오늘 하루 일정 (2025-07-19)09:00 ~ 12:00 : 전투 시스템 수정 및 테스트용에게 죽을 경우 특별한 부활 이벤트 추가몬스터 레벨 조건, 이름 기반 이스터에그 처리13:00 ~ 16:00 : 스토리 연출 및 게임 오버/엔딩 구현인트로, 엔딩 스토리 출력 연출 개선레벨에 따라 다른 엔딩 분기 처리16:00 ~ 18:00 : TIL 작성 및 전체 테스트 마무리경험치 수동 상승(스페이스바 입력 시 증가) 디버그 기능 추가BattleState 흐름 점검 및 디버깅🧠 오늘의 학습 키워드C# 콘솔 연출 (Thread.Sleep / 컬러 출력 / 줄 단위 연출)클래스 간 static 변수 공유조건 분기 처리 (if, else, switch)상태 머신(BattleState..
2025.07.19
no image
내일배움캠프 15일차 TIL [TextRPG 팀프로젝트]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : 프로젝트 작업직업별 스킬 시스템 구조 리팩토링 (SkillSet 인터페이스 기반)UseSkill 메서드 구조 변경 및 범위 공격 구현장착 시스템 FinalAtk, FinalDef 구조 반영 확인회피 확률 → 민첩 기반으로 재설계 (DodgeChance 동적 계산)🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 18:00 : 팀 프로젝트 발표 준비발표용 코드 정리 및 구조 설명 작성몬스터 다수 공격 시 HP 변화 출력 개선 (prevHpDict)트러블슈팅 정리직업 클래스 구조 단순화 이슈 → 해결 과정퀘스트 클래스 역할 분리 이슈 → 해결 과정발표용 PPT 구성 요소 정리 및 작성 시작🍽️ 저녁시간18:00 ~ 19:00 :..
2025.07.18
no image
내일배움캠프 13일차 TIL [예비군 훈련 + 팀프로젝트 직업 밸런스+스킬 추가]
🗓️ 2025년 7월 16일 (수) – 오늘의 일정✅ 오전 & 오후09:00 ~ 18:00 : 예비군 훈련🍽️ 저녁시간18:00 ~ 19:00 : 저녁 식사🧘 개인시간19:00 ~ 20:00 : 개인 휴식🛠️ 팀 프로젝트 개발20:00 ~ 00:00 : 텍스트 RPG 직업 설계 및 스킬 개발직업 능력치 정리 및 보정 적용전사, 마법사, 도적, 궁수, 해적 클래스 정리각 직업별 스킬 3종 설계 및 코드 구현✅ 오늘 학습 키워드직업 클래스 설계 리팩터링능력치 자동 계산 구조 (계산 프로퍼티 활용)직업별 특성 기반 능력치 보정직업별 스킬 구조 설계 및 구현추상 메서드 오버라이드 구조✅ 오늘 학습 한 내용을 나만의 언어로 정리하기오늘은 텍스트 RPG 프로젝트에서 직업 시스템과 전투 스킬 구조를 본격적으로..
2025.07.16
no image
내일배움캠프 12일차 TIL [예비군 훈련 + 팀프로젝트 퀘스트내용 개발]
🗓️ 오늘 하루 일정 (2025년 7월 15일)✅ 오전 ~ 오후09:00 ~ 18:00 : 예비군 훈련훈련소 출석 및 전반 일정 소화🍽️ 저녁시간18:00 ~ 19:00 : 저녁식사 및 휴식💻 개인 작업 시간19:00 ~ 23:00 : 텍스트 RPG 프로젝트 작업Quest 시스템 UI 기획 및 전체 구조 수정QuestUI.cs에서 퀘스트 목록 → 상세 보기 흐름 구현Console ASCII UI 3D 형태 조정 (QUEST 박스 완성)콘솔 폭 맞춤 문제로 인한 출력 깨짐 디버깅최종적으로 깔끔한 Console.WriteLine 출력으로 리셋 및 구조 정비✅ 오늘 학습 키워드Console.WriteLine() UI 구성ASCII 아트 박스 디자인 (QUEST)퀘스트 목록 출력 및 선택 흐름List 처리..
2025.07.15
no image
내일배움캠프 11일차 TIL [예비군 훈련 + 팀프로젝트 클래스 구조 설계]
🗓️ 오늘 하루 일정✅ 오전 & 오후09:00 ~ 18:00 : 예비군 훈련🍽️ 저녁시간18:00 ~ 19:00 : 저녁식사✅ 저녁19:00 ~ 20:00 : 팀 프로젝트 회의20:00 ~ 20:30 : 팀원들과 프로젝트 계획 조율20:30 ~ 21:00 : 개인 TIL 작성✅ 심야 작업21:00 ~ 00:00 : 게임 저장 시스템 구조 설계 및 디버깅GameSaveData 클래스: 저장할 캐릭터 정보, 인벤토리, 완료 퀘스트 등 데이터 모델 정의SaveManager 클래스: JSON 저장/불러오기 기능 및 자동 경로 생성 처리실행 경로 기준 상대 경로 저장 위치 확인 (bin/Debug/net8.0/...) 및 경로 재설정Unicode 이스케이프(예: \\uC7AC\\uC740) 현상 확인 및 보기..
2025.07.15
no image
C# - Longest Increasing Subsequence
📘 300. Longest Increasing Subsequence🔹 문제 설명정수 배열 nums가 주어질 때,배열에서 오름차순으로 증가하는 가장 긴 부분 수열의 길이를 구하라.부분 수열(subsequence):(연속된 값일 필요는 없음)원래 배열에서 순서를 유지하면서 일부 원소를 건너뛰어 선택할 수 있음🔸 예시Input: nums = [10, 9, 2, 5, 3, 7, 101, 18]Output: 4설명: 가장 긴 오름차순 부분 수열은 [2, 3, 7, 101] 이므로 길이는 🔹 조건1 10⁴ 🎯 목표👉 배열에서 가장 길게 오름차순으로 증가하는 부분 수열을 찾아서그 길이를 반환하는 함수를 작성하는 것이 목표야.✅ 예시 2Input: nums = [0, 1, 0, 3, 2, 3]Output: ..
2025.07.13
C#
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 10:00 : 새로운 팀 배정 및 팀원 자기소개
  • 10:00 ~ 10:30 : Unity 입문 챕터 발제 강의 수강
  • 10:30 ~ 13:00 : 2D TopDown Shooting 게임 개발 시작

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심시간

✅ 오후

  • 14:30 ~ 16:00 : 이력서 작성 강의 (기본 정보, 자기소개, 프로젝트 항목 포함)
  • 16:00 ~ 18:00 : 탑다운 슈팅 게임 디버깅 및 기능 구현
    • Input System 설정 오류 수정
    • Sprite 설정 문제 해결
    • 투사체 생성/충돌 디버깅
    • AudioSource 누락 문제 해결

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁시간

✅ 저녁

  • 19:00 ~ 21:00 : 깃허브 README 작성 및 프로젝트 업로드, TIL 작성
    • TheStack, TopDown 프로젝트 업로드
    • 각 프로젝트 리드미 작성
    • 트러블슈팅/폴더 구조 정리

✅ 오늘 학습 키워드

  • Unity 2D TopDown Shooting 개발
  • Input System 이벤트 함수 매핑 (OnMove, OnLook, OnFire)
  • 투사체 발사 및 충돌 처리 (ProjectileManager, ProjectileController)
  • SpriteRenderer 누락 및 이미지 표시 문제 해결
  • AudioSource 컴포넌트 오류 디버깅 (SoundManager)
  • 애니메이션 이벤트 오류 (AnimationEvent without function)
  • EnemyManager를 통한 적 생성 및 웨이브 진행 구조
  • GameManager 흐름 제어 및 Init 함수 호출 구조
  • GitHub 프로젝트 업로드 방식
  • .gitignore 및 라이선스 설정
  • README.md 작성 실습 (프로젝트 설명, 기능 요약, 트러블슈팅, 폴더 구조)
  • Resume 작성 기초 강의 (기본 정보, 자기소개, 프로젝트 항목 중심)

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

 

Unity - Singleton Pattern (싱글톤 패턴) in Unity

🎮 Unity에서의 싱글톤(Singleton) 패턴🔍 싱글톤이란?싱글톤(Singleton)은 프로그램 전체에서 단 하나의 인스턴스만 존재하도록 보장하는 디자인 패턴이다. 게임에서는 주로 오디오 매니저, 게임 매

dev-jen.tistory.com

 

Unity - Unity에서의 Generic Singleton 패턴

❓ 왜 Generic Singleton이 필요할까?Unity에서는 GameManager, SoundManager, UIManager 등 다양한 매니저 클래스에서 싱글톤(Singleton) 패턴을 사용한다.하지만 매번 static instance 선언, Awake()에서 중복 제거 같은

dev-jen.tistory.com

 

오늘은 새로운 팀에 배정되고, 팀원들과 인사를 나눈 후 개인 프로젝트로 2D TopDown 슈팅 게임 개발을 시작했다. Unity Input System을 적용하면서 OnMove, OnLook, OnFire 같은 입력 함수가 자동으로 호출되기 위해서는 Input 액션 이름과 함수명이 정확히 일치해야 한다는 것을 다시 한번 확인했다. 단순한 오타로 인해 캐릭터가 움직이지 않았던 상황이 있었고, 해당 이슈를 해결하며 Input System의 작동 원리에 대해 더 명확히 이해하게 되었다.

또한 ProjectileManager와 ProjectileController를 통해 투사체를 생성하고, RaycastHit2D로 충돌 여부를 판별하여 적에게 데미지를 주는 로직을 구현했다. 화살이 생성되었는데도 이미지가 보이지 않아 당황했는데, 이는 프리팹에 SpriteRenderer가 누락된 것이 원인이었다. 이처럼 사소한 실수가 게임 동작에 영향을 줄 수 있다는 점을 다시금 느꼈다.

사운드 구현 과정에서는 SoundManager가 참조하는 AudioSource 컴포넌트가 오브젝트에 붙어 있지 않으면 MissingComponentException이 발생한다는 걸 직접 경험하며, Unity에서 컴포넌트 구조를 꼼꼼히 확인하는 습관의 중요성을 배웠다.

마지막으로, 오늘 만든 TheStack과 TopDown 프로젝트를 GitHub에 업로드하고, 리드미를 정리하면서 폴더 구조, 기능 설명, 트러블슈팅 내용을 문서화했다. 이렇게 기록하는 과정이 내가 만든 프로젝트를 더 명확하게 이해하게 해주었고, 앞으로 포트폴리오 작성에도 큰 도움이 될 것 같다.


🧩 학습하며 겪었던 문제점 & 에러

1. ❌ 캐릭터가 움직이지 않음

  • 문제정의: 플레이어가 키 입력을 받아도 움직이지 않았다.
  • 시도: PlayerController의 OnMove()가 제대로 작성되어 있는지, InputAction 설정이 되어 있는지 확인.
  • 해결 방법: InputAction의 이름이 Lock으로 잘못 작성되어 있었음. Look으로 수정하자 마우스 방향 회전도 정상 작동함.
  • 새롭게 알게 된 점: Input System은 액션 이름과 함수명이 정확히 일치해야 메서드가 호출된다.
  • 다시 만나게 된다면: Input Action 설정 후 함수 연결 확인 시 오타 여부를 가장 먼저 점검하자.

2. ❌ 투사체는 생성되지만 이미지가 보이지 않음

  • 문제정의: 활 공격 시 화살이 생성되지만 Sprite가 보이지 않았다.
  • 시도: ProjectileController의 로직 점검, SpriteRenderer의 설정 확인.
  • 해결 방법: projectilePrefabs로 등록한 화살 프리팹에 SpriteRenderer 컴포넌트가 누락되어 있었음. SpriteRenderer를 추가하자 정상적으로 이미지 출력됨.
  • 새롭게 알게 된 점: 프리팹 구성 요소 중 하나라도 누락되면 기능은 작동해도 시각적으로 표시되지 않을 수 있다.
  • 다시 만나게 된다면: 프리팹 등록 전 구성 요소 체크리스트를 확인하자.

3. ❌ 효과음 재생 시 MissingComponentException 발생

  • 문제정의: 게임 실행 시 SoundManager에서 BGM을 재생하려다 MissingComponentException 발생.
  • 시도: 로그를 따라 AudioSource 관련 코드 위치 확인.
  • 해결 방법: SoundManager 오브젝트에 AudioSource가 빠져 있었음. Add Component로 추가하여 해결.
  • 새롭게 알게 된 점: 스크립트에서 사용하는 컴포넌트는 Inspector에서 수동 추가가 필요한 경우가 많다.
  • 다시 만나게 된다면: Awake 또는 Start에서 사용하는 컴포넌트가 Editor 상에 존재하는지 꼭 확인하자.

📝 메모

오늘은 개인적으로 만든 탑다운 슈팅 게임 프로젝트를 디버깅하면서 정말 많은 걸 배웠다.

처음엔 단순히 Sprite가 안 보이는 이유가 코드 때문일 줄만 알았는데, 오히려 Inspector에서의 누락이 문제였다는 걸 깨달았고,

Input System도 처음 도입하면서 Action 이름과 함수 이름이 정확히 일치해야 작동하는 등, 작은 오타 하나로 전체 흐름이 막힐 수 있다는 점을 체감했다.

디버깅을 반복하며 단순히 "왜 안 되지?"를 넘어서, **"내가 무엇을 놓치고 있는가?"**를 묻는 습관을 조금씩 갖게 되는 하루였다.

그리고 무엇보다 중요한 건 "작은 성공 경험"을 계속 축적하는 일인 것 같다. 하나하나 오류를 해결해 나가며 기능이 살아나는 그 순간의 기쁨은, 정말 다시 코드를 짜고 싶게 만든다.

내가 만든 프로젝트를 깃허브에 올리면서 처음으로 README를 제대로 구성해봤는데,

정리된 폴더 구조와 트러블슈팅 문서를 작성하는 경험 자체가 내 코드에 대한 애정을 더 깊게 만들어줬다.

사실 과제를 빠르게 만들고싶어서 급하게 하다 많은 오류가 났었던거같다.. 내일은 다시 코드리뷰해보면서 하나씩 되짚어봐야겠다.

하루하루 화이팅!!!~!!

 

TopDown 실행화면

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 13:00 : 프로젝트 회의 및 코드 정리
    • 전체 구조 리뷰 및 코드 수정
    • 팀원들과 기능 분담 및 로직 개선 방향 논의

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심시간

✅ 오후

  • 14:00 ~ 16:00 : 프로젝트 발표
    • 팀 프로젝트 진행 상황 및 주요 구현 기능 발표
    • 트러블슈팅 내용 공유 및 발표자료 구성 피드백
  • 16:00 ~ 18:00 : Flappy Bird 스타일 게임 제작
    • Player, Obstacle, BgLooper, FollowCamera, GameManager, UIManager 등 구현
    • 배경 루핑, 점프 및 장애물 통과 로직, 카메라 이동 구현

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁시간

✅ 저녁

  • 19:00 ~ 21:00 : Stack 블록 게임 UI 시스템 구현
    • BaseUI, HomeUI, GameUI, ScoreUI, UIManager 설계
    • TheStack 게임 로직 완성 및 UI 연동
    • 점수/콤보 UI 반영, 버튼 이벤트 연결 방식 개선

✅ 오늘 학습 키워드

  • Unity UI 시스템
  • BaseUI 및 상태 기반 UI 전환
  • TextMeshPro와 버튼 이벤트 인스펙터 연결
  • PlayerPrefs를 이용한 점수 저장
  • 2D 배경 루프 구현 (BgLooper)
  • Flappy Bird 스타일 점프 및 장애물 재배치 로직
  • 카메라 따라가기 구현 (FollowCamera)
  • NullReferenceException 디버깅 및 인스펙터 연결 방식 개선
  • 게임 매니저(GameManager) 중심의 흐름 제어
  • Stack 블록 정렬 판정 및 콤보 보상 시스템

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

오늘 오전에는 그동안 팀원들과 함께 개발해왔던 TextRPG 프로젝트를 중심으로 전체 코드 구조를 점검하고 회의를 진행했다. 기능이 많아지면서 코드가 점점 복잡해졌기 때문에, 각 클래스의 책임을 명확히 나누고 UI, 전투, 퀘스트, 저장 시스템 등 각 모듈별로 정리된 형태로 개선해보자는 공감대가 있었다. 특히 트러블슈팅 내용들을 발표 자료로 정리하면서 구조 개선의 필요성과 우리가 어떤 식으로 문제를 해결해왔는지 되돌아볼 수 있었던 의미 있는 시간이었다.

오후 발표 이후에는 완전히 다른 2D 게임들을 구현하면서 Unity의 다양한 시스템들을 익힐 수 있었다. 먼저 Flappy Bird 스타일의 게임에서는 Player 캐릭터가 점프하고 장애물을 피하는 간단한 구조를 만들었지만, 그 안에서도 배경 루프, 장애물 재배치, 카메라 따라가기 같은 중요한 기능들을 경험할 수 있었다. BgLooper에서 배경과 장애물을 적절한 위치로 재배치해 무한히 이어지는 듯한 느낌을 주는 로직이 특히 인상 깊었다.

저녁에는 Stack 블록 게임을 완성도 있게 구현했다. 블록이 일정한 속도로 좌우 이동하며, 플레이어가 타이밍 맞춰 멈추게 하면 정확도에 따라 잘려나가거나 콤보가 쌓이는 구조를 갖고 있다. 정확하게 쌓을수록 콤보가 쌓이고, 일정 콤보마다 블록이 커지는 보상이 주어져 게임성이 높아졌다. UI 시스템도 BaseUI를 중심으로 상태 기반으로 관리했고, TextMeshPro와 버튼 이벤트를 인스펙터에서 직접 연결해 오류 없이 깔끔하게 동작하게 만들었다. 특히 NullReferenceException 오류를 직접 겪고 나서 구조를 변경한 경험이 큰 배움으로 남았다.


🧩 학습하며 겪었던 문제점 & 에러

1. NullReferenceException 오류 (ScoreUI.cs)

  • 문제정의
  • UIManager가 ScoreUI를 초기화할 때 transform.Find()로 찾은 오브젝트들이 null이 되어 NullReferenceException이 발생함.
  • 시도
  • 오브젝트 이름이 잘못되었나 확인하고, 프리팹 구조를 여러 번 점검함.
  • 해결방법
  • 모든 UI 요소를 public으로 선언하고, 인스펙터에서 직접 연결하는 방식으로 변경함.
  • 새롭게 알게 된 점
  • 코드 상에서 무조건 transform.Find()로 접근하기보다는, 인스펙터 연결을 통해 안정성과 명확성을 높이는 것이 좋다는 점을 배움.
  • 다시 만나게 된다면
  • UIManager에서 UI 요소를 초기화할 때는 반드시 null 체크와 연결 상태를 사전에 점검해야 함.

2. InvalidCastException 오류 (BgLooper.cs)

  • 문제정의
  • BoxCollider2D로 캐스팅하려던 백그라운드 오브젝트가 실제로 BoxCollider2D가 아니라 오류가 발생함.
  • 시도
  • collision에 어떤 컴포넌트가 붙어 있는지 디버깅으로 확인하고, GetComponent<BoxCollider2D>()로 수정 시도함.
  • 해결방법
  • ((BoxCollider2D)collision) → collision.GetComponent<BoxCollider2D>()로 수정하여 해결.
  • 새롭게 알게 된 점
  • Collider2D를 바로 캐스팅하는 것은 위험할 수 있으며, GetComponent를 통해 필요한 컴포넌트를 명확히 가져와야 안정적임.

3. NullReferenceException 오류 (TheStack.cs)

  • 문제정의
  • 게임 시작 후 lastBlock이 null 상태인데도 MoveBlock()에서 접근하며 NullReferenceException 발생.
  • 시도
  • Update() 흐름을 점검하고 lastBlock 초기화 타이밍을 확인함.
  • 해결방법
  • if (lastBlock == null) return; 체크를 MoveBlock() 내부에 추가하여 예외 방지.
  • 새롭게 알게 된 점
  • 오브젝트 생성 직후 프레임 내에서 처리되는 흐름을 고려해야 하며, null 방어 코드가 항상 중요함.

📝 메모

오늘은 진짜 많은 걸 겪고, 많이 배운 하루였다.

오전에는 TextRPG 프로젝트 회의를 하면서 우리가 얼마나 많은 기능을 구현해왔는지 되돌아봤고, 그 과정에서 구조적인 한계와 개선 방향을 직접 확인할 수 있었다. 발표 준비를 하면서 트러블슈팅 내용을 정리했던 것도 내가 어떤 고민을 했는지 되짚어볼 수 있는 좋은 기회였다.

오후에는 Flappy Bird 스타일 게임을 처음부터 새로 만들면서 Unity의 2D 시스템을 적극적으로 활용해봤다. 반복되는 배경, 장애물 위치 재배치, 플레이어 사망 처리 등 단순해 보여도 실제로 구현하면 고려할 게 많은 구조였다.

저녁에는 Stack 게임을 마무리하면서 UIManager, BaseUI 구조를 직접 설계하고 버튼 이벤트를 인스펙터에서 연결하는 방식을 적용했다. 그동안 transform.Find()만 쓰다가 오류를 계속 만나고 나서 구조를 바꾼 건, 단순히 기능을 구현하는 걸 넘어 '왜 이런 설계가 더 나은가'를 직접 체험한 값진 경험이었다.

실수도 많았지만, 그만큼 코드를 더 깊이 이해할 수 있었고, 내가 만든 시스템들이 점점 단단해지고 있다는 느낌을 받았다.

내일도 화이팅!!!!!

 

🧩 오늘 만든 게임들!

Flappy Bird 비슷한 게임?


The Stack 게임

반응형
반응형

25.07.19 TIL

🗓️ 오늘 하루 일정 (2025-07-19)

  • 09:00 ~ 12:00 : 전투 시스템 수정 및 테스트
    • 용에게 죽을 경우 특별한 부활 이벤트 추가
    • 몬스터 레벨 조건, 이름 기반 이스터에그 처리
  • 13:00 ~ 16:00 : 스토리 연출 및 게임 오버/엔딩 구현
    • 인트로, 엔딩 스토리 출력 연출 개선
    • 레벨에 따라 다른 엔딩 분기 처리
  • 16:00 ~ 18:00 : TIL 작성 및 전체 테스트 마무리
    • 경험치 수동 상승(스페이스바 입력 시 증가) 디버그 기능 추가
    • BattleState 흐름 점검 및 디버깅

🧠 오늘의 학습 키워드

  • C# 콘솔 연출 (Thread.Sleep / 컬러 출력 / 줄 단위 연출)
  • 클래스 간 static 변수 공유
  • 조건 분기 처리 (if, else, switch)
  • 상태 머신(BattleState) 전개 구조 이해
  • 디버그 입력 처리 (Console.ReadKey())

📘 오늘 배운 내용을 나만의 언어로 정리하기

  • Thread.Sleep()과 컬러 출력을 활용하여, 스토리를 줄 단위로 자연스럽게 보여주는 연출을 구현했다. 사용자 경험을 높이기 위해 ConsoleColor, 아이콘 이모지, 랜덤 딜레이 등을 활용했다.
  • 플레이어가 **특정 몬스터(광포한 레드 드래곤)**에게 죽었을 경우에만 부활하는 이스터에그를 구현했고, Name.Contains() 로 문자열 일치를 판단했다.
  • 레벨에 따라 게임 오버 시 나오는 엔딩 분기 조건을 player.Level >= 10로 설정하여 엔딩의 무게감을 조정했다.
  • Battle.isEnd라는 static 변수를 통해 엔딩 중복 출력 방지 로직을 관리했다.
  • 테스트 편의성을 위해 스페이스바 입력 시 경험치 1 증가 기능을 추가해 레벨업과 엔딩 출력 조건을 빠르게 확인할 수 있도록 했다.

🧩 학습하며 겪었던 문제점 & 에러

1. 문제정의

광포한 레드 드래곤에게 죽었는데 TriggerDragonResurrection() 함수가 실행되지 않음.

  • 시도: 이름 비교 "광포한 레드 드래곤" 조건 확인
  • 해결방법: Name.Contains("광포한 레드 드래곤") 으로 수정 → 정상 실행
  • 새롭게 알게 된 점: 문자열 비교는 == 대신 Contains() 또는 Equals()(대소문자 옵션 포함)를 상황에 맞게 사용해야 함.
  • 다시 만나게 된다면: 디버깅할 때 해당 몬스터의 Name을 로그에 찍어서 확인하자.

2. 문제정의

ShowEnding() 내부 조건문에서 컴파일 에러 발생

  • 시도: if 없이 (조건식)만 작성함
  • 해결방법: if (조건) {}로 감싸고 중괄호 블록 구조 정리
  • 새롭게 알게 된 점: C#에서는 단독 조건식은 if, switch 등 문맥 내에서만 허용됨
  • 다시 만나게 된다면: 항상 if, else는 블록으로 감쌀 것

 

 

 

 

🌈 2025년 7월 셋째 주 WIL: 몰입과 성장의 시간들

1. 지난 일주일 동안 가장 인상 깊었던 배움은?

이번 주는 텍스트 RPG에 스토리와 생명력을 불어넣는 작업에 집중했다.
기존의 전투 시스템에 연출을 입히고, 플레이어의 선택에 따라 다양한 결과와 엔딩이 발생하도록 구성했다.
특히, 광포한 레드 드래곤에게 죽으면 부활하는 이스터에그,
레벨 10 이상일 때만 나오는 '인간의 선봉장' 엔딩은 내가 직접 상상했던 세계관을 코드로 구현해내면서 정말 뿌듯했던 순간이었다.

텍스트 기반이지만 Thread.Sleep()과 ConsoleColor, 아이콘 이모지를 활용해서
몰입감 있는 이야기 전달이 가능하다는 걸 온몸으로 배웠다.
이건 분명 내가 만든 "게임"이라는 매체가 줄 수 있는 특별한 감동이었다.


2. 배움까지 다가가는데 어떤 어려움이 있었지?

  • BattleState 흐름 오류 때문에 특정 상황에서 메뉴가 반복되거나 전투가 겹쳐 출력되는 문제가 발생했다.
  • if 문을 깜빡하거나 Console.Clear() 위치가 부적절해서 출력이 겹치는 문제도 많이 겪었다.
  • 레벨업 경험치 처리와 전투 종료 후 경험치 중복 증가 등 논리적 오류를 디버깅하면서 꽤 많은 수정을 반복해야 했다.

하지만 이러한 오류들 덕분에 프로그램 흐름을 더 깊이 이해하게 되었고,
클래스 간 static 변수 관리, 조건 분기 흐름, UI 출력 타이밍 등에 대해 한층 더 단단해진 느낌이다.


3. 그 과정을 겪으며 나는 무엇을 깨달았고, 어떤 감정이 들었었지?

가장 많이 느낀 건,

"게임은 단순히 작동하는 코드 그 이상이라는 것"
이었다.

단순히 전투가 돌아간다고 해서 재미있는 게 아니었다.
그 안에 몰입할 수 있는 문장 하나, 연출 하나, 기대하게 만드는 선택지 하나가 있을 때
플레이어가 감정을 이입하고, 이야기로 느낄 수 있다는 걸 배웠다.

그리고 내가 이걸 만들어내고 있다는 게 너무 신기하고,
처음엔 단순한 콘솔 RPG였지만, 지금은 나만의 세계가 조금씩 완성되어 가는 것 같아서 매일매일 기대됐다.
작은 부분이라도 완성될 때마다 큰 성취감이 밀려왔다.


4. 💭 메모

  • 이번 주는 유독 “내가 만들고 있는 게임”이라는 감정이 강하게 들었던 한 주였다.
  • 어느새 “이건 단순히 과제가 아니라, 내가 진심을 담은 작품”이라는 생각이 들었고,
  • 그런 만큼 디테일 하나하나에 더 집착했고, 덕분에 내가 몰랐던 내 실력까지 꺼내볼 수 있었다.

앞으로도 단순히 “되게 하는” 코드가 아니라
“전달하고, 느끼게 하고, 기억에 남게 하는” 코드를 짜고 싶다.

 

이번주는 예비군때문에 많은 내용을 하지않았지만 그래도 예비군 끝나고 거의 매일 12시까지 나머지 작업을 했었다 팀원들에게도 너무 미안했고..ㅠㅜ 그래서 주말에도 남은 작업을 진행했다! 이제 이정도면 완성한거같다 ㅎㅎ.. 예비군때문에 별로 참여도못했으니 열심히라도 해야지..  이제 벌써 3주차다 앞으로도 화이팅해보자!!!!

📅 이번 주 TIL 목록

 

내일배움캠프 11일차 TIL [예비군 훈련 + 팀프로젝트 클래스 구조 설계]

🗓️ 오늘 하루 일정✅ 오전 & 오후09:00 ~ 18:00 : 예비군 훈련🍽️ 저녁시간18:00 ~ 19:00 : 저녁식사✅ 저녁19:00 ~ 20:00 : 팀 프로젝트 회의20:00 ~ 20:30 : 팀원들과 프로젝트 계획 조율20:30 ~ 21:00 : 개인 TI

dev-jen.tistory.com

 

내일배움캠프 12일차 TIL [예비군 훈련 + 팀프로젝트 퀘스트내용 개발]

🗓️ 오늘 하루 일정 (2025년 7월 15일)✅ 오전 ~ 오후09:00 ~ 18:00 : 예비군 훈련훈련소 출석 및 전반 일정 소화🍽️ 저녁시간18:00 ~ 19:00 : 저녁식사 및 휴식💻 개인 작업 시간19:00 ~ 23:00 : 텍스트 RPG

dev-jen.tistory.com

 

내일배움캠프 13일차 TIL [예비군 훈련 + 팀프로젝트 직업 밸런스+스킬 추가]

🗓️ 2025년 7월 16일 (수) – 오늘의 일정✅ 오전 & 오후09:00 ~ 18:00 : 예비군 훈련🍽️ 저녁시간18:00 ~ 19:00 : 저녁 식사🧘 개인시간19:00 ~ 20:00 : 개인 휴식🛠️ 팀 프로젝트 개발20:00 ~ 00:00 : 텍스트

dev-jen.tistory.com

 

내일배움캠프 15일차 TIL [TextRPG 팀프로젝트]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : 프로젝트 작업직업별 스킬 시스템 구조 리팩토링 (SkillSet 인터페이스 기반)UseSkill 메서드 구조 변경 및 범위 공격 구현장착 시스템 FinalAtk, FinalDef 구조 반

dev-jen.tistory.com

 

 

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 13:00 : 프로젝트 작업
    • 직업별 스킬 시스템 구조 리팩토링 (SkillSet 인터페이스 기반)
    • UseSkill 메서드 구조 변경 및 범위 공격 구현
    • 장착 시스템 FinalAtk, FinalDef 구조 반영 확인
    • 회피 확률 → 민첩 기반으로 재설계 (DodgeChance 동적 계산)

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심시간

✅ 오후

  • 14:00 ~ 18:00 : 팀 프로젝트 발표 준비
    • 발표용 코드 정리 및 구조 설명 작성
    • 몬스터 다수 공격 시 HP 변화 출력 개선 (prevHpDict)
    • 트러블슈팅 정리
      • 직업 클래스 구조 단순화 이슈 → 해결 과정
      • 퀘스트 클래스 역할 분리 이슈 → 해결 과정
    • 발표용 PPT 구성 요소 정리 및 작성 시작

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁시간

✅ 저녁

  • 19:00 ~ 21:00 : 발표용 트러블슈팅 작성 & 마무리 피드백
    • 발표용 설명 작성: 다형성, 체력 추적, 스킬 범위 공격 등
    • 퀘스트 시스템 구조 변경 경험 정리
    • 아이템 리스트 구조 변경 내용 보완

✅ 오늘 학습 키워드

  • SkillSet 인터페이스 기반 직업 다형성
  • 범위 스킬 및 피해 대상 추적 출력
  • FinalAtk, FinalDef 개념으로 능력치 분리
  • DodgeChance = 민첩 기반 회피 확률 구현
  • 발표용 트러블슈팅 작성
  • 퀘스트 클래스 역할 분리 (Manager, UI, 데이터)

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

🎯 직업 스킬 구조의 리팩토링

  • 기존에는 Job 클래스별로 스킬을 따로 정의했는데, 유지보수가 어렵고 중복이 많았음.
  • SkillSet 인터페이스를 정의하고, 각 직업이 이를 상속해 고유 스킬을 구현하게 변경함.
  • UseSkill(int index, Player, List<Monster>, Monster mainTarget) 시그니처로 통일하여, 단일/다중 타겟 모두 처리 가능하게 함.
  • 이로써 다형성을 통한 유연한 스킬 시스템을 완성했고, 전사, 마법사, 궁수, 도적, 해적 모두 동일한 틀 안에서 관리 가능해짐.

🌀 몬스터 다수 공격 처리

  • prevHpDict = monsterSpanwed.ToDictionary(m => m, m => m.Hp) 를 활용해,
  • 스킬 사용 전 몬스터들의 체력을 저장 → 공격 후 변화가 있는 몬스터만 출력함.
  • 이 과정은 DisplayHpInfo 함수를 통해 시각적으로 체력 감소 효과를 보여줌.
  • 피해를 입은 대상만 출력되므로 플레이어의 인식이 명확해지고 몰입도 증가.

🛡️ 능력치 구조 정리

  • 기존에는 Atk, Def 등 수치가 장비 장착 시 바로 바뀌어 관리가 어려웠음.
  • Atk + ExtraAtk = FinalAtk, Def + ExtraDef = FinalDef 구조로 분리.
  • 덕분에 장착 효과와 기본 능력치를 분리해 관리할 수 있게 되었고,
  • 장착/해제/판매 시에도 안정적으로 적용됨.

🧠 회피 확률 계산 방식 개선

  • 기존에는 DodgeChance가 고정값이었는데, 민첩 Dex 수치를 기반으로 동적으로 계산하도록 변경.
  • 예: DodgeChance = Math.Min(50, Dex / 2) 처럼 민첩 수치가 높을수록 회피율도 증가하도록 설정함.
  • 이로 인해 능력치가 전투에 직접적인 영향을 주는 구조로 개선됨.

🧩 학습하며 겪었던 문제점 & 에러

① 문제정의: 직업 클래스를 Job으로 나누니 코드가 너무 복잡해졌다

🧩 문제 상황

  • 처음에는 직업마다 Job 클래스를 만들어 공격력, 방어력, 스킬 등을 직접 구현했다.
  • 예를 들어 WarriorJob, MageJob, ThiefJob 같은 식으로 클래스가 각각 존재했음.
  • 직업이 늘어날수록 코드가 급격히 길어지고, 스킬을 사용하는 방식이 서로 달라지다 보니 호출부에서 일일이 분기 처리해야 했다.

🧪 시도

// 예전 방식 - Job마다 스킬을 따로 정의하고 조건문으로 분기
if (player.Job == "전사")
    WarriorSkill.UseSkill(index, player, monster);
else if (player.Job == "마법사")
    MageSkill.UseSkill(index, player, monster);

🛠 해결 방법

  • SkillSet 인터페이스를 만들고, 각 직업 스킬 클래스에 상속시켰다.
  • 이제 직업에 따라 스킬 클래스만 다르게 생성하면, 호출부는 공통된 방식으로 처리 가능하다.

✅ 개선된 코드

// 인터페이스 기반 구조
public interface SkillSet
{
    List<string> SkillNames { get; }
    void UseSkill(int index, Player player, List<Monster> monsters, Monster mainTarget);
}

// 전사 스킬 예시
public class WarriorSkill : SkillSet
{
    public List<string> SkillNames => new() { "강타", "회전베기", "분쇄", "더블스트라이크" };

    public void UseSkill(int index, Player player, List<Monster> monsters, Monster mainTarget)
    {
        // 스킬 사용 로직 통합
    }
}

// 호출 시
SkillSet skillSet = new WarriorSkill(); // 직업에 따라 바꿔주기만 하면 됨
skillSet.UseSkill(index, player, monsters, target);

💡 새롭게 알게 된 점

  • 인터페이스를 활용하면 다형성을 통해 중복을 없애고 구조를 단순화할 수 있다.
  • 앞으로는 Job 자체를 코드로 관리하지 않고 스킬/능력치 중심으로 설계하는 게 유지보수에 더 좋다.

② 문제정의: 퀘스트 클래스를 하나로 처리했더니 역할이 꼬이고 유지보수가 힘들었다

🧩 문제 상황

  • 퀘스트 진행, UI 출력, 퀘스트 상태 갱신 등을 전부 Quest.cs 하나에서 처리하고 있었음.
  • 클래스가 너무 커져서 어떤 코드가 어떤 역할을 하는지 찾기 어렵고, 테스트하기도 힘들었음.

🧪 시도

// 문제였던 코드
public class Quest
{
    public string Title;
    public string Info;
    public int TargetCount;
    public int CurrentCount;
    public bool IsAccepted;
    public bool IsCompleted;

    public void DisplayQuestUI() { ... } // UI 코드
    public void UpdateQuestProgress(string monsterName) { ... } // 로직 코드
}

🛠 해결 방법

  • 역할을 나누어 클래스를 3개로 분리
    1. Quest.cs: 퀘스트 데이터만 담당 (제목, 설명, 진행률 등)
    2. QuestManager.cs: 진행, 완료 체크 등의 로직만 담당
    3. QuestUI.cs: 퀘스트 출력 전용 클래스

✅ 개선된 구조

// Quest.cs - 데이터만 담당
public class Quest
{
    public string Title;
    public string Info;
    public int TargetCount;
    public int CurrentCount;
    public bool IsAccepted;
    public bool IsCompleted;
}

// QuestManager.cs
public static class QuestManager
{
    public static void CheckKill(string monsterName, Player player)
    {
        foreach (var quest in player.Quests)
        {
            if (quest.IsAccepted && !quest.IsCompleted && quest.Title.Contains(monsterName))
            {
                quest.CurrentCount++;
                if (quest.CurrentCount >= quest.TargetCount)
                    quest.IsCompleted = true;
            }
        }
    }
}

// QuestUI.cs - 출력 전용
public static class QuestUI
{
    public static void DisplayQuestList(List<Quest> quests)
    {
        foreach (var quest in quests)
        {
            Console.WriteLine($"🧾 {quest.Title} - {quest.CurrentCount}/{quest.TargetCount}");
        }
    }
}

💡 새롭게 알게 된 점

  • 클래스를 기능별로 나누면, 역할이 명확해지고 코드를 찾기도 쉽고 디버깅도 수월하다.
  • *단일 책임 원칙(SRP)**의 중요성을 몸으로 체감했다.

📝 메모

  • 점점 코드가 커질수록 책임 분리와 구조화가 중요하다는 걸 실감했다.
  • 내가 만든 구조를 다시 뜯어보면서 "내가 이걸 왜 이렇게 했지?" 싶은 게 많았는데,
  • 하나씩 이유를 찾고 개선해 나가면서 기분이 좋았다!
  • 발표를 준비하면서 나도 몰랐던 내 코드의 장점을 알게 되어 더 자신감이 생겼다!

이제 예비군도 끝나서그런지 오늘 팀프로젝트 하는데 너무 즐거웠다ㅠㅜ.. 공부가 이렇게 재밌었지.. 항상 새롭게 느껴지고.. 오류 생길때는 살짝 답답할때도 있지만 하루하루 즐기면서 개발 잘 해보자ㅏ 오예ㅖ!~!!


반응형
반응형

🗓️ 2025년 7월 16일 (수) – 오늘의 일정

✅ 오전 & 오후

  • 09:00 ~ 18:00 : 예비군 훈련

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁 식사

🧘 개인시간

  • 19:00 ~ 20:00 : 개인 휴식

🛠️ 팀 프로젝트 개발

  • 20:00 ~ 00:00 : 텍스트 RPG 직업 설계 및 스킬 개발
    • 직업 능력치 정리 및 보정 적용
    • 전사, 마법사, 도적, 궁수, 해적 클래스 정리
    • 각 직업별 스킬 3종 설계 및 코드 구현

✅ 오늘 학습 키워드

  • 직업 클래스 설계 리팩터링
  • 능력치 자동 계산 구조 (계산 프로퍼티 활용)
  • 직업별 특성 기반 능력치 보정
  • 직업별 스킬 구조 설계 및 구현
  • 추상 메서드 오버라이드 구조

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

오늘은 텍스트 RPG 프로젝트에서 직업 시스템과 전투 스킬 구조를 본격적으로 설계하고 구현했다.

먼저 Job 클래스에 각 능력치를 계산 프로퍼티(get) 로 리팩터링하여,

장비나 추가 능력치가 변하면 자동으로 최종 능력치에 반영되도록 구조를 개선했다.

그 후 각 직업(전사, 마법사, 도적, 궁수, 해적)의 고유 특성을 기준으로

공격력, 체력, 마나, 민첩, 회피율 등 보정 규칙을 다르게 적용하여 밸런스를 맞췄다.

마지막으로 각 직업마다 3개의 고유 스킬을 SkillNames와 UseSkill() 메서드로 구현했다.

스킬마다 치명타, 연속 공격, 상태 이상, MP 소비, 조건부 보정 등 개성이 잘 반영되도록 설계했.


🧩 학습하며 겪었던 문제점 & 에러

1. 문제정의

전사의 MaxMp가 설정한 값(40)보다 Job 기본값(50)이 우선 적용되는 문제 발생

  • 시도: 기본 구조에서 MaxMp => 50 + ExtraMp로 고정되어 있었음
  • 해결 방법: 각 직업 클래스에서 MaxHp, MaxMp, Agility 등을 override하여 명확히 기본값 반영
  • 새롭게 알게 된 점: 계산 프로퍼티 방식에서도 기본값이 우선 적용되므로, 반드시 각 클래스에서 오버라이드가 필요함
  • 다시 만나게 된다면: 능력치 기준값이 기본 구조보다 낮은 경우엔 항상 오버라이드를 체크할 것

📝 메모

오늘 구조를 정비하면서 느꼈다. 처음엔 간단해 보였던 클래스 구조도 실제 구현에 들어가면 훨씬 세밀하게 설계해야 한다는 걸 배웠다. 스킬을 따로 분리하지 않고 직업 내부에서 관리한 방식이 지금 구조엔 가장 자연스럽고 깔끔했던 선택이었다. 많은 스킬을 만든다면 따로 만드는게 맞지만 굳이..

하여간 오늘도 이렇게 끝났다 예비군 훈련이 하루 남았다!! 개발을 더 많이 해야하는데..팀원들한테 너무 미안하다 ㅠㅜㅜ 금요일날 아주..밤새서 개발을 해보겠어..각오해…

 

 

직업별 능력치 밸런스 기획

📊 직업별 능력치 및 특성 보정 요약표

직업 공격력 방어력 민첩 MaxHP MaxMP 치명타 확률 치명타 배수 회피 계산 방식 능력치 보정

전사 8 9 4 140 40 10% 1.5배 민첩 × 1.0 ExtraHp × 1.5배, ExtraAttack × 1.2배
마법사 10 3 5 90 120 15% 1.8배 민첩 × 1.0 ExtraMp × 1.5배, ExtraAttack × 1.2배
도적 9 4 10 95 70 18% 1.6배 (민첩 + 보정) × 1.5배 민첩 회피 특화 (DodgeChance 직접 계산)
궁수 8 5 9 100 60 30% 2.0배 민첩 × 1.0 치명타 확률, 배수 특화
해적 8 6 6 120 60 10% 1.7배 (민첩 × 1.2) × 1.0 ExtraHp / Mp / Agility × 1.2배

🧠 직업 특성 설계 요약

직업 설계 의도 및 특성 설명

전사 체력과 방어를 기반으로 안정적인 탱커 역할 수행. 장비에 의한 HP 보정 효과가 커서 후반 생존력 뛰어남. 공격력 보정도 일부 적용해 균형 잡힘.
마법사 마나 기반의 폭딜러. 마법 데미지 스킬 활용 전제이며 MP가 장비로 많이 늘어날수록 강해짐. 체력은 낮지만 한 방이 강한 캐릭터.
도적 회피 특화 캐릭터. 민첩 수치가 회피율에 크게 반영되며, 기동성과 회피를 활용한 지속적 타격 스타일. 치명타 수치는 궁수보다 낮음.
궁수 치명타 확률과 배율이 가장 높은 캐릭터. 민첩 회피 보정은 없지만 확률 기반 한 방이 강력함. 정확성과 폭딜 중심 설계.
해적 전천후 밸런스형 캐릭터. HP, MP, 민첩 모두 고르게 보정돼 유연한 대응 가능. 극단적 강점은 없지만 안정적인 성능을 가짐.
반응형
반응형

🗓️ 오늘 하루 일정 (2025년 7월 15일)

✅ 오전 ~ 오후

  • 09:00 ~ 18:00 : 예비군 훈련
    • 훈련소 출석 및 전반 일정 소화

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁식사 및 휴식

💻 개인 작업 시간

  • 19:00 ~ 23:00 : 텍스트 RPG 프로젝트 작업
    • Quest 시스템 UI 기획 및 전체 구조 수정
    • QuestUI.cs에서 퀘스트 목록 → 상세 보기 흐름 구현
    • Console ASCII UI 3D 형태 조정 (QUEST 박스 완성)
    • 콘솔 폭 맞춤 문제로 인한 출력 깨짐 디버깅
    • 최종적으로 깔끔한 Console.WriteLine 출력으로 리셋 및 구조 정비

✅ 오늘 학습 키워드

  • Console.WriteLine() UI 구성
  • ASCII 아트 박스 디자인 (QUEST)
  • 퀘스트 목록 출력 및 선택 흐름
  • List<Quest> 처리와 인덱스 기반 선택
  • Console.Clear(), Console.ReadKey() 흐름 제어

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

오늘은 텍스트 RPG의 퀘스트 시스템을 좀 더 다듬고 시각적으로 보기 좋게 만들기 위해 콘솔 출력 형식을 고도화했다.

초반에는 Quest 정보를 박스 형태로 이쁘게 표현하려고 시도했지만, 이모지나 한글 등으로 인해 콘솔 출력 폭이 들쑥날쑥해져서 UI가 깨지는 문제를 마주했다.

결국 여러 방식들을 테스트하다가, 가장 안정적인 방식인 Console.WriteLine() 중심의 깔끔한 구조로 다시 돌아오기로 결정했다.

그리고 퀘스트를 1. 제목 형태로 보여주고, 번호를 선택하면 상세 정보를 출력해주는 흐름도 구현해서 사용자 인터랙션 흐름도 잡을 수 있었다.

마지막엔 QUEST라는 텍스트를 입체감 있게 ASCII 아트로 표현하는 것도 마무리해서 전체적으로 UI 완성도를 높이는 날이었다.


🧩 학습하며 겪었던 문제점 & 에러

…생략 오늘은 봐주세여..예비군 갔다가 11시까지 개발 했어여ㅠ


📝 메모

오늘은 내가 아무리 체력이 좋아도 너무 피곤했다ㅎㅎㅠㅠ..

그래도 끝까지 마무리하고 나니 기분이 후련하다.

무엇보다 도중에 ‘그냥 대충 마무리할까’ 하는 유혹을 이기고,

최소한 내가 원한 수준까지는 도달하고 잠자리에 드는 이 결심이 제일 뿌듯하다.

내일..또 예비군 훈련이 있지만 그래도 개발은 재밌다.. 예비군 훈련할때

오늘 집가서 뭐 개발하지..생각밖에 없다… 예비군 빨리 끝내고 팀원들이랑 프로젝트 진행해야지.. 예비군 때문에 팀프로젝트를 소홀히 할 수 없다. 어떻게든 더 만들고 끝내야지 하루하루.. 남은 기간 화이팅ㅠㅜ


반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전 & 오후

  • 09:00 ~ 18:00 : 예비군 훈련

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁식사

✅ 저녁

  • 19:00 ~ 20:00 : 팀 프로젝트 회의
  • 20:00 ~ 20:30 : 팀원들과 프로젝트 계획 조율
  • 20:30 ~ 21:00 : 개인 TIL 작성

✅ 심야 작업

  • 21:00 ~ 00:00 : 게임 저장 시스템 구조 설계 및 디버깅
    • GameSaveData 클래스: 저장할 캐릭터 정보, 인벤토리, 완료 퀘스트 등 데이터 모델 정의
    • SaveManager 클래스: JSON 저장/불러오기 기능 및 자동 경로 생성 처리
    • 실행 경로 기준 상대 경로 저장 위치 확인 (bin/Debug/net8.0/...) 및 경로 재설정
    • Unicode 이스케이프(예: \\uC7AC\\uC740) 현상 확인 및 보기 편한 저장 방식 옵션 추가
    • 직렬화가 잘 되지 않던 문제를 { get; set; } 자동 속성으로 수정
    • 클래스 구조의 역할 분리와 폴더 정리까지 완료

✅ 오늘 학습 키워드

  • C# JSON 저장 시스템
  • System.Text.Json 직렬화
  • 상대 경로 vs 실행 경로
  • 디렉토리 자동 생성
  • Unicode 이스케이프
  • { get; set; } 자동 속성
  • 저장용 클래스 구조 설계 (GameSaveData, SaveManager)

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

오늘은 예비군 훈련을 마친 후, 밤 시간대를 활용해 게임 저장 시스템의 핵심 구조를 설계하고 구현했다.

먼저 GameSaveData 클래스를 통해 저장할 데이터를 설계했는데, 캐릭터 이름, 직업, 레벨, 경험치, 골드, HP/MP, 인벤토리, 완료한 퀘스트 등 저장이 필요한 항목들을 데이터 중심으로 구성했다.

그리고 SaveManager 클래스를 만들어 JSON 저장/불러오기 기능을 구현했다.

처음에는 저장 파일이 보이지 않아 당황했지만, 상대 경로의 기준이 실행 파일 위치(bin/Debug/net8.0/)라는 것을 확인하고 AppContext.BaseDirectory를 이용해 경로를 조정했다.

또한 저장 시 생성할 디렉토리가 없으면 자동으로 만들어주는 기능도 함께 처리해 실제 실행 환경에서도 문제없이 저장될 수 있도록 했다.

한 가지 흥미로운 점은 JSON으로 저장된 한글이 \\uC7AC\\uC740처럼 유니코드 이스케이프 형태로 저장된 것이었는데, 이는 System.Text.Json의 기본 동작이라는 것을 알게 되었고, 보기 편한 저장을 위해 UnsafeRelaxedJsonEscaping 옵션을 적용하는 방법도 함께 학습했다.

무엇보다 이번 작업에서는 단순히 기능만 구현한 것이 아니라, 저장 시스템의 클래스 구조를 깔끔하게 나누고 폴더별로 역할을 분리했다는 점에서 의미가 있었다.

이렇게 구조화해두면 앞으로 저장 슬롯, 자동 저장, 캐릭터 복원 같은 기능을 추가할 때 매우 편리하게 확장할 수 있다.

 

추가 클래스 구조

Challenge_JaeEun

├── Character_Folder

│   └── NewCharacter.cs

├── Job_Folder

│   ├── Job.cs (추상 클래스)

│   ├── Warrior.cs

│   ├── Archer.cs

│   ├── Mage.cs

│   └── Skill _Folder

│       └── JobSkill.cs

├── Quest_Folder

│   ├── Quest.cs

│   └── QuestManager.cs

├── SaveSystem _Folder

│   ├── GameSaveData.cs

│   └── SaveManager.cs


🧩 학습하며 겪었던 문제점 & 에러

1. 문제정의

NewCharacter 클래스에서 Job 타입을 사용하려고 했는데, 타입 인식을 못 하는 오류 발생

  • 시도
  • using 문과 네임스페이스를 점검했지만 문제는 해결되지 않았고, Job 클래스가 abstract라서 생긴 문제인지 의심도 해봄
  • 해결 방법Visual Studio가 폴더명을 타입으로 인식하면서 충돌이 발생했던 것
  • → 폴더명을 Job_Folder로 바꾸고 다시 네임스페이스를 정리하자 오류 해결됨
  • 폴더 이름과 클래스 이름이 모두 Job으로 동일했던 것이 문제였음.
  • 새롭게 알게 된 점
  • 폴더 이름과 클래스 이름이 같으면 네임스페이스 해석에서 충돌이 발생할 수 있다는 것을 처음 체감
  • 다시 만나게 된다면
  • 폴더 이름은 항상 클래스 이름과 다르게 명확하게 정리하고, 충돌이 의심되면 namespace, using을 전부 다시 확인하자

🔴 문제 상황 (오류 발생 코드)

// NewCharacter.cs
using TextRPG.Challenge_JaeEun.Character.Job;

namespace TextRPG.Challenge_JaeEun.Character
{
    public class NewCharacter
    {
        public string Name;
        public Job CharacterJob;  // ⚠ 오류: Job 클래스를 찾지 못함
    }
}
// Job.cs
namespace TextRPG.Challenge_JaeEun.Character.Job
{
    public abstract class Job
    {
        public string JobName;
    }
}

문제 원인: Job이라는 클래스 이름과 Job이라는 폴더 이름이 동일하여,

Visual Studio가 네임스페이스와 타입을 혼동함 → Job 타입을 인식하지 못함

✅ 해결 방법 (폴더명을 Job_Folder로 변경)

// NewCharacter.cs
using TextRPG.Challenge_JaeEun.Character.Job_Folder;

namespace TextRPG.Challenge_JaeEun.Character
{
    public class NewCharacter
    {
        public string Name;
        public Job CharacterJob;  // ✅ 오류 사라짐
    }
}
// Job.cs
namespace TextRPG.Challenge_JaeEun.Character.Job_Folder
{
    public abstract class Job
    {
        public string JobName;
    }
}

2. 문제정의

SaveToJson()을 호출했는데 저장된 파일이 프로젝트 폴더에 보이지 않음

  • 시도
  • 경로 설정은 "Challenge_JaeEun/JSON_Data"로 했고, 파일 생성도 성공 메시지가 출력되어 있음
  • 해결 방법→ AppContext.BaseDirectory를 사용해 원하는 위치로 경로 재지정하고 해결
  • 확인 결과, 저장은 잘 되었지만 **상대 경로 기준이 실행 위치(bin/Debug/net8.0/)**였다는 사실을 몰랐던 것
  • 새롭게 알게 된 점또한, Directory.CreateDirectory()를 활용하면 없는 폴더도 자동 생성되므로 에러 없이 저장이 가능하다는 것도 배움
  • 상대 경로는 소스코드 위치가 아니라 실행 파일 위치 기준으로 동작한다는 점
  • 다시 만나게 된다면
  • 경로 문제를 만났을 땐 반드시 File.Exists(), Directory.Exists()로 경로 실존 여부를 확인하고, 실행 기준 경로를 먼저 파악하자

🔴 문제 상황 (파일은 저장되지만 안 보임)

private static readonly string SaveDirectory = "Challenge_JaeEun/JSON_Data";
private static readonly string SavePath = Path.Combine(SaveDirectory, "save.json");

File.WriteAllText(SavePath, json);

문제 원인: 상대 경로 기준은 **실행 파일 위치 (bin/Debug/net8.0/)**라서,

프로젝트 폴더에는 파일이 보이지 않음


✅ 해결 방법 (경로를 프로젝트 루트로 변경)

// 실행 기준에서 프로젝트 폴더로 올라간 다음 경로 설정
private static readonly string SaveDirectory = Path.Combine(AppContext.BaseDirectory, @"..\\..\\..\\Challenge_JaeEun\\JSON_Data");
private static readonly string SavePath = Path.Combine(SaveDirectory, "save.json");

Directory.CreateDirectory(SaveDirectory);
File.WriteAllText(SavePath, json);

이렇게 하면 실제 프로젝트 폴더 내부에 JSON이 저장됨, 그리고

경로 오류도 사라짐!


📝 메모

오늘은 정신적으로도, 체력적으로도 정말 밀도 있는 하루였다.

하루 종일 예비군 훈련을 받고 나니 진이 빠졌지만,

밤에는 오히려 더 집중이 잘 돼서 저장 시스템 설계를 깊이 있게 고민할 수 있었다.

사소한 문제라고 생각했던 Job 네임스페이스 오류나,

파일이 저장되지 않는다고 착각했던 경로 이슈처럼

사실 알고 보면 "몰랐던 게 아니라 오해했던 것들"이 많았다.

하지만 그런 문제를 직접 하나하나 풀어내면서,

구조를 쌓고, 클래스를 나누고, 저장 흐름을 통제하는 이 과정이 너무 재밌었다.

오늘은 기능뿐 아니라 클래스를 명확하게 나누고 폴더 구조도 정리한 날이었다.

이렇게 하나씩 쌓아올리다 보면 정말 좋은 프로젝트가 될 거라는 기대가 생긴다.

오늘도 잘했고, 내일도 잘할 수 있다!!! 💪 예비군 2일차 화이팅 ㅠㅜ.. 코딩이 더 재밌다..차라리 공부를ㅠㅜ..


반응형
반응형

📘 300. Longest Increasing Subsequence

🔹 문제 설명

정수 배열 nums가 주어질 때,

배열에서 오름차순으로 증가하는 가장 긴 부분 수열의 길이를 구하라.

  • 부분 수열(subsequence):(연속된 값일 필요는 없음)
  • 원래 배열에서 순서를 유지하면서 일부 원소를 건너뛰어 선택할 수 있음

🔸 예시

Input: nums = [10, 9, 2, 5, 3, 7, 101, 18]
Output: 4

설명: 가장 긴 오름차순 부분 수열은 [2, 3, 7, 101] 이므로 길이는 

🔹 조건

  • 1 <= nums.length <= 2500
  • 10⁴ <= nums[i] <= 10⁴

🎯 목표

👉 배열에서 가장 길게 오름차순으로 증가하는 부분 수열을 찾아서

길이를 반환하는 함수를 작성하는 것이 목표야.


✅ 예시 2

Input: nums = [0, 1, 0, 3, 2, 3]
Output: 4
설명: [0, 1, 2, 3] 이 가장 길다

🧠 핵심 개념

이 문제는 전형적인 동적 계획법 (DP) 또는 이진 탐색을 이용한 최적화 문제야.

  • 기본 DP 풀이: O(n²)
  • 이진 탐색 최적화: O(n log n)
using System;

public class Program
{
    public static void Main()
    {
        int[] nums = new int[] { 10, 9, 2, 5, 3, 7, 101, 18 };

        Console.WriteLine("Input Array: " + string.Join(", ", nums));

        int result = FindLengthOfLIS(nums);

        Console.WriteLine("Longest Increasing Subsequence Length: " + result);
    }

    public static int FindLengthOfLIS(int[] nums)
    {
        int n = nums.Length;
        if (n == 0) return 0;

        int[] dp = new int[n];
        for (int i = 0; i < n; i++)
            dp[i] = 1;  // 최소 자기 자신

        for (int i = 1; i < n; i++)
        {
            for (int j = 0; j < i; j++)
            {
                if (nums[j] < nums[i])
                {
                    dp[i] = Math.Max(dp[i], dp[j] + 1);
                }
            }
        }

        int maxLength = 0;
        for (int i = 0; i < n; i++)
            maxLength = Math.Max(maxLength, dp[i]);

        return maxLength;
    }
}
반응형