NGUI 2D 조합디펜스게임 

예상 개발기간 : 3주~4주

게임소개 :  랜덤으로 생성되는 캐릭터를 조합(강화)하는 디펜스게임

 

1. 테이블구성

해당 타입의 맞게 스프레드시트를 통해 데이터를 불러와 표시하려고 한다.

config : 버전 등

stage : 스테이지 데이터들을 가지고 있는 테이블

Hero : 캐릭터 능력치

캐릭터 테이블

Comb: 조합테이블

조합표 테이블

캐릭터들은 nID를 통해 관리하고 싶어 hero,comb 테이블 각각 다르지만 ID를 고유값으로 설정했다.

사실 이렇게 초기셋팅은 해놨지만 구현하다가 바뀔수도 있을것 같다.

파일은 스프레드시트의 키값과 주소를 문자열을 파싱해여 Json형식으로 받아 데이터형식으로 받는다.

이 테이블은 각각 Table.class를 생성했고, TableMng.class를 통해 테이블을 요청했을때 해당하는 테이블 데이터를 리턴하도록 만들었다. 

그리고 게임시작할때 한번 모든 테이블과 데이터들은 로드된다. 이 테이블이 다운로드되는 시간을 로딩신으로 구현할것이다. 

게임시작 시 실행

 

반응형

리소스를 임포트를 하려고 했는데 이런 에러가났다.

알아보니 이런 오류가나는 몇가지 이유들이 있었다.

1. 파일경로에 영어외의 문자가 있을경우

2. 패키지작성자와 패키지수신자의 버전이 맞지 않는 경우

3. 패키지를 export하는 압축 과정중에 아직 끝나지 않은 경우에 유니티를 종료했을 경우

 

나는 3번째 경우였다.

 

반응형

-형상관리툴

소프트웨어 버전 관리 툴이라고 생각하면 될듯하다. 

-형상관리는 소스의 변화를 끊임없이 관리하는 것이다. 개발과정에서 소스를 수정하거나 특정 시점으로 되돌릴 수 있기 때문에 특히 협업프로젝트는 필히

형상관리 툴로 깃허브,빗버킷,깃랩,SVN등이 있지만 이 프로젝트는 깃랩을 사용하기로 했다.

이유는 pravite저장소에 10GB용량을 무료로 지원해주기 때문이다.

-소스트리

사실 깃을 사용하기에는 쉽지않다. 깃에서 사용되는 명령어들도 알고 있어야한다.  그래서 좀 더 쉽게 사용하기 위해 소스트리 https://www.sourcetreeapp.com/ 를 이용하기로 했다.

소스트리

연동방법:  Clone탭 -> 첫 번째칸에는 깃랩 프로젝트의 주소를 넣고 두 번째 경로에는 내 로컬저장소 위치를 넣어주면된다.

유니티는 Asset,Packages,ProjectSettings 이 3개의 폴더만 푸쉬해야한다.

그렇기 때문에 이런식으로 무시 해두자. 한번 무시하면 저폴더의 하위목록들은 커밋창에 뜨지 않는다.

소스트리는 커밋으로 로컬 저장소에 올린 뒤에 푸쉬를해서 서버에 올리는 방식이다. 이중저장같은 느낌

 

유의점

- 작업하는 유니티버전 맞추기(버전마다 리소스의 메타파일 ID가 다를 수 있음)

- Edit - Project Settings - Asset Serializationg - Force Text로 변경

씬에 변경된 내용을 추적이 가능하다고 한다. 아직 해본적이 없지만 일단 이렇게 셋팅!

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

문제

문자열 배열을 받아서 위에서 부터 차례대로 받는다고 생각하고, 입력된 문자열중에 같은 문자열이 있으면 문자열 끝에 '(1)'을 추가해준다. ex) a라는 문자열이 존재한 상태에서 a를 추가하면 새로 추가한 문자열은 a(1)이된다. 그 다음 다시 a를 넣으면  a가 있기 때문에 a(1)으로 바꿔준다. 그런데 또 a(1)이 있기 때문에 a(2)로 바꿔준다. 

가장 이해하기 좋은 테스트 문제

풀이 : 내가 작성한 코드

배열을 통째로 받지만 함수안에서 위에서부터 처음부터 받는다고 생각해야한다. 일단 문자열을 관리 할 수있는 컨테이너를 만든 뒤, 문자열을 하나 추가하면 그 컨테이너에서 새로 추가한 문자열이 중복이 있는지 체크한다. 그런데 여기서 한번 더 생각해야 할 것이 처삽입될 문자열을 바꾸고, 또 다시 컨테이너를 탐색해야한다. 컨테이너의 같은 문자열이 있을 수는 없기 떄문이다.   for문으로 체크하기에는 배열의 인덱스와 요소 체크하기가 까다로울 것 같고, while문으로 삽입된 리스트들을 통째로 탐색하도록 한다.

count를 통해 같은 문자열의 갯수를 체크하고 문자열의 값을 변경하면서 while문을 통해 list를 탐색한다.

풀이 : 다른 사람이 작성한 코드

while(!set.Add(cade))를 통해 중복된 문자가있으면 카운트를 증가시키고 그렇지 않으면 set에 추가 하게된다. HashSet은 잘 사용하지 않았었는데 HashSet.Add에는 bool반환형이 있다. 추가되었으면 ture, 요소가 이미 있으면 false를 리턴한다.

 

문제 : https://codesignal.com/

반응형

3D물체를 움직이면 캐릭터에 가까운 지형은 활성화 멀리있는 지형은 비활성화 하도록 풀링을 해보았다.

땅을 생성하면 자동적으로 랜덤으로 땅위 바위와 나무들이 랜덤으로 위치한다.

클릭 하면 gif 재생

