나 개발자 진짜 되냐?

C#으로 텍스트 RPG 만들기 _ [ 업그레이드 버전 ] 본문

C# 을 맛보았어요!/프로젝트를 만들었어요!

C#으로 텍스트 RPG 만들기 _ [ 업그레이드 버전 ]

Snow Rabbit 2024. 9. 27. 23:20

핼로우

 

오늘은 저번 RPG에서 조금 아쉬웠던 부분들을

업그레이드하는 시간을 가져보자.

 


 

우리는 전 시간에

배열을 하나하나 만들어줘서

이어주었다.

 

하지만 데이터가 이러면 조금 많고 복잡하고

약간의 오류로

뭐 다른 쪽 데이터를 가져올 수 도 있는 불상사가 생기기 때문에

그래서 클래스로 만들게 되면

관련되어 있는 친구들끼리

묶어서 사용할 수 있다.

 

이 하나하나

하나의 객체가 되는 것이다.

이렇게 만들면

객체 하나만 뽑으면 되어서

 

값이 틀려질 일도 없고

코드도 더 간결해질 것이다.

 


자,

 하나씩 만들어 보자

 

우리는 클래스를 이용해 줄 것이다.

 

 

클래스 생성은

프로젝트 > 클래스추가 해주면 된다!

깨끗한 친구가 생성됐다.

 

이제 우리는

 

여기에 캐릭터 정보를 넣어줄 것이다.

 

 

아이템장착인데.. 왜 캐릭터에 있지?

 

 

캐릭터가 입고 벗을 옷이라고 생각해서

 

캐릭터에 넣어줬다.

 

static도 빼줘도 된다.

왜냐면 이 친구들은 클래스가 바뀌었기 때문!

 

여기서 중요한 것!

 

우리는 그래도 장비가 아이템이기 때문에

List <int>에

int 대신 item을 넣어준다.

 

나는 사실

 

List 꺽새에 왜 <> item을 넣는 게 이해가 안 갔는데.

 

그냥 아이템 클래스에 있는

저런 다양한 친구들을 쓰려면 넣어줘야 된다고 한다.

 

꺾새 안에다가

나 자료형쓸건데..

그건 내가 방금 만든 class item이야!라는 뜻이 된다.

 

 

 

야무지게 그림을 그려보았다.

 

그림으로 이해해야 빠르지. 암암

 

클래스를 통해서 우리는 틀을 만들고

그렇게 객체를 찍어 낸다.

 

그 객체 하나하나를 리스트에 넣어서

리스트 1번은 객체 1,

리스트 2번은 객체 2

이 방식인 거다

 

 

여하튼! List < item >을 통해

그래서 item클래스에 있는 정보들을 쓸 수 있도록 한다.

 

item클래스를 만들어보자

 

 

 

아이템 클래스도 만들어 주었다

 

전에는 우리가 배열로

일일이 값을 넣어줬었다.

 

이렇게

 

하지만 우리는 이제 클래스를 만들었기 때문에

이 클래스 안에 이렇게 많은 배열을 안 넣어줘도 된다!

 

 

간결하게 넣어주면 된다.

 

static도 빼줘도 된다.

왜냐면 이 친구들은 클래스가 바뀌었기 때문!

 

 

자 이제 이 변수들을 밖에서 사용하기 위해

privatepublic로 바꿔준다.

 

그다음에 보면

다 외부로 유입이 되니까

 

기본값이 틀어지거나

값을 누가 수정하거나 등

이상한 문제가 생길 수도 있다.

 

그런 걸 방지하는 친구

🌟 property 🌟

라는 친구를 사용해 줄 것이다.

 

형태는 중괄호 열고 get; set;을 적어주면 된다.

{ get; set; }

get은 이 변수의 반환값을 재정의,

set은 변수에 조건을 걸어주는 것이다.

 

get은 가져다 써라

set은 가져다 수정해라

 

근데 우리는 수정은 안되고 가져다 쓰는 거만 되니깐

get만 써주면 된다.

 

지금은 클래스에 있는 친구들은

틀만 짜놨다.

그래서 이 글자들을 입력받을 수 있도록 해주는 친구가

 

이것이 바로 생성자라는 함수이다.

 

이 함수의 특징은

클래스와 이름이 같다.

 

player이 생성될 때, 입력한 level값이

클래스에 있던 Level에 적용이 된다.

 

이렇게 써주면

이 인자가 들어왔을 때

이 값을 다 클래스에 넣어서

틀 하나 찍어주겠다!

로 생각해 주면 된다.

 

이것이!

클래스를 만드는 기본구조이다.

 

데이터

+

 

데이터를 받는 생성자

 

 

 

자, 다음

리스트를 잠깐 보면

값을 변경해 주면 안 되니까 private로 변경해 준다.

 

하지만 리스트에서 인벤토리 같은 경우

인벤토리 안에 몇 개가 있는지, 개수가 필요로 할 때가 있다.

그래서 그 값을 받을 변수 하나 만들어준다.

 

public int InventoryCount { get }

 

get; 이면

받은 값 그대로 리턴

 

그러지 않으려면 

get한테 선언해줘야 한다

get { return = 0 }

이렇게!

 

우리는 이 함수를 만든 이유가

인벤토리의 크기만큼 반환해 주는 것이기 때문에

 

return Inventory.Count;를 반환해주어야 한다.

 

 

자, 그다음에 또 유저 클래스에 뭘 넣어야 하나..

유저랑 뭐가 관련이 있을까 하고 봤더니

 

1. 상태정보창 

2. 인벤토리

3. 인벤토리 in 아이템 장착

4. 아이템 구매 ( 그래야 인벤토리로 넘어감 )

 

 

이렇게 준비해 준다

 

 

보면 아이템이름이 붙은 친구는 

아이템에서 값을 가져와야지만 뭐

장착하는지 뭐 샀는지 알 수 있어서

인자 값을

넣어준다.

palyer에는 이렇게 값을 넣어주고

 

다음

인벤토리가 중요하다

 

 

인벤토리에는 우선,

 

보면 Item targetItem Inventory [i]라고 되어있다.

 

여기서 Item이라고 쓰면서

Item에 있는 모든 정보를 포함하고 있는 애는 targetItem이라고 된다.

 

이렇게 해주면

targetItem친구를 통해

Item에 있던 친구들을 쓸 수 있다.

 

 

아이템클래스

또한

아이템을 출력해 주는 함수를 만들자!

 

아이템의 정보를 표시하는 부분이 많이 나오기 때문에

함수로 만들어준다.

 

이름은

public string ItemInfoText() 


단, 상점에서는 가격표시가 필요하고,

인벤토리에선 E가 표시되어야 한다.


그래서 먼저 공통적인 부분만 표시해 준다.

 

요렇게 해주면!

공통적인 부분이 된다.

 

음..

잘 보면 Type 같은 경우