처음에는 지형이 가지고 있는 스크립트에서 캐릭터와의 거리를 체크해주려고 했는데 오브젝트가 꺼져있을때 체크가 불가능하기 때문에 지형이 생성될 때 위치를 관리하고 있다가 그 거리를 캐릭터와 비교 하도록 했다.

m_lipool : 풀링에 들어온 오브젝트

m_liActive : 활성화 된 오브젝트

유니티 실행하면 초기에 땅을 생성하는 함수이다. 생성과 동시에 리스트에 지형오브젝트의 위치를 추가해준다. 

캐릭터와 멀리있는 지형에 있는 오브젝트를 비 활성화 해주기 위한 함수이다. 

m_liTemp는 멀리있는 지형을 비 활성화 해주기 위한 리스트이다. PlanSet스크립트를 통해 멀리있으면 m_liTemp에 담아 두고 꺼주도록 한다. m_liActive에는 삭제해주고 다시 m_liPool에 넣어둔다. 

무한이 로딩되는 맵에 사용하도록 하면 좋을 듯하다.

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

문제

','를 구분한 문자열중 가장 긴 문자열을 구하는 문제이다. 특수문자 제외,  쉼표(',')제외

풀이 : 내가 작성한 코드

빈 문자열 변수를 만들어 놓고 a~z || A <Z 사이에 포함되는 문자들만 입력한다. else는 ','를 받게되면 다음 문자열의 길이를 비교하여 다음 문자열을 만들 준비를 한다.  고려할 부분은 띄어쓰기와 특수문자를 제외하는 방법 이 두가지 정도가 있을 수 있다. C#문법만 하더라도 여러가지 방법이 있겠지만 나는 문자의 범위를 비교하였다. 

풀이 : 다른 사람이 작성한 코드

Regex.Matches 문법을 사용했다. 입력 문자열에 있는 정규식을 모두 검색하고 일치 항목을 모두 반환한다고 한다. 그러면 자동적으로 띄어쓰기와 , 특수문자를 제외 시킨 문자가 m 입력된다. C#에는 다양한 문법이 있지만 게임에서 적용은 하기 힘들듯하다.

https://docs.microsoft.com/ko-kr/dotnet/api/system.text.regularexpressions.regex.matches?view=netframework-4.8

문제 : https://codesignal.com/

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

문제

문제는 길지만 테스트문제를 보면 쉽게 이해 할 수 있었다. 

문자열을 체크하여 숫자만 뽑아내어 그 숫자들의 합을 리턴하는 문제이다.

풀이 : 내가 작성한 코드

단순히 문자열을 for문을 통해 char요소를 하나씩 체크하여 숫자가 나오면 새로 생성한 int형 변수에 차근차근 더하여 계산 하려했지만, 숫자가 붙어있는 경우(즉 1자리를 넘는 경우)에도 모두 1의자리로 계산이된다.  그러면 숫자를 그때마다 int형으로 바꿔서 더하지 말고 십의자리 그 이상의 자리까지를 대비가 필요하다. char형 문자를 체크하면서 숫자가 나오면 string변 수에 넣어준다. 다음 문자가 숫자가 아닐때 까지, 숫자가 아닐 때 까지 모두 더한 string변수를 int형으로 변경하여 값을 더 해준다.

두번째 if문에서 temp !=""를 체크하는 이유 : 첫 번째 if문은 숫자가 아닐 경우 temp에 있는 값을  sum 변수에 더해주고 있다. 문자열 마지막요소의 형식이 숫자라면 그 전까지 더한 temp를 넘기게된다. 그래서 마지막 체크를 한번 더 해줬다. 

풀이 : 다른 사람이 작성한 코드

foreach(Match match in Regex.Matches(inputString, "[0-9]+") 지정한 정규식을 통해 stirng 숫자값만 딱 뽑아진다.

 

문제 : https://codesignal.com/

반응형

이쪽 카테고리는 학습하면서 삽질 + 복습용으로 사용해야겠다.

문법중에 제네릭인데 구조적으로 자주 사용하는게 좋은데 안쓰다보니 계속 안쓰게된다.... 다시 복습겸 기본 예제 코드를 만들어서 복습했다.

public class Test<T>
{
	public T field;
	
	public Test(T t)
	{
		field = t;
	}
}

제네릭 Test.class를 만들고 클래스 인스턴스를 생성할때 생성자를 통해 변수 field에 할당 하도록 했다.  

public class m_test : MonoBehaviour
{
	public Test<int> m_int;
	public GameObject obj_test;
	public Test<GameObject> m_gobj;

	void Start()
    {
		m_int = new Test<int>(10);
		Debug.Log(m_int.field);


		m_gobj = new Test<GameObject>(obj_test);
		Debug.Log(m_gobj.field.gameObject.name);
	}
}

예로 <int>, <GameObject>두 가지로 클래스를 생성했다. Test<int>는 10을 넣고 Test<GameObject>는 TestObj라는 이름 인 GameObject를 인스펙터창에서 넣고    Test<GameObject> 클래스 생성할 때 생성자에 넣었다.

유니티 디버그 콘솔창

where T : 제약조건  (인터페이스

where T : <인터페이스 이름> 형식 인수가 지정된 인터페이스이거나 지정된 인터페이스를 구현해야 합니다. 여러 인터페이스 제약 조건을 지정할 수 있습니다. 제한하는 인터페이스는 제네릭이 될 수도 있습니다.
public interface IMonster
{
	void print();
}
public class MessagePrinter : IMonster
{
	string Message;

	public MessagePrinter(string message)
	{

		this.Message = message;
	}

	public void print()
	{
		Debug.Log(this.Message);
	}
}

public class Test<T>  where T : IMonster
{
	public T[] Array { get; set; }

	public Test(int size)
	{
		Array = new T[3];
	}

}

 

public class m_test : MonoBehaviour 
{

	Test<IMonster> test = new Test<IMonster>(3);
	void Start()
    {
		test.Array[0] = new MessagePrinter("하나");
		test.Array[1] = new MessagePrinter("둘");
		test.Array[2] = new MessagePrinter("셋");


		for (int i = 0; i < 3; i++)
			test.Array[i].print();
	}
}

반응형

NGUI를 공부하다가  간단하게 뭐라도 만들면 좋을것 같다고 생각하다가 예~전에 윈도우에 설치되어있던 카드게임을 만들게 되었다. 솔리테어인데 사실 이 게임 룰도 몰랐다. 생각보다 만들다 보니 룰이 복잡했다. 아직 카드를 놓을 수 있는 룰 제한은 넣지 않았다. 

1.카드 나열

순서대로 1번째는 1장,2번째는 2장 ~~~7번째는 7장의 카드가 놓여지고 그 배열의 맨 마지막 카드만 뒤집어짐

2. 나열되지 않은 카드배열 뒤집기

밑에 나열된 카드를 제외하고 남은 카드배열을 가지고있다가 버튼을 누르면 위에서부터 하나씩 뒤집어준다.

3. 마지막 위치한 카드 뒤집기 (아직 룰 적용 X)

카드를 선택하고 이동할 위치에 클릭하면 카드가 선택한 카드의 위치의 카드정렬은 마지막카드를 뒤집어준다.

미처리 부분 

- A로 적혀있는 빈공간에는 A부터 차례대로 놓을 수 있게 처리

- 밑에 뒤집어져있는 7개의 카드에는 제일 위에있는 카드 숫자보다 1 큰 카드만 올 수있고 다른 색의 카드가 와야한다 ex) 7클로버(검      은색)카드가 있다면 8하트(빨간색)or8다이아(빨간색)..빨간색의 숫자가 8인 카드

- 맨 오른쪽위의 카드는 7개의 깔려있는 카드 외의 카드들이다. 모두 뒤집었을 경우 다시 반대로 뒤집어 지도록 

- 모든 카드들은 클릭될 수가 있으므로, 뒤집어져 있는 카드만 클릭이 되도록 설정 예를들어 5장의 카드가 뒤집어져있는 카드배열을 클릭하면 모두 움직이도록 설정이 필요

- 추가적으로  생각나지 않는것들..

간단하게 연습삼아 만들어봤는데 생각보다 복잡해서 당황했다..

 

반응형

'유니티 > NGUI' 카테고리의 다른 글

NGUI) UI 사용법[버튼 클릭처리,텍스트(Label)]  (0) 2019.04.30
NGUI) Sprite,아틀라스 활용하기  (0) 2019.04.28

문제점 : 빨간색 / 해결방법 : 파란색 / 느낀 점 : 녹색 

 

위 box, 밑 bomb 

폭탄이 터지면 4방향(좌,위,우,하)를 레이캐스트로 확인해주려고 한다.

오브젝트 종류 : box,wall,player,enemy

4방향의 wall있으면 wall이있는 방향에는 폭탄이 터지는 애니메이션 발동X

box는 box를 애니메이션 발동과 box를파괴를 하고싶었다.

이런식으로 레이가 4방향으로 돌면서 콜라이더를 검출하도록 했다.

우선 충돌처리를 하기 위해 boxcollider2D와 rigidbody2D컴포넌트를 추가했다.

이상하게 계속 검출이 안됐다. 이유는 rigidbody2D의 Simulated체크를 안했었다.

유니티도큐 : 리지드바디 2D 및 연결된 모든 콜라이더 2D와 조인트 2D가 런타임에 물리 시뮬레이션과 상호작용하도록 하려면 Simulated 를 활성화합니다(체크박스를 선택합니다). 비활성화되면(체크박스가 선택 해제되면) 이들 컴포넌트가 시뮬레이션과 상호작용하지 않습니다. 

느낀 점 : 충돌처리를 할때는 생각해야 할 부분들이 있다 . Coliider,Rigidbody, 스크립트 상의 OnTrigger,On ColiiderOnCollisi

onEnter등 차이점과 활성화와 비활성화 했을때 각각 다른점들을 다시 한번에 체크해봐야겠다.

반응형

Label 은 폰트를 설정하여 글씨를 표시할 수 있는 객체

Texture 는 PNG, JPG 등의 파일을 불러와 이미지를 표시

Sprite 는 PSD 등의 Atlas파일을 불러와 이미지를 표시하는 오브젝트

Widget 은 기본적인 공간 상의 설정만을 가지는 빈 오브젝트

 

일단 작업전에 셋팅해주면 좋은거

원활한 UI작업을 위해 기즈모 사이즈를 줄여서하는 좋을 듯하다.

NGUI를 사용하려면 알아야 할 기본적인 것들

1. 모든 UI들은 UI Root안에 있어야한다. (UGUI의 canvas처럼)

2. 보통 UGUI와 NGUI를 같이 사용하지 않는다.

3. Depth기준을 어느정도 정해놓고 작업 진행하는게 좋다.

3. UI Panel Clipping -> softclip으로 변경 시

 

버튼 기능만들기

UGUI는 Button컴포넌트가 있다면 NGUI는 EventTrigger가 있다

1. 셋팅

UGUI버튼의 OnClickButton이랑 비슷한 기능이다. On Press는 마우스 클릭했을 때 발동된다. 

클릭하면 스프라이트이미지가 변경된다.

BoxCollider 추가하기

마우스처리를 하려면 콜라이더를 추가해야한다. 그리고 Collider auto-adjust to macth를 클릭해준다. 이게 무엇이냐 NGUI장점 스프라이트 크기만큼 콜라이더의 사이즈가 맞춰진다. 굿!

UI Camera 셋팅 

2D UI로 변경해준다.

텍스트 만들기 Label

Label을 처음 만들면 font를 지정해줘야한다. 같은 객체 안에 UI sprite, UI Label을 같이 사용하지 않도록한다.