공격력방어력 값이 두 개로 나뉜다.

 

그래서 둘 중 하나 출력해 주어야 하니까

우리는 type == 0이면 무기라서 공격력

type == 1이면 갑옷이라 방어력

올라가게끔?

 

전 시간에 배웠던 삼항 연산자를 사용해 보자

 

Type == 0? " 공격력 " : " 방어력 "

 

흠 근데 이거 여러 번 썼던 게 기억나는가?

 

그렇다면 또 우리는 함수를 통해 하나로 만들어보자.

 

" 공격력 " 과 " 방어력 " 이

출력되어야 하니

문자열일 것이고!

 

이렇게 써주면 완성!

 

자 이제 다시 플레이어 클래스로 돌아와 보자

 

전에는 배열이었기 때문에..

 

 

이렇게 써주었지만..

 

이제는 클래스를 이용해 더 간단하게 구현이 가능하다.

 

 

이게 다라고요?!

 

정말 너무 간결해진 거 아닙니까!?!

 

정말 나도 잘 활용하고 싶다..ㅎㅎ

 

자,

이제 장착을 보자!

 

 

전에 가져올 식을 먼저 그대로 가져와보자

 

214번째 줄부터 216번째 줄

bool값으로 받아와서 if문에 넣어주었다.

 

그 bool이 참이 되는 조건은

equipList에 targetItem이 Contains 포함되어 있는가

 

targetItem변수는 지금은 잘려서 안 보이지만

저번 식에서는 누르는 번호 -1 이 되어있었다.

 

contains는 포함되어 있으면 참까지 내주는 친절한 친구기에

 

if문에 잘 들어갔다.

 

우리는 이것을 미리 불값으로 함수 만들어 두었다.

 

그러면 더 간단하게 줄여진다.

 

< AFTER >

이렇게!

 

이미 저 함수가 bool값이니 자연스레

if문에 그대로 넣어도 문제없고,

 

item을 매개변수로 넣어주는 게 정말 중요하다!

 

위에 함수에서 

 

public void EquipItem(Item item)

이 자리에는 원래

( 자료형 매개변수 )가 들어가야 한다.

 

즉,

Item은 자료형으로 해석해서

 

Item이라는 자료형을 쓸 거고 나는 그것을

함수 내에서! item이라고 부를 거야!

라는 뜻이 된다.

 

그래서 코드를 보면,

들어가는 변숫값, 그리고

 

원래

클래스. 속성 하나

였다면

우리는 그 친구를 매개변수 item으로 부르기로 했으니

item.Value가 될 수 있다.

 

< BEFORE >

 

전과 비교했을 때 많이 간소화된 것을 확인할 수 있다.

 

흠 여기까지 잘 왔다면

나에게 궁금한 것이 생겨야 정상

 

❗❗빨간 줄 빨간 줄❗❗

 

ExtraAd와 ExtraDef에서 빨간 줄이에요..

 

그 이유는

 

위에 올라가 보면

 

public으로 선언해 주었지만

우리는 set을 설정해주지 않았다.

즉 밖에서 못 바꾸게 해 놨는데

왜 얘 내 허락도 없이 +-막 해줘?

 

이렇게 된 경우이다.

 

그렇기 때문에

아 나 고칠 거야

하는 set을 써줘야 한다.

ㅇㅅㅇ

 

자 사실 이렇게 해주면

밖에서 고치는 것을 허락해 주었기 때문에

문제가 생길 수 있어 처리를 해줘야 한다.

 

바로 set 앞에

private를 붙여서

 

set를 플레이어 클래스 안에서만! 작동할 수 있게

그 이외는 안된다!라는 뜻이 된다.

 

 

자 다음

IsEqipItem 함수를 보자

 

지금은 false로 고정해 놨지만.

ture 일 때 false로

false일 때 true 가 되도록 해줘야 한다.

 

그래서 값을 바꿔주어야 하는데

 

어떻게?

 

장착 리스트에 매개변수로 입력받았던 그 값이 포함된다면!

 

이렇게 해주니 

밑에 HasItem도 bool값이라

똑같이 해주면 된다.

대신 얘는 가지고 있는 거니까

인벤토리겠지요!

 

 

남은 건 상점 구매 함수이다.

 

우리는 전 시간에도 상점 구매 함수를 야무지게 적어두었다.

 

한번 가져와보자

 

찾았는가?

 

그렇다면.. 천재

 

난 사실 못 찾았다.

 

왜냐면 이 함수에는

물건 구매! 기 때문에

구매하고 가격이 차감되는 함수를 적는 곳이었다..ㅋㅋㅋ

 

for문이녜 뭐 다 가져왔는데..ㅋㅋ 스읍

 

일단 여기서

구매는 돈을 주고 구매하는 곳이니

 

두줄이다.

복사해 와서 붙여놔 보자

 

변수 글자를 수정하다가 생긴 빨간 오류는?

뭐다?

 

 

set을 넣어줘라

private 잊지 말고!!

 

자 이제 클래스 두 개 만들었으니

 

이 클래스를 가지고 Start 클래스를 만들어보자!

 

깨끗한 start클래스를 만들고!

 

여기에는 우리가 아까 열심히 작성했던

클래스를 가져와야 한다.

정확히 고급용어로 말하면

객체 선언

Player이라는 타입을 가진 player

Item배열인 ItemDb;

 

자 우리는 아까 말 그대로 선언만 해주었다.

 

우리는 이 친구를 제대로 만들어준 게 아니기 때문에

데이터를 만들어주는 친구

NEW를 사용해야 한다.

 

만약에 new를 통해서 만들지 않았다면

 

NULL Reference Exception

참조오류가 발생한다.

 

New는 새롭게 생성하는 거라

같은 거에는 한 번만 사용하는 게 원칙

왜냐면 같은 이름으로 계속 객체 만들면

복사가 아니라 덮어쓰기가 된답니다..^^

 

여하튼 이따가 제대로 한번 쓰도록 하고 우리는

Main을 적어보자

 

맨 처음에 Main에서는 해야 할 것 이

1. 초기 스탯 설정

2. 초기 화면 띄우기

 

이다.

 

그래서 두 함수를 적는다.

 

SetData에서

우리는 저번에 하나하나 스탯을 적어주었다

뭐 레벨은 몇

뭐 이름은 뭐

 

하지만 이제는! 클래스를 만들어 주었기 때문에!

 

간단하게 생성자 덕으로

한 줄 코딩이 완성된다.

 

에메랄드 색 Player이 클래스인데

저기에 마우스를 가져다 대면

내가 뭘 써야 하는지 순서가 나온다.

그거에 맞게 써주면 된다!

 

이것이 객체 생성이라는 것이다!!

 

setData는 일단 초기설정이기 때문에

Item 배열도 해보자!

 

배열을 생성해 줄 때

배열 내 내용이나 자료형이 다르다면

 

대괄호에 배열 개수를 적는 것보단

중괄호를 넣어서 무슨 내용을 적을지 넣는 게 더 좋다.

 

자 내용을 넣을 때도 new를 사용해야 한다.

 

 

엇 왜죠? new 썼잖아요!

 

맞아요 쓰긴 했죠

하지만 우리는 배열[] 이 칸을 만들어준 거고

이 배열에 값을 넣어주어야 하기 때문에

그 값 하나하나에도 new를 써주어야 합니다!!

불태웠다...

 

이다음에

UI는 지난 시간에 꾸며줬기 때문에

UI들은 그대로 복사해서 붙여 넣고

 

빨간 줄이 생긴 부분만 고쳐주면 된다.

 

초기메인에는 빨간 줄 없고

 

stat출력 UI에서는 우리가

아까 stat출력 내용을 복사해서 

 

Player 클래스

DisplayPlayerInfo에

넣었으니까!

 

여기에는

Player 클래스로 만든 player에서

DisplayPlayerInfo를 찍어주면 된다.

 

그럼 빨간 줄 안녕!

 

다음 인벤토리 UI에서도

아이템 목록을 우리가 아까

Player 클래스에 빼주었다.

어디에?

 

DisplayPlayerInfo에

 

 

 

이렇게 되었다면 성공!

 

다음이 중요하다!

장착인데,

 

지금은 우리가 123456으로 객체를 만들었지만

여기서 템을 만약에 1번 4번 두 개만 사면

 

위치상

1 4 즉

두 번째 위치에 4가 들어가기 때문에

4번 객체를 뽑아주려면?

인벤토리에서 2번째를 찾아서 줘! 가 되어야 한다.

 

그래서 만들었던 친구

리스트 길이만큼 출력해라.

 

저번시간 열심히 정성 들인 그림을 가져오면

 

 

지금 상황은 1이랑 4 두 개가 들어갔으니

리스트는 두 칸 차지하고 있을 거고,

리스트 길이만큼 출력하면

객체 1 객체 4 이렇게 나올 것이다.

 

그래서 리스트상 2번 위치에 있는

객체 4가 가져오게 되는 것이다.

 

여하튼

 

 

이렇게 된다.

 

 

바로 밑으로 내려와서

default에 보면

 

player에 EquipItem을 가져오고 ( 장착 [E] )

엇 빨간 줄 뭘까?

 

매개변수가 없단다

그러면 우리는 이 괄호에 뭘 써줘야 할까?!

 

바로 item n번째가 들어가야 한다

그래야 검사해서 출력이 되잖소!

 

근데 이 아이템 번호는

입력받은 값에서 1 빼줘야 하고

왜? 배열이니까

 

그 값을 배열 인덱스에 넣어주기만 하면 된다.

그러면 배열 인덱스에 있는 번호가 들어가서

그 배열 값을 호출할 것이다.

 

 

혹시 이해가 갔는가?

 

제 코드를 보며 맞춰보세요

 

 

나는..

저 에메랄드 Item을 안 썼다 ㅋㅋㅋ

 

저 친구에게도 자료형이 필요하다는 사실을 잊었다.

 

무엇보다

ItemDb 또한 Item이기 때문에

자료형을 맞춘다는 생각을 가지고 앞에 Item을 써주는 게

바로바로 생각났으면 좋겠다.

 

그럼 빨간 줄 클리어!

 

다음으로 넘어가면..

shop 상점입니다.

 

흠..

 

먼저 첫 번째

우리는 itemNames가 아니라 

아까 만든 아이템 배열이 들어가야 한다

그래서 그 배열길이만큼 검사해야 한다.

 

다음으로

지금 아이템이 뭔지를

배열 Db에서 꺼내와 보자

 

 Item curItem itemDb [i];

클래스 Item

 (여기서는 자료형이겠지만..ㅎ )

 

itemDb에서 i번째 값을

변수 curItem에 넣어준다.

 

사실 이 식을 쓴 이유는 그냥

6번 돌겠다. 이 뜻이다.

 

자 다음 삼항연산자의 빨간 줄을 없애야 하는데

 

첫 번째에

inventory.Count(i)는

인벤토리의 길이를 나타냈다.

 

우리는 인벤토리의 길이를 표현하기 위해

아까

플레이어 클래스에서

HasItem 가지고 있는 함수를 만들었었다.

 

즉 내가 가지고 있는 아이템들을 넣는 함수였다.

 

그 친구를 사용할 거고

그 함수 매개변수로 방금 만든

itemDb [i]을 넣어주면 된다.

 

그리고

가격에는 

itemDb [i]에서 price값

을 넣어주면 된다.

 

그리고 밑에는

뭐 똑같이

itemDb [i]를 우리는 curItem으로 해주었기 때문에\

 

 

이렇게 되었다면

그대는 천재..

 

나는 따라오는데 오래 걸렸습니다.

 

여기서 

더 천재가 될 수 있는 것

 

우리는 아까 Item 클래스에다가

 

이 친구를 추가했었다.

 

굉장히 유사해 보이죠?

 

더 간단해졌다면..

 

완전 천재

 

 

이 글을 더 볼 필요가 있을까?

 

ㅋㅋㅎ

자 이제 BuyUI

 

for문 빨간 줄은

위에 아이템 상점과 같고

아!

 하나 다른 건

아이템이 몇 번인지 번호 출력이 있어야 하니까 

 

마지막 출력에

{ i+1 }을 해주면 된다.

 

 

밑에 내려와서

default를 보면

 

if (inventory.Contains(result - 1))

 

일단 여기 

inventory.Contains

아까 함수로 만들어준

player.HasItem으로 바꿔줄 거고

result - 1 은 더 이상 해줄 필요없다.

정보의 하나를 가져오는게 아니라

배열 자체를 가져와야하기때문에

 

result - 1 를 업그레이드 해줘야한다.

 

 

아까 장착때 해줬었다.

 

그렇다면 뭐 다했다.

 

 

골드도 바꾸고

인벤토리도

targetItem로 바꿔주면 끝!

 

그러면 문제가 생긴다.

아이템 장착 시,

DisplayInventoryInfo() 이라는 

player  클래스에서 만든 함수에서

 

값을 고정해놨기때문에 앞에 숫자가 안나오게 된다.

 

그러면 어떻게 해야할까?

 

음..만약에 참 ( 아이템 장착 창이면 )

숫자 보여주고

거짓  ( 아이템 보여주는 창이면 )

숫자 안보여주면 되지않을까??

 

바로 해보자

저 함수 파라미터로

bool값을 하나 받아준다.

 

DisplayInventoryInfo(bool showIdx)

 

그리고 밑에

 

string displayIdx = showIdx ? $"{ i+1 }  " : " " ;

 

Console.WriteLine($"- {displayIdx} {displayequip} {targetItem.ItemInfoText}");

 

 