확실히 다른 컴포넌트를 추가하지 않아도 기본적인 NGUI 기능들이 많다. 다 쓸까? 오히려 복잡해보이기도 하고 빌트인된 UGUI가 아직 더 편한거 같다.

반응형

'유니티 > NGUI' 카테고리의 다른 글

NGUI연습) 솔리테어 카드게임_작업중  (1) 2019.05.03
NGUI) Sprite,아틀라스 활용하기  (0) 2019.04.28

문제점 : 빨간색 / 해결방법 : 파란색 / 느낀 점 : 녹색 

C# 윈폼으로 포폴 소개용 툴을 제작 중에 오류이다.

일단 C#문법을 익힐 때 공부했던 내용이다. static클래스는 모든 멤버가 static멤버로 되어 있으며, 클래스 명 앞에 static이라는 키워드를 정의해주고 사용해야한다. 그리고 Static클래스는 public 생성자를 가질 수 없다.  

Static클래스가 생성자를 가질 수 없는 이유는?

static클래스는 객체를 생성할 수 없기 때문이다. 그럼 또 다시 static클래스의 내용을 살펴보면 인스턴스를 생성해서 메서드를 접근하는 방법과 다르게 static클래스로 부터 직접 호출하는 메서드이다. (클래스이름.메서드이름)

인스턴스를 생성하지 않는다?

일반  클래스는 인스턴스를 생성할 때마다 메모리에 매번 새로 생성되는데, static필드는 프로그램 실행 후 해당 클래스가 처음으로 사용될 때 한 번 초기화되어 계속 동일한 메모리를 사용하게된다.

Static생성자를 이용할때는?

주로 static필드들을 초기화 하는데 사용한다.  생성자가 실행되는 시점은?

1) 클래스의 정적필드에 접근하기 직전에 호출된다.

2) 클래스의 인스턴스를 생성하기 직전에 호출된다.

3) 모든 클래스의 정적 생성자는 최초 한번만 호출된다.


처음에 C#문법을 공부할때는 Static클래스,생성자 등 그냥 그런가보다 외우고 이걸 언제 사용할까? 생각했는데 프로젝트를 만들고 오류에 직접 부딪혀보고 해결하다 보니 이해가 된다. 

반응형
	public UISprite sprite;
    void Start()
    {
		sprite.spriteName = "key4";
	}

UGUI에서 아틀라스 공부했을때 드로우콜을 줄여 성능에 도움이된다고 학습했다. NGUI에서도 아틀라스를 다루기위해 학습 포스팅하게 되었다.

(UGUI아틀라스) : https://funfunhanblog.tistory.com/44

UGUI와 사용 방법이 다르다.

1.아틀라스 생성

Create -> Atlas

이름을 지정하고 생성해준다.

성공적으로 생성이 됐다면 Assets폴더에 생긴다.

 2. sprite추가

Open -> Atlas Maker

Atlas Maker를 누르면 위 그림과 같은 창이 뜨는데, 1번 그림 처럼 Atlas를 누르면 2번 그림 처럼 새로운 창이 뜬다. 그러면 현재 만들어져있는 아틀라스 목록들이 나오는데 여기서 사용할 아틀라스를 클릭해준다.

이미지를 추가할 아틀라스를 선택하고 이미지를 클릭하면 자동으로 sprite목록을 추가된다.  그 다음 Add/Update를 누르면 실제 아틀라스에 묶이게 된다.

삭제
추가

삭제한 다음에 이미지를 클릭하면 Add로 상태 보여준다. 같은 방법으로 Add/Update 버튼을 눌러준다.

3. sprite적용방법

sprite객체를 만들고

UI Sprite스크립트에서 생성한 아틀라스와 스프라이트를 설정해준다.

3. sprite적용방법2_스크립트적용

spritename = coin3

    public UISprite sprite;
    void Start()
    {
		sprite.spriteName = "key4";
	}

sprite.sprtieName = "이미지 이름"; 이러면 끝이다

ugui보다 간편하게 적용이 가능하다.

 

반응형

그래프 알고리즘 중에 깊이 우선 탐색(DFS) 과정을 유니티로 구현해봤다.

깊이 우선 탐색은 먼저 해당하는 모든 정점을 탐색하고, 넓게(wide) 탐색하기 전에 깊게(deep) 탐색하는 것이다. 인접 노드를 먼저 탐색하고 인접 노드를 모두 방문하면 그다음 정점으로 탐색한다.

 

알파벳 박스들은 정점, 보라 색선은 간선이다.  Clear 버튼을 누르면 데이터를 가지고 있는 컨테이너들을 비워주고 위치 또한 다시 랜덤으로 설정하도록 했다.

오른쪽에 긴 사각형이 stack으로 실제 정점데이터가 stack으로 push 또는 pop 되면, 정점에 해당하는 이미지박스 역시 채워지고 비워진다.

노란색으로 바뀌는 박스는 stack에 들어있는 정점이고, 파란색은 방문한 정점이다. (방문한 정점은 다시 방문하지 않음)

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

문제

올바른 시간을 표현하고 있는지 여부를 체크하는 문제이다. 시간 00부터 ~23까지/ 분은 0부터 59까지 표현이 가능하다는 부분

풀이 : 내가 작성한 코드

C#에는 Split라는 함수 덕분에 ':'기준으로 나눈 문자열을 배열로 쉽게 받을 수 있다. 시간을 나타내는 time[0]과 분을 나나태는 time[1]로 나뉘게 된 것이다.  int.Parse를 통해 숫자로 바꾸어주고 24와 59를 비교해준다. 

풀이 : 다른 사람이 작성한 코드

어렵지 않은 문제라 C#함수를 사용한 짧은 코드보다 다른 방법으로 접근한 코드들을 찾아봤다. 

디버깅 해보니 DateTime dummy에는 현재 날짜와 매개변수로 받은 time이 시간,분으로 입력되었다. ParseExact함수 두 번째 문자열은 시간,분을 받는 형식을 지정해준다. 이 형식또는 시간규칙에 맞지 않으면 catch해주도록 한다.

 

문제 : https://codesignal.com/

반응형

문제점 : 빨간색 / 해결방법 : 파란색 / 느낀 점 : 녹색 

C# 윈폼으로 포폴 소개용 툴을 제작 중에 오류이다.

저 드랍다운 리스트를 클릭하면 드롭다운으로 선택한 항목의 목록들이 출력되는데

리스트 드랍다운버튼을 클릭하면 실행되는 코드

저 리스트 드랍다운버튼을 클릭하면 실행되는 코드 dataget이라는 data를 가지고 있는 클래스를 받는다( Define클래스를 통해 가져옴) 그런 뒤 listBox1.Item을 채워주면 밑에 목록들이 노출된다. 클릭할 때마다 해당하는 목록이 출력해주기 위해 클릭하는 목록들을 각각 0부터~인덱스를 매겼다.

두 번째 클릭

문제는 각 항목들을 처음 클릭 했을때 잘 노출이 되는데 전에 눌렀던 항목을 다시 클릭하면 리스트가 출력되지 않았다. 이유를 찾아보니 list.Clear()를  하면  생성자를 통해 static으로 새로운 객체를 만들어주고 있기 때문에, Define클래스에 가져오려던 리스트가 Clear가 되는 상황이다. 그리고 항목을 매번 클릭할 때마다 Define에서 받아 오는 것은 좋지 않다.

해결방법 : 

프로그램 시작 시 한번실행되는 함수

처음 시작되는 함수에서 항목들의 데이터를 갖고있는 클래스를 리스트로 받고

항목을 선택 할때 리스트를 접근하여 해당하는 데이터 클래스를 불러오도록 수정했다.

 느낀 점 :  정적클래스와 정적 데이터의 관하여 자주 실수하는 부분이 있기 때문에 개념을 확실히 잡고 메모리 관리에도 신경 쓰면서 작업을 해야겠다. 

반응형

문제점 : 빨간색 / 해결방법 : 파란색 / 느낀 점 : 녹색 

오류내용

동적으로 오브젝트를 생성하려고 하자 생기는 ArgumentException..

메시지 내용은   ArgumentException : 인스턴스 화하려는 것이 null입니다.
Unity Engine.Object.CheckNullArgument (System.Object arg,
System.String.Message)

찾아보니 인스터스화하려는 오브젝트 null이라고 한다.

GraphSerach.class

이 코드는 밑에 클래스에 함수를 호출하는 부분

Stackbox.class

이 코드는 호출을 불리는 코드이다. Awake에서 프리 팹 로드할 경로를 받고 StackPush( )를 호출하면 그~동안 계속 잘해왔던 프리 팹이 생성되어야 하는데.

GraphSerach.class

문제는 여기였다. 그냥 클래스 new 만 해주고 있었다. stackBox클래스를 가지고있는 오브젝트를 가지고 있던가 새로운 오브젝트에 그 클래스를 추가하던가 해줘야지 클래스에 있는 함수를 호출할 수 있다.

 

느낀 점 : 너무 기초적인 오류였다. 생각해보면 당연한 거고 어려운 부분도 아니다. 하지만 이런 자잘한 오류인데 이유를 모르고  있다면 시간을 꽤 잡아먹을 수 있다 생각이 든다. 다시 안 하기 위해 작성했다.

반응형

인접 행렬법

단점 : 메모리낭비 그래프의 정점의 개수를 V라고 하면 V * V행렬을 이용하여 표현한다. Vi가 행렬 i행과 i열에 대응된다고 할 때 만일 Vi와 Vj간의 간선이 있을 경우 [i,j]와 [j,i]요소를 1로 하고, 아닌 경우는 0으로 한다.

 

인접 리스트법

단순 연결리스트를 이용하여 각 정점에 간선으로 연결된 정점들을 주렁주렁 달아놓는 방법을 말한다. 인접행렬법과 대조적으로 인접리스트법에서는 그래프를 반사적으로 구성하기 위해 명시적으로 정보를 저장하지 않는다. 모든 간선에 대한 정보를 저장하지는 않는다. 정점에서 가능한 필요한 간선만 기록하게 된다.

 

탐색

우선탐색(DFS)과 너비 우선 탐색(Breadth First Search,BFS)방법이 있다. 나무와 다르게 그래프는 방향성이 없기 때문에 순서가 매번 다르다.

인접행렬의 깊이 우선 탐색

시작 정점에서 시작하여 그 정점과 연결된 정점으로 다음에는 그 정점에서 다시 연결된 정점의 순으로 진행된다.(당연히 방문한 정점은 다시 방문하지 않는다)

=> 탐색의 위치가 간선을 따라 깊이 들어가면서 움직인다.

비재귀

스택을 사용, 유일한 순회 순서가 존재하지 않음

인접 리스트의 깊이 우선 탐색

정점의 연결 상태를 알아내는 방법이 인접행렬과 다르다. 인접리스트로 그래프를 구현할 경우에는 순회 순서가 간선의 입력 순서에 민감하다.

먼저 입력된 간선이 각 리스트에서 앞에 위치하게 된다.

방문하지 않은 모든 요소를 탐색 ver

 

인접 행렬의 너비 우선탐색

깊이 우선 탐색과 대조적으로 우선 시작하는 정점과 연결된 정점을 탐색하고 다시 시작 정점의 다른 연결된 정점을 찾는 순으로 탐색한다.  트리순회의 레벨순회와 비슷하다고 생각하면 된다.

그래프의 불규칙성과 여러 개의 연결 요소로 구성된 다는 점을 고려해야 하므로 방문한 정점에 대한 체크가 필요하다. 재귀 호출 부분은 하나의 연결 요소만을 탐색하게 되므로 탐색 부분의 바깥에서 각 연결 요소의 시작 정점을 찾아내어 탐색을 시켜주는 부분이 필요하다.