핼로우

 

오늘은 저번 RPG에서 조금 아쉬웠던 부분들을

업그레이드하는 시간을 가져보자.

 


 

우리는 전 시간에

배열을 하나하나 만들어줘서

이어주었다.

 

하지만 데이터가 이러면 조금 많고 복잡하고

약간의 오류로

뭐 다른 쪽 데이터를 가져올 수 도 있는 불상사가 생기기 때문에

그래서 클래스로 만들게 되면

관련되어 있는 친구들끼리

묶어서 사용할 수 있다.

 

이 하나하나

하나의 객체가 되는 것이다.

이렇게 만들면

객체 하나만 뽑으면 되어서

 

값이 틀려질 일도 없고

코드도 더 간결해질 것이다.

 


자,

 하나씩 만들어 보자

 

우리는 클래스를 이용해 줄 것이다.

 

 

클래스 생성은

프로젝트 > 클래스추가 해주면 된다!

깨끗한 친구가 생성됐다.

 

이제 우리는

 

여기에 캐릭터 정보를 넣어줄 것이다.

 

 

아이템장착인데.. 왜 캐릭터에 있지?

 

 

캐릭터가 입고 벗을 옷이라고 생각해서

 

캐릭터에 넣어줬다.

 

static도 빼줘도 된다.

왜냐면 이 친구들은 클래스가 바뀌었기 때문!

 

여기서 중요한 것!

 

우리는 그래도 장비가 아이템이기 때문에

List <int>에

int 대신 item을 넣어준다.

 

나는 사실

 

List 꺽새에 왜 <> item을 넣는 게 이해가 안 갔는데.

 

그냥 아이템 클래스에 있는

저런 다양한 친구들을 쓰려면 넣어줘야 된다고 한다.

 

꺾새 안에다가

나 자료형쓸건데..

그건 내가 방금 만든 class item이야!라는 뜻이 된다.

 

 

 

야무지게 그림을 그려보았다.

 

그림으로 이해해야 빠르지. 암암

 

클래스를 통해서 우리는 틀을 만들고

그렇게 객체를 찍어 낸다.

 

그 객체 하나하나를 리스트에 넣어서

리스트 1번은 객체 1,

리스트 2번은 객체 2

이 방식인 거다

 

 

여하튼! List < item >을 통해

그래서 item클래스에 있는 정보들을 쓸 수 있도록 한다.

 

item클래스를 만들어보자

 

 

 

아이템 클래스도 만들어 주었다

 

전에는 우리가 배열로

일일이 값을 넣어줬었다.

 

이렇게

 

하지만 우리는 이제 클래스를 만들었기 때문에

이 클래스 안에 이렇게 많은 배열을 안 넣어줘도 된다!

 

 

간결하게 넣어주면 된다.

 

static도 빼줘도 된다.

왜냐면 이 친구들은 클래스가 바뀌었기 때문!

 

 

자 이제 이 변수들을 밖에서 사용하기 위해

private public로 바꿔준다.

 

그다음에 보면

다 외부로 유입이 되니까

 

기본값이 틀어지거나

값을 누가 수정하거나 등

이상한 문제가 생길 수도 있다.

 

그런 걸 방지하는 친구

🌟 property 🌟

라는 친구를 사용해 줄 것이다.

 

형태는 중괄호 열고 get; set;을 적어주면 된다.

{ get; set; }

get은 이 변수의 반환값을 재정의,

set은 변수에 조건을 걸어주는 것이다.

 

get은 가져다 써라

set은 가져다 수정해라

 

근데 우리는 수정은 안되고 가져다 쓰는 거만 되니깐

get만 써주면 된다.

 

지금은 클래스에 있는 친구들은

틀만 짜놨다.

그래서 이 글자들을 입력받을 수 있도록 해주는 친구가

 

이것이 바로 생성자라는 함수이다.

 

이 함수의 특징은

클래스와 이름이 같다.

 

player이 생성될 때, 입력한 level값이

클래스에 있던 Level에 적용이 된다.

 

이렇게 써주면

이 인자가 들어왔을 때

이 값을 다 클래스에 넣어서

틀 하나 찍어주겠다!

로 생각해 주면 된다.

 

이것이!

클래스를 만드는 기본구조이다.

 

데이터

+

 

데이터를 받는 생성자

 

 

 

자, 다음

리스트를 잠깐 보면

값을 변경해 주면 안 되니까 private로 변경해 준다.

 

하지만 리스트에서 인벤토리 같은 경우

인벤토리 안에 몇 개가 있는지, 개수가 필요로 할 때가 있다.

그래서 그 값을 받을 변수 하나 만들어준다.

 

public int InventoryCount { get }

 

get; 이면

받은 값 그대로 리턴

 

그러지 않으려면 

get한테 선언해줘야 한다

get { return = 0 }

이렇게!

 

우리는 이 함수를 만든 이유가

인벤토리의 크기만큼 반환해 주는 것이기 때문에

 

return Inventory.Count;를 반환해주어야 한다.

 

 

자, 그다음에 또 유저 클래스에 뭘 넣어야 하나..

유저랑 뭐가 관련이 있을까 하고 봤더니

 

1. 상태정보창 

2. 인벤토리

3. 인벤토리 in 아이템 장착

4. 아이템 구매 ( 그래야 인벤토리로 넘어감 )

 

 

이렇게 준비해 준다

 

 

보면 아이템이름이 붙은 친구는 

아이템에서 값을 가져와야지만 뭐

장착하는지 뭐 샀는지 알 수 있어서

인자 값을

넣어준다.

palyer에는 이렇게 값을 넣어주고

 

다음

인벤토리가 중요하다

 

 

인벤토리에는 우선,

 

보면 Item targetItem  Inventory [i]라고 되어있다.

 

여기서 Item이라고 쓰면서

Item에 있는 모든 정보를 포함하고 있는 애는 targetItem이라고 된다.

 

이렇게 해주면

targetItem친구를 통해

Item에 있던 친구들을 쓸 수 있다.

 

 

아이템클래스

또한

아이템을 출력해 주는 함수를 만들자!

 

아이템의 정보를 표시하는 부분이 많이 나오기 때문에

함수로 만들어준다.

 

이름은

public string ItemInfoText() 


단, 상점에서는 가격표시가 필요하고,

인벤토리에선 E가 표시되어야 한다.


그래서 먼저 공통적인 부분만 표시해 준다.

 

요렇게 해주면!

공통적인 부분이 된다.

 

음..

잘 보면 Type 같은 경우

공격력 방어력 값이 두 개로 나뉜다.

 

그래서 둘 중 하나 출력해 주어야 하니까

우리는 type == 0이면 무기라서 공격력

type == 1이면 갑옷이라 방어력

올라가게끔?

 

전 시간에 배웠던 삼항 연산자를 사용해 보자

 

Type == 0? " 공격력 " : " 방어력 "

 