인접리스트의 너비 우선 탐색

 

학습참고 : c로배우는 알고리즘

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

문제

중복된 문자를 개수를 파악해서 문자와 같이 표기해준다. 중복된 문자가 없을 경우 문자만 출력해야 한다.

풀이 : 내가 작성한 코드

어려운 문제는 아닌데 문자열 string을 char로 받아 현재 문자와 다음 문자의 중복 여부를 확인한 뒤 반복문으로 확인했다. 문제는 s [i+1]로 확인하려다 보니 다음 인덱스의 범위가 벗어나서 오류가 떴다. 원래는 while문을 (s[i] == s[i+1])로 했었는데 배열의 길이를 확인하는 것으로 바꿨다. 역시 if, else가 너무 많다. 

풀이 : 다른 사람이 작성한 코드

삼항 연산자를 사용해서 if, else 문도 적고 foreach를 사용하면 나처럼 인덱스 범위를 벗어나는 경우를 체크할 필요가 없었다.  알고리즘 문제를 풀 때 좀 더 여러 방법으로 접근하는 습관을 길러야겠다.

문제 : https://codesignal.com/

반응형

트리 알고리즘을 공부하다 보니까 

공부한것을 이용해 보고싶다는 생각이 들었다.

그래서 유니티로 트리구조를 가시적으로 보이도록 구현해봤다.

이진트리와 AVL 트리를 구현했다.

 

둘다 기본적인 구조는 이진트리이다.

삽입된 노드는 root노드부터 비교하면서 자신의 값보다 현재

위치한 노드가 크면 왼쪽 삽입된 노드가 크면 오른쪽으로 이동한다. 

바이너리(이진)트리

 

이진트리. 삽입/ 찾기

 

 

 AVL 트리

트리의 균형도가 절대 값1이 넘어 갈 경우 자동으로 균형 회전을 하도록 구현했다.

avl트리 LL회전

 

AVL트리 RR회전

콘솔로만 구현하기는 인터넷에도 많고 구현도 잘되어 있다.  트리구조에 따라 UI오브젝트도 움직이는 이려면 추가적으로 자료구조 구현이 필요하다.

사실 실제 데이터가 움직이는 트리구조와 이미지박스가 움직이는 것은 아예 상관이 없이 움직인다고 생각하면 된다. 별도로 움직여야 한다.

 

내가 구현한 코드에 노드는 Key는 int비교를 하기 위한 변수로 사용하고

Value는 오브젝트를 움직이기 위한 변수를 같이 담고 있다. (키 값을 통해 오브젝트를 불러오기 위함)

먼저 오브젝트의 위치를 움직여주고 그 다음에  트리구조에 데이터 구조를 변경하도록 한다.

반응형

그래프 알고리즘

 

그래프는 정점과 간섭의 집합이다.

정점 :  일반적으로 이름을 가지는 원으로 표시 ( 0 ,1 ,2, 3...)

간섭 : 두 정점간을 연결하는 선으로 표현 (0과1을 이어주는 선,1과 4를 이어주는 선...)

정점의 위치는 의미가 없고, 정점간의 연결 상태만이 중요하다.

경로 : 정점x로부터 정점y에 이르는 간선으로 연결된 정점들의 순서 집합이다.

단순경로 : 처음 정점 외에 중복된 정점이 없는 경우를 의미( 그래프 G1에서 정점 A에서 정점 C까지의 경로 중 (A-B-C)는 단순 경로이고 A-B-D-A-B-C는 단순 경로가 아니다)

회로(cycle) :  첫 정점과 끝 정점이 같은 경우 (G1에서 A-B-C-D-A)

위키 백과 : 신장 부분 나무 그래프

신장 나무 : 어떤 그래프의 부분 그래프로서 정점의 집합V는 원래의 그래프와 같은 나무 구조를 말한다. 즉 회로(cycle)가 없는 그래프

나무구조는 정점이 v개일 경우 간선은 v-1개 정점개수가 v라면 트리구조일 수 가 없다 => 회로가 존재

위키 백과 : 무방향

무향 그래프 : 간선의 방향성이 없는 그래프

위키 백과 : 방향 그래프

방향 그래프 : 간선의 방향성이 있는 그래프

위키 백과 : 가중/네트워크

가중 그래프 : 간선의 방향성과 가중치까지 표현한 그래프

네트워크 : 가중 그래프이면서 방향 그래프 인것

정점에 이어진 간선의 수로 차수를 결정한다. 무향 그래프일 경우 단순하게 차수라 할 수 있지만 방향이 있는 방향 그래프인 경우는 나가는 선과 들어오는 선을 구분 할 필요가 있다.

외차수 : 정점으로 부터 나가는 간선의 수 ( 정점 V1에 e2,e3)

내차수 : 정점으로 들어오는 간선의 수 (정점 V1에 e1,e5)

학습 참고
1) c로배우는 알고리즘 
2) https://ko.khanacademy.org/computing/computer-science/algorithms/graph-representation/a/representing-graphs
3) https://m.blog.naver.com/PostView.nhn?blogId=k97b1114&logNo=140163248655&proxyReferer=https%3A%2F%2Fwww.google.com%2F

 

반응형

문제

MAC-48 주소를 표준 (IEEE 802) 형식은 하이픈으로 구분 된 2 개의 16 진수 숫자 (0 ~ 9 또는 A ~ F)의 6 개 그룹입니다 (예 : 01-23-45-67-89- AB).

 

풀이 : 내가 작성한 코드

하이픈 '-'을 기준으로 문자가 16진수로 변환했을 때 'F'를 넘어서는 안된다. (대소문자 다름'F'!='f')

'-'사이로 문자가 2개가 있어야 한다.

이 정도 조건문을 가지고 실행했을 경우 생각하지 못한 조건들이 있었다. 

1) '-'개수가 5개가 아닌 경우  ex) '-'하이픈이 아예 없을 경우에도 true를 반환 할 것이다. 

2) 문자열의 길이가 17이 아닌 경우  ex) "-----" 위 조건들만 있을 경우 이 하이픈만 있는 문자열도 true를 반환 할 것이다. 

첫 번째 if문 17개가 아닐경우를 체크한다.

마지막 return문에서 삼항연산자로 '-'이 6이상,0일때 체크해주고있다. (1번조건)

 

풀이 : 다른 사람이 작성 한 코드

string[ ] l = s.Split('-') : '-'을 기준으로 제외한 문자열을 배열에 담는다. ex) "00-1B-63-84-45-E6" => {00, 1B ,63 ,84 ,45 ,E6}

if(l.Length !=6 ) : '-'을 제외한 문자열의 길이가 6이 아니면 false

if (!(c.Length == 2 && ((c[i] >= '0' && c[i] <= '9') || (c[i] >= 'A' && c[i] <= 'F')))) : 배열의 요소인 문자열의 길이가 2이어야 하고, 0보다 같거나 크고 9보다 같거나 작거나 또는 A,F마찬가지로 비교한다. 

 

느낀점 : string.Split로 '-'를 없애면서 첫 번째 문자열의 길이를 체크하는if문을 없애고, 그 없앤 문자열을 가지고 비교를 좀 더 간단하게 비교가 가능해졌다.  if else가 많이 줄었다. 

반응형

알고리즘을 공부하던중 재미있는 알고리즘을 발견해서 공부해보았다.

그것은 허프만 알고리즘.

 

허프만 알고리즘 Huffman

 

사용하는 빈도수의 따라 bit를 할당

자주쓰이는 문자에 가장 작은 bit를 할당

 

예를들어

HAN HA

이라는 문자열을 받으면

가장 많이 사용된 ‘H’에 0이라는 1bit를 부여하고

A에게 10, N에는 11을 할당한다.

(0)(10)(11) (0)(10)

 

당연히 중복된 문자가 많기 때문에 용량이 클수록 압축률은 올라간다.

 

코드부분

FileStream 부분

.txt 파일을 읽어 드리는 FileStream부분이다.

Header h = Compressor.Compress(bytes); 압축과정을 거친 후

 

h.Write(bf); 출력

압축과정

딕셔너리에 추가하면서 문자중복이라면 nVal(빈도수 )을 증가 시킨다.

 

노드를 만들어주는 과정 노드 빈도수의 합을 가지고 트리구조를 만듬

코드할당 부분 (01010) 왼쪽은 '0' 오른쪽 '1'

 

출력 코드 부분은 생략

 

보헤미안 랩소리 노래 앞부분을 txt파일에 넣음

 

빈도 수

파일용량 3KB -> 2KB

 

사실 노래앞부분만 넣었을 경우 내용이 짧기 때문 압축이 되지 않았다. 

같은 문자를 여러번 복사해야 헤더가 물고있는? 문자들이 많이지기 때문에 압축률이 올라간다.

반응형

문제

'@'문자 이후에 문자들을 출력하는 문제이다.

처음 '@'나온 이후부터 구조체에 넣어서 출력하면 될 줄 알았는데

위 테스트 문제처럼 '@'가 여러개인 경우도 있다.

풀이 : 내가 작성한 코드

.

for문을 통해 '@'문자가 나온 후 그 이후에 문자들을 문자열 s에 넣는다.

그런 뒤 한번더 '@'문자가 나올 경우를 체크하고 만약 '@'가 또 나온다면 s 문자열을 비우고

다시 '@'이후 문자 들을 담는다.

풀이 : 다른 사람 코드

게임개발에는 사용하기 힘들지만 강력한 기능 LinQ.

Split('@').Last()로 한번에 구할 수가 있었다.

  

반응형

문제

bishop이 pawn을 대각선으로만 이동해서 잡을수 있다.

잡을 수 있으면 true / 못 잡으면 false

풀이 : 내가 작성한 코드

(bishop[0] + bishop[1]) % 2 == (pawn[0] + pawn[1]) % 2 :

문자열의 알파벳과 숫자의 합이 짝수 이거나 홀수로 두 문자열이 같아야한다.(홀이거나 짝수)

bishop[0] != pawn[0]문자 앞 알파벳이 같으면 대각선이 아니므로 체크

 

풀이 : 다른 사람이 작성한 코드

알파벳끼리 빼고 숫자끼리 뺀값은 결국 대각선으로 증감되는 값이 나온다. 

ex )

(a1,b2) : (a-b)==(1-2)

(a1,c3) : (a-c)==(1-3)

....

반응형

문제

문자열을 받고 그 문자열에 연속된 숫자를 출력하는 문제이다. 

처음 문자가 비었다면 return : Empty

풀이 : 내가 작성한 코드

if(inputString.Length==0) : 문자열이 없을 때 비어있는 문자열 리턴