흠 근데 이거 여러 번 썼던 게 기억나는가?

 

그렇다면 또 우리는 함수를 통해 하나로 만들어보자.

 

" 공격력 " 과 " 방어력 " 이

출력되어야 하니

문자열일 것이고!

 

이렇게 써주면 완성!

 

자 이제 다시 플레이어 클래스로 돌아와 보자

 

전에는 배열이었기 때문에..

 

 

이렇게 써주었지만..

 

이제는 클래스를 이용해 더 간단하게 구현이 가능하다.

 

 

이게 다라고요?!

 

정말 너무 간결해진 거 아닙니까!?!

 

정말 나도 잘 활용하고 싶다..ㅎㅎ

 

자,

이제 장착을 보자!

 

 

전에 가져올 식을 먼저 그대로 가져와보자

 

214번째 줄부터 216번째 줄

bool값으로 받아와서 if문에 넣어주었다.

 

그 bool이 참이 되는 조건은

equipList에 targetItem이 Contains 포함되어 있는가

 

targetItem변수는 지금은 잘려서 안 보이지만

저번 식에서는 누르는 번호 -1 이 되어있었다.

 

contains는 포함되어 있으면 참까지 내주는 친절한 친구기에

 

if문에 잘 들어갔다.

 

우리는 이것을 미리 불값으로 함수 만들어 두었다.

 

그러면 더 간단하게 줄여진다.

 

< AFTER >

이렇게!

 

이미 저 함수가 bool값이니 자연스레

if문에 그대로 넣어도 문제없고,

 

item을 매개변수로 넣어주는 게 정말 중요하다!

 

위에 함수에서 

 

public void EquipItem(Item item)

이 자리에는 원래

( 자료형 매개변수 )가 들어가야 한다.

 

즉,

Item은 자료형으로 해석해서

 

Item이라는 자료형을 쓸 거고 나는 그것을

 함수 내에서! item이라고 부를 거야!

라는 뜻이 된다.

 

그래서 코드를 보면,

들어가는 변숫값, 그리고

 

원래

클래스. 속성 하나

였다면

우리는 그 친구를 매개변수 item으로 부르기로 했으니

item.Value가 될 수 있다.

 

< BEFORE >

 

전과 비교했을 때 많이 간소화된 것을 확인할 수 있다.

 

흠 여기까지 잘 왔다면

나에게 궁금한 것이 생겨야 정상

 

❗❗빨간 줄 빨간 줄❗❗

 

ExtraAd와 ExtraDef에서 빨간 줄이에요..

 

그 이유는

 

위에 올라가 보면

 

public으로 선언해 주었지만

우리는 set을 설정해주지 않았다.

즉 밖에서 못 바꾸게 해 놨는데

왜 얘 내 허락도 없이 +-막 해줘?

 

이렇게 된 경우이다.

 

그렇기 때문에

아 나 고칠 거야

하는 set을 써줘야 한다.

ㅇㅅㅇ

 

자 사실 이렇게 해주면

밖에서 고치는 것을 허락해 주었기 때문에

문제가 생길 수 있어 처리를 해줘야 한다.

 

바로 set 앞에

private를 붙여서

 

set를 플레이어 클래스 안에서만! 작동할 수 있게

그 이외는 안된다!라는 뜻이 된다.

 

 

자 다음

IsEqipItem 함수를 보자

 

지금은 false로 고정해 놨지만.

ture 일 때 false로

false일 때 true 가 되도록 해줘야 한다.

 

그래서 값을 바꿔주어야 하는데

 

어떻게?

 

장착 리스트에 매개변수로 입력받았던 그 값이 포함된다면!

 

이렇게 해주니 

밑에 HasItem도 bool값이라

똑같이 해주면 된다.

대신 얘는 가지고 있는 거니까

인벤토리겠지요!

 

 

남은 건 상점 구매 함수이다.

 

우리는 전 시간에도 상점 구매 함수를 야무지게 적어두었다.

 

한번 가져와보자

 

찾았는가?

 

그렇다면.. 천재

 

난 사실 못 찾았다.

 

왜냐면 이 함수에는

물건 구매! 기 때문에

구매하고 가격이 차감되는 함수를 적는 곳이었다..ㅋㅋㅋ

 

for문이녜 뭐 다 가져왔는데..ㅋㅋ 스읍

 

일단 여기서

구매는 돈을 주고 구매하는 곳이니

 

두줄이다.

복사해 와서 붙여놔 보자

 

변수 글자를 수정하다가 생긴 빨간 오류는?

뭐다?

 

 

set을 넣어줘라

private 잊지 말고!!

 

자 이제 클래스 두 개 만들었으니

 

이 클래스를 가지고 Start 클래스를 만들어보자!

 

깨끗한 start클래스를 만들고!

 

여기에는 우리가 아까 열심히 작성했던

클래스를 가져와야 한다.

정확히 고급용어로 말하면

객체 선언

Player이라는 타입을 가진 player

Item배열인 ItemDb;

 

자 우리는 아까 말 그대로 선언만 해주었다.

 

우리는 이 친구를 제대로 만들어준 게 아니기 때문에

데이터를 만들어주는 친구

NEW를 사용해야 한다.

 

만약에 new를 통해서 만들지 않았다면

 

NULL Reference Exception

참조오류가 발생한다.

 

New는 새롭게 생성하는 거라

같은 거에는 한 번만 사용하는 게 원칙

왜냐면 같은 이름으로 계속 객체 만들면

복사가 아니라 덮어쓰기가 된답니다..^^

 

여하튼 이따가 제대로 한번 쓰도록 하고 우리는

Main을 적어보자

 

맨 처음에 Main에서는 해야 할 것 이

1. 초기 스탯 설정

2. 초기 화면 띄우기

 

이다.

 

그래서 두 함수를 적는다.

 

SetData에서

우리는 저번에 하나하나 스탯을 적어주었다

뭐 레벨은 몇

뭐 이름은 뭐

 

하지만 이제는! 클래스를 만들어 주었기 때문에!

 

간단하게 생성자 덕으로

한 줄 코딩이 완성된다.

 

에메랄드 색 Player이 클래스인데

저기에 마우스를 가져다 대면

내가 뭘 써야 하는지 순서가 나온다.

그거에 맞게 써주면 된다!

 

이것이 객체 생성이라는 것이다!!

 

setData는 일단 초기설정이기 때문에

Item 배열도 해보자!

 

배열을 생성해 줄 때

배열 내 내용이나 자료형이 다르다면

 

대괄호에 배열 개수를 적는 것보단

중괄호를 넣어서 무슨 내용을 적을지 넣는 게 더 좋다.

 

자 내용을 넣을 때도 new를 사용해야 한다.

 

 

엇 왜죠? new 썼잖아요!

 

맞아요 쓰긴 했죠

하지만 우리는 배열[] 이 칸을 만들어준 거고

이 배열에 값을 넣어주어야 하기 때문에

그 값 하나하나에도 new를 써주어야 합니다!!

불태웠다...

 

이다음에

UI는 지난 시간에 꾸며줬기 때문에

UI들은 그대로 복사해서 붙여 넣고

 

빨간 줄이 생긴 부분만 고쳐주면 된다.

 

초기메인에는 빨간 줄 없고

 

stat출력 UI에서는 우리가

아까 stat출력 내용을 복사해서 

 

Player 클래스

DisplayPlayerInfo에

넣었으니까!

 

여기에는

Player 클래스로 만든 player에서

DisplayPlayerInfo를 찍어주면 된다.

 

그럼 빨간 줄 안녕!

 

다음 인벤토리 UI에서도

아이템 목록을 우리가 아까

Player 클래스에 빼주었다.

어디에?

 

DisplayPlayerInfo에

 

 

 

이렇게 되었다면 성공!

 

다음이 중요하다!

장착인데,

 

지금은 우리가 123456으로 객체를 만들었지만

여기서 템을 만약에 1번 4번 두 개만 사면

 

위치상

1 4 즉

두 번째 위치에 4가 들어가기 때문에

4번 객체를 뽑아주려면?

인벤토리에서 2번째를 찾아서 줘! 가 되어야 한다.

 

그래서 만들었던 친구

리스트 길이만큼 출력해라.

 

저번시간 열심히 정성 들인 그림을 가져오면

 

 

지금 상황은 1이랑 4 두 개가 들어갔으니

리스트는 두 칸 차지하고 있을 거고,

리스트 길이만큼 출력하면

객체 1 객체 4 이렇게 나올 것이다.

 

그래서 리스트상 2번 위치에 있는

객체 4가 가져오게 되는 것이다.

 

여하튼

 

 

이렇게 된다.

 

 

바로 밑으로 내려와서

default에 보면

 

player에 EquipItem을 가져오고 ( 장착 [E] )

엇 빨간 줄 뭘까?

 

매개변수가 없단다

그러면 우리는 이 괄호에 뭘 써줘야 할까?!

 

바로 item n번째가 들어가야 한다

그래야 검사해서 출력이 되잖소!

 

근데 이 아이템 번호는

입력받은 값에서 1 빼줘야 하고

왜? 배열이니까

 

그 값을 배열 인덱스에 넣어주기만 하면 된다.

그러면 배열 인덱스에 있는 번호가 들어가서

그 배열 값을 호출할 것이다.

 

 

혹시 이해가 갔는가?

 

제 코드를 보며 맞춰보세요

 

 

나는..

저 에메랄드 Item을 안 썼다 ㅋㅋㅋ

 

저 친구에게도 자료형이 필요하다는 사실을 잊었다.

 

무엇보다

ItemDb 또한 Item이기 때문에

자료형을 맞춘다는 생각을 가지고 앞에 Item을 써주는 게

바로바로 생각났으면 좋겠다.

 

그럼 빨간 줄 클리어!

 

다음으로 넘어가면..

shop 상점입니다.

 

흠..

 

먼저 첫 번째

우리는 itemNames가 아니라 

아까 만든 아이템 배열이 들어가야 한다

그래서 그 배열길이만큼 검사해야 한다.

 

다음으로

지금 아이템이 뭔지를

배열 Db에서 꺼내와 보자

 

 Item curItem itemDb [i];

클래스 Item

 (여기서는 자료형이겠지만..ㅎ )

 

itemDb에서 i번째 값을

변수 curItem에 넣어준다.

 

사실 이 식을 쓴 이유는 그냥

6번 돌겠다. 이 뜻이다.

 

자 다음 삼항연산자의 빨간 줄을 없애야 하는데

 

첫 번째에

inventory.Count(i)는

인벤토리의 길이를 나타냈다.

 

우리는 인벤토리의 길이를 표현하기 위해

아까

플레이어 클래스에서

HasItem 가지고 있는 함수를 만들었었다.

 

즉 내가 가지고 있는 아이템들을 넣는 함수였다.

 

그 친구를 사용할 거고

그 함수 매개변수로 방금 만든

itemDb [i]을 넣어주면 된다.

 

그리고

가격에는 

itemDb [i]에서 price값

을 넣어주면 된다.

 

그리고 밑에는

뭐 똑같이

itemDb [i]를 우리는 curItem으로 해주었기 때문에\

 

 

이렇게 되었다면

그대는 천재..

 

나는 따라오는데 오래 걸렸습니다.

 

여기서 

더 천재가 될 수 있는 것

 

우리는 아까 Item 클래스에다가

이 친구를 추가했었다.

 

굉장히 유사해 보이죠?

 

더 간단해졌다면..

 

완전 천재

 

 

이 글을 더 볼 필요가 있을까?

 

ㅋㅋㅎ

자 이제 BuyUI

 

for문 빨간 줄은

위에 아이템 상점과 같고

아!

 하나 다른 건

아이템이 몇 번인지 번호 출력이 있어야 하니까 

 

마지막 출력에

{ i+1 }을 해주면 된다.

 

 

밑에 내려와서

default를 보면

 

if (inventory.Contains(result - 1))

 

일단 여기 

inventory.Contains

아까 함수로 만들어준

player.HasItem으로 바꿔줄 거고

 result - 1 은 더 이상 해줄 필요없다.

정보의 하나를 가져오는게 아니라

배열 자체를 가져와야하기때문에

 

 result - 1 를 업그레이드 해줘야한다.

 

 

아까 장착때 해줬었다.

 

그렇다면 뭐 다했다.

 

 

골드도 바꾸고

인벤토리도

targetItem로 바꿔주면 끝!

 

그러면 문제가 생긴다.

아이템 장착 시,

DisplayInventoryInfo() 이라는 

player  클래스에서 만든 함수에서

 

값을 고정해놨기때문에 앞에 숫자가 안나오게 된다.

 

그러면 어떻게 해야할까?

 

음..만약에 참 ( 아이템 장착 창이면 )

숫자 보여주고

거짓  ( 아이템 보여주는 창이면 )

숫자 안보여주면 되지않을까??

 

바로 해보자

저 함수 파라미터로

bool값을 하나 받아준다.

 

DisplayInventoryInfo(bool showIdx)

 

그리고 밑에

 

string displayIdx = showIdx ? $"{ i+1 }  " : " " ;

 

Console.WriteLine($"- {displayIdx} {displayequip} {targetItem.ItemInfoText}");

 

 

이렇게 다!

 

해주면 끝나는데

 

오류가 하나 생긴다.

 

 

문제는 배열로 만들어주었는데

itemDb[itemIdx]는 

우리한테 있던 6개 itemDb의 번호를 가져오는 것이다.

 

하지만 그렇게 되면

4번째 템을 사게되면

인벤토리에서는 첫번째가 되어야하는데

 