if(char.IsDigit(val) : 숫자인지 체크하고 숫자가 아닐 경우 break로 반복문 빠져나온다.

ss += val : 숫자일경우 문자열을 완성시킨다. 

풀이 : 다른 사람 코드

if( c.Equal("  ") || !Char.IsNumber(c))  : 첫문자열이 비어있거나, 숫자가 아니면 return

반응형

문제

'abcdc'를 뒤집어도 똑같은 문자열이 나오는 최소조건을 만드는 문제이다.

최소조건이란 최대한 적은 문자를 사용하라는 말이다.

 

풀이

처음에 문자열을 맨앞과 맨뒤를 비교하면서 같으면 넘어가고 다를 경우 기존 문자열에 추가하면 될거라고

생각했지만 하나의 문자열의 같은 문자가 반복되는 경우가 있기 때문에 정답이 될 수 없었다. 

다른 자료구조가 필요했다.

 

int pos : 문자열의 역순으로 들어갈 인덱스번호(pos번째까지)

int Length = st.Length;  :  문자열의 길이

 

예로 'abcdc'를 입력한다고 하자

if(st[iif (st[i] != st[j]) : 

{

 i = ++pos;
 j = Length - 1;

}

문자열의 맨앞과 맨뒤를 비교해서

다를 경우 맨앞의 문자열의 인덱스( pos증가 )를 한 칸 이동한다.

계속 해서 i를 증가시켜 맨 뒤 문자와 비교하다가 같은 문자가 나오면

맨 뒤를 가리키는 인덱스도 앞으로 이동해준다.

앞 뒤 문자가 같다는 말은 뒤집었을때 최소조건이 될 수도 있다는 말이다.

 

여기서 for문 조건을 통해 i가 h를 넘었다면 반복문을 종료한다.

하지만 종료조건이 아니라면 계속해서 내가 처음 생각했던 구조처럼

같은 문자가 반복되는 경우가 있기 때문에 계속 비교를 이어나가면 된다.

 

입력받은 문자열에 앞에서 부터 pos번째까지가 뒤집었을때 최소조건을 충족하는 문자들이 된다.

 

 

 

 

 

 

반응형

AVL나무

왼쪽 작은 나무의 높이와 오른쪽 작은 나무의 높이가 같거나 하나 차이나는 나무를 말한다.

AVL나무의 각 노드는 균형도라는 수치를 가지고 있는데 이는 왼쪽 작은 나무의 높이에 오른쪽 작은 나무의 높이를 뺀 값을 의미하며, 이 값의 절대 값이 클수록 나무 모양이 불균형하다는 뜻이 된다.

 

결국 AVL트리는 이진 검색트리이면서 동시에 균형을 유지하고 있는데, 균형이란 왼쪽과 오른쪽 높이의 차이가 1이하인 상태이다. (-1, 0 ,1)

 

이런 균형적인 구조를 지켜야 검색 시의 효율성을 보장할 수 있기 때문이다.

그림 첫번째 구조는 균형, 두 번째 구조는 불 균형

 

위에서 설명한대로 

[균형도 = 왼쪽노드 레벨 - 오른쪽 노드 레벨]

식으로 계산하여 균형도는 절대값이 0과 1사이에 이어야 한다.

 

두 번째 그림처럼 균형이 무너진 유형중 하나인 LL구조이다.

AVL 불균형 구조는 회전방향과 회전 횟수에 따라 4가지로 구분된다.

 

1. LL : 균형도가 2인 경우

★은 문제가되는(불균형) 노드

 

2. RR : 균형도가 -2인 경우

LL반대로 코드는 생략

3. RL :

 

4. LR

★은 문제가되는(불균형) 노드

 

 

반응형

문제

정수 k에 따라 배열에 연속된 요소들의 합이 가장 큰 값을 출력하는 문제이다.

예를 들어 배열 [2,3,5,1,6] 일 때 k가 2일 경우 3+5=8 이 가장 크다. 

 

 

 

풀이 : 내가 작성한 코드

for(int i=0; i<inputArray.Length-k+1; i++) :

배열의 길이 - k +1인 이유는 아래 sum에 K만큼 연속된 요소를 더하기 위함이다. 

 

for(int j=i; j<k+i; j++) :

k+j로 요소길이 만큼 범위를 변경해준다,

 

풀이 : 다른 사람 코드

for(var i=0; i< k; ++i) : 처음 0부터 k번째까지의 요소의 합

Math.Max(maxSum, currentSum) 0이상 수중 큰 수를 리턴(if문을 안 씀)

for(var i=k; i <inputArray.Lenght; ++i) : k만큼의 요소를 더하는데 

배열 [2, 4, 10, 1] k가 2일 때 

currentSum += inputArray[i] - inputArray[i-k]; :

inputArray[0] + inputArray[1] += inputArray[2] - inputArray[0] 

inputArray[1] + inputArray[2]

 6 += 8   = 14 (두 번째 k길이 만큼의 요소합)

이렇게 이미 currentSum에서 전에 더한 요소가 있기 때문에 그것을 제외한 다음요소만

더해서 다음 k번째 길이만큼의 요소의 합을 구해준다.

 

내가 작성한 코드보다 연산횟수가 적다.

배열의 길이가 4, k가 2일 때 

내가 작성한 코드보다 for문을 5번더 적게 돈다.

 

 

반응형

이분검색

이미 정렬된 배열에 대해서 검색하는 알고리즘이다. 순차 검색과 달리 자료를 정렬이라는 방법으로 조직한다. 그래서 검색은 간단하지만 자료를 삽입하거나 삭제할 때는 자료의 구조를 깨뜨리지 않아야 하는 어려움이 있다.

 

이분검색방법

  1. 자료의 집합은 크기순으로 정렬되어 있어야한다.

  2. 이미 정렬된 자료 집합에 대해 이분 검색법은 자료의 중간값을 우선 검사한다. 이 자료의 중간값이 찾는 키값이 아니라면 중간값과 키값의 크기를 비교하여 왼쪽 구간이나 오른쪽 구간을 선택한다.

  3. 그리고 그 구간에 대해서 똑같은 방법으로 중간값과 키값의 크기를 비교한다.

검색

[탐색 방법]

① 구간의 중간값을 구한다.

② if(중간값 < 키값) 오른쪽 구간또는 왼쪽 구간을 선택한다.

삽입

 

[삽입 방법]

① key가 들어갈 위치를 찾는다.

② 삽입할 공간을 만든다

③ 공간에 자료를 삽입하고 자료수를 증가시킨다.

 

삭제방법은

순차검색알고리즘 삭제방법과 동일


이분 검색은 삽입과 삭제의 어려움 때문에 삽입과 삭제가 적은 거의 고정적인 자료집합에 유리하다.

반응형

+ Recent posts