그대로 4번이 오게 되는 것이다.

 

그러면 어떻게 해주어야할까?

 

인벤토리에 있는 값을 가져오면 되겠다!

 

하지만 인벤토리는 현재 플레이어 클래스에서

private로 지정되어있다.

 

즉 외부에서는 쓸 수없게 만들어져있다.

 

그래서 우리는 

 get을 통해서 밖으로 꺼낼 수 있도록 할 것이다.

 

플레이어 클래스로 돌아가서

 

 

생성! 

 

그래서 그 밑에

player.Inventory[itemIdx]

인데?

Inventory는 우리가 returnInventory로 만들어줬으니

 

 Item targetItem = player.returnInventory[itemIdx];

 

해주면 오류 소멸!

 

이렇게 클래스를 나누어서해주면

더 깔끔하게 코드를 짤 수있다.

 

업그레이드 를 준비했으니

여러분들도 충분히 보면서

익히도록 하십쇼

 

그럼 

20000!

 

< Player.cs >

using System.Reflection.Emit;
using System.Windows.Markup;
using System.Xml.Linq;

namespace ConsoleApp1
{

    internal class Player
    {
        //캐릭터 정보
        //( 레벨 / 이름 / 직업 / 공격력 / 방어력 / 체력 / 골드 )

        public int Level { get; }
        public string Name { get; }
        public string Job { get; }
        public int Ad { get; }
        public int Def { get; }
        public int Hp { get; }
        public int Gold { get; private set; }

        // 추가공격력, 나중에 +- 해줘서 값이 달라질테니 set도 필요하다.
        // set을 안써주면 읽기전용이라는 에러 발생
        public int ExtraAd { get; private set; }
        public int ExtraDef { get; private set; }


        private List<Item> Inventory = new List<Item>();
        // 캐릭터가 장비를 가지고 있다.
        private List<Item> EquipList = new List<Item>();

        public int InventoryCount
        {
            get
            {
                return Inventory.Count;
            }

        }

        public List<Item> returnInventory
        {
            get
            {
                return Inventory;
            }

        }


        public Player(int level, string name, string job, int ad, int def, int hp, int gold)
        {
            Level = level;
            Name = name;
            Job = job;
            Ad = ad;
            Def = def;
            Hp = hp;
            Gold = gold;
        }
        public void DispalyPlayerInfo()
        {
            Console.WriteLine($"LV.{Level:D2}");
            Console.WriteLine($"{Name} {{ {Job} }}");

            Console.WriteLine(ExtraAd == 0 ? $"공격력 : {Ad}" : $"공격력 : {ExtraAd + Ad} (+{ExtraAd})");
            Console.WriteLine(ExtraDef == 0 ? $"방어력 : {Def}" : $"방어력 : {ExtraDef + Def} (+{ExtraDef})");

            Console.WriteLine($"체력 : {Hp}");
            Console.WriteLine($"골드 : {Gold}G");
        }

        public void DisplayInventoryInfo(bool showIdx)
        {

            for (int i = 0; i < Inventory.Count; i++)
            {
                Item targetItem = Inventory[i];
                string displayIdx = showIdx ? $"{i + 1}  " : "";
                string displayequip = IsEquipItem(targetItem) ? "[E]" : "";
                Console.WriteLine($"-{displayIdx}{displayequip} {targetItem.ItemInfoText()}");
            }

        }

        public void EquipItem(Item item)
        {
            if (IsEquipItem(item))
            {  //장착이 되어있다면 [E] 해제 + 추가 공격력 방어력 extra값 -

                EquipList.Remove(item);
                if (item.Type == 0)
                {
                    ExtraAd -= item.Value;
                }
                else
                {
                    ExtraDef -= item.Value;
                }
            }
            else
            {//장착이 안되어있으면 [E] 장착 + 추가 공격력 방어력 extra값 +
                EquipList.Add(item);
                if (item.Type == 0)
                {
                    ExtraAd += item.Value;
                }
                else
                {
                    ExtraDef += item.Value;
                }
            }
        }
        
        public bool IsEquipItem(Item item)
        {
            return EquipList.Contains(item);
        }
        
        public void BuyItem(Item item)
        {
            Gold -= item.Price; // 금액 차감
            Inventory.Add(item); // 인벤토리리스트에 배열 추가
        }

        public bool HasItem(Item item)
        {
            return Inventory.Contains(item);
        }

    }

}

 

< Item.cs >

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    internal class Item
    {
        public string Name { get; }
        public int Type { get; }
        public int Value { get; }
        public string Desc { get; }
        public int Price { get; }

        public Item(string name, int type, int value, string desc, int price)
        {
            Name = name;
            Type = type;
            Value = value;
            Desc = desc;
            Price = price;
        }

        public string DisplayTypeText { get { return Type == 0 ? "공격력" : "방어력"; } }

        public string ItemInfoText() 
        {
            // 아이템 정보 출력, 조금씩 다르기때문에 그래서 공통적인 부분만 표시해준다.
            // 이름 | 공격력 or 방어력 + n | 설명
            return ($"{Name} |{DisplayTypeText} + {Value} | {Desc}");
            
        }

    }
}

 

< Start.cs >

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace ConsoleApp1
{
    internal class Start
    {
        private static Player player;
        private static Item[] itemDb;

        static void Main(string[] args)
        {
            SetData(); // 여기엔 내 정보 초기화
            DisplayMainUI(); //초기 화면
        }

        static void SetData()
        {
            player = new Player(1, "Cha", "전사", 10, 5, 100, 150000);
            itemDb = new Item[]
            {
                new Item("수련자의 갑옷", 1, 5,"수련에 도움을 주는 갑옷입니다.",1000),
                new Item("무쇠갑옷", 1, 9,"무쇠로 만들어져 튼튼한 갑옷입니다.",2000),
                new Item("스파르타의 갑옷",1,15,"스파르타의 전사들이 사용했다는 전설의 갑옷입니다.",3500),
                new Item("낡은 검", 0, 2,"쉽게 볼 수 있는 낡은 검 입니다.",500),
                new Item("청동 도끼", 0, 5,"어디선가 사용됐던거 같은 도끼입니다.",1500),
                new Item("스파르타의 창", 0, 7,"스파르타의 전사들이 사용했다는 전설의 창입니다.",2500)
            };
        }

        static void DisplayMainUI()
        {
            Console.Clear();
            Console.WriteLine("텍리지에 오신것을 환영합니다.");
            Console.WriteLine("이곳에서 던전으로 들어가기 전 활동을 할 수 있습니다.");
            Console.WriteLine();
            Console.WriteLine("1. 상태보기");
            Console.WriteLine("2. 인벤토리");
            Console.WriteLine("3. 상점");
            Console.WriteLine();
            Console.WriteLine("원하시는 행동을 입력해주세요.");


            int result = CheckInput(1, 3);

            switch (result)
            {
                case 1:
                    DisplayStatUI();
                    break;

                case 2:
                    DisplayInventoryUI();
                    break;

                case 3:
                    DisplayShopUI();
                    break;
            }

        }

        static void DisplayStatUI()
        {
            Console.Clear();
            Console.WriteLine("내 상태 보기");
            Console.WriteLine("캐릭터의 정보가 표시됩니다.\n");

            player.DispalyPlayerInfo();

            Console.WriteLine();
            Console.WriteLine("0 : 나가기");
            Console.WriteLine();
            Console.WriteLine("원하시는 행동을 입력해주세요.");

            int result = CheckInput(0, 0);

            switch (result)
            {
                case 0:
                    DisplayMainUI();
                    break;
            }

        }

        // 인벤토리 UI
        static void DisplayInventoryUI()
        {
            Console.Clear();
            Console.WriteLine("인벤토리");
            Console.WriteLine("보유중인 아이템을 관리할 수 있습니다.");
            Console.WriteLine();
            Console.WriteLine("[ 아이템 목록 ]");

            player.DisplayInventoryInfo(false);

            Console.WriteLine();
            Console.WriteLine("1 : 장착 관리");
            Console.WriteLine("0 : 나가기");
            Console.WriteLine();
            Console.WriteLine("원하시는 행동을 입력해주세요.");

            int result = CheckInput(0, 1);

            switch (result)
            {
                case 0:
                    DisplayMainUI();
                    break;

                case 1:
                    DisplayEquipUI();
                    break;
            }

        }

        // 인벤토리 장착 UI
        static void DisplayEquipUI()
        {
            Console.Clear();
            Console.WriteLine("인벤토리");
            Console.WriteLine("장착 할 아이템을 선택해 주세요.");
            Console.WriteLine();
            Console.WriteLine("[ 아이템 목록 ]");

            player.DisplayInventoryInfo(true);

            Console.WriteLine();
            Console.WriteLine("0 : 나가기");
            Console.WriteLine();
            Console.WriteLine("장착할 아이템의 번호를 적어주세요.");

            int result = CheckInput(0, player.InventoryCount);

            switch (result)
            {
                case 0:
                    DisplayInventoryUI();
                    break;

                default: // 장착로직 구현
                    int itemIdx = result - 1;
                    //Item targetItem = itemDb[itemIdx]; -> ㅈㅏㄹㅁㅗㅅㄷㅚㅁ 
                    Item targetItem = player.returnInventory[itemIdx];
                    player.EquipItem(targetItem);

                   
                    DisplayEquipUI();
                    break;

            }
        }

        // 상점 UI
        static void DisplayShopUI()
        {
            Console.Clear();
            Console.WriteLine("상점");
            Console.WriteLine("아이템을 구매할 수 있습니다.");
            Console.WriteLine();
            Console.WriteLine("[ 보유골드 ]");
            Console.WriteLine($"{player.Gold}G");// 보간문자열 사용
            Console.WriteLine();
            Console.WriteLine("[ 아이템 목록 ]");
            //아이템을 써주어야한다.

            for (int i = 0; i < itemDb.Length; i++)
            {
                //구매 완료 시 금액이 아니라 구매완료가 떠야한다.
                Item curItem = itemDb[i];

                string displayPrice = player.HasItem(curItem) ? "구매완료" : $"{curItem.Price}G";
                Console.WriteLine($"- {curItem.ItemInfoText()} | {displayPrice}");
            }

            Console.WriteLine();
            Console.WriteLine("1 : 아이템 구매");
            Console.WriteLine("0 : 나가기");
            Console.WriteLine();
            Console.WriteLine("원하시는 행동을 입력해주세요.");

            int result = CheckInput(0, 1);

            switch (result)
            {
                case 0:
                    DisplayMainUI();
                    break;

                case 1:
                    DisplayBuyUI();
                    break;
            }

        }

        // 상점 구매 UI
        static void DisplayBuyUI()
        {
            Console.Clear();
            Console.WriteLine("상점 - 아이템 구매");
            Console.WriteLine("아이템을 구매할 수 있습니다.");
            Console.WriteLine();
            Console.WriteLine("[ 보유골드 ]");
            Console.WriteLine($"{player.Gold}G");// 보간문자열 사용
            Console.WriteLine();
            Console.WriteLine("[ 아이템 목록 ]");
            //아이템을 써주어야한다.

            for (int i = 0; i < itemDb.Length; i++)
            {
                //구매 완료 시 금액이 아니라 구매완료가 떠야한다.
                Item curItem = itemDb[i];

                string displayPrice = player.HasItem(curItem) ? "구매완료" : $"{curItem.Price}G";
                Console.WriteLine($"-{i + 1} {curItem.ItemInfoText()} | {displayPrice}");
            }

            Console.WriteLine();
            Console.WriteLine("0 : 나가기");
            Console.WriteLine();
            Console.WriteLine("원하시는 행동을 입력해주세요.");

            int result = CheckInput(0, itemDb.Length); // 아이템 길이만큼..

            switch (result)
            {
                case 0:
                    DisplayShopUI();
                    break;

                default: // 0 이 아닌 다른값이 들어온다면 진입

                    int itemIdx = result - 1;
                    Item targetItem = itemDb[itemIdx];
                    if (player.HasItem(targetItem)) // 이미 샀다면, 구매완료표시가 이미 있다면
                    {                // 이 구매완료표시가 있다는 뜻은 List에 들어가있다면! 으로 해석가능
                        Console.WriteLine(" ===  이미 구매 완료했습니다 === ");
                        Console.WriteLine("enter를 입력해주세요.");
                        Console.ReadLine();
                    }
                    //구매 완료 표시가 떠야함
                    else // 살 수 있다! 구매 표시가 없을때!
                    {
                        if (player.Gold >= targetItem.Price) // 돈이 많을경우 (구매가능)
                        {
                            Console.WriteLine(" === 구매를 완료했습니다. === ");
                            Console.WriteLine("enter를 입력해주세요.");
                            Console.ReadLine();

                            player.BuyItem(targetItem);
                        }
                        else
                        {
                            Console.WriteLine(" === 골드가 부족합니다. === ");
                            Console.WriteLine("enter를 입력해주세요.");
                            Console.ReadLine();

                        }
                    }

                    DisplayBuyUI();
                    break;
            }
        }


        // 숫자가 맞는지 확인하는 친구
        static int CheckInput(int min, int max)
        {
            //int result = int.Parse(Console.ReadLine());
            int result; // 값을 담을 변수선언

            while (true)
            {

                bool isNumber = int.TryParse(Console.ReadLine(), out result);
                if (isNumber)
                {
                    if (result >= min && result <= max) { return result; }

                }
                Console.WriteLine("잘못된 입력입니다.");
            }
        }


    }
}

 

 

진짜 끝!