내일배움캠프 게임개발(Unity) 사전캠프 16일차 TIL
사천성 만들기
1. 두 카드가 연결 가능한지 확인하기
두 카드가 같은 카드일 때 삭제되는 것을 구현했으니
이제 두 카드가 사천성 규칙에 따라 연결 가능한지 확인해야할 차례이다.
- 두 카드의 연결선이 3번 이상 꺾이면 안된다.
- 두 카드는 빈 공간에서만 연결된다.
분명 오늘 계획은 적절한 알고리즘을 이용해 구현을 하는 것이었지만
bfs, 다익스트라 등 아직 알고리즘에 익숙하지 않은 나에게 응용은 너무 큰 꿈이었다.
그래서 일단 구현에 초점을 맞추고 코드를 작성했다.
일단 구현의 편의성을 위해 CardManager를 GameManager와 합쳤다.
그리고 Start문에서 Shuffle한 카드들을 position에 따라 정렬했다.
그런 다음 각 카드마다 순서대로 number를 부여했다.
이 number로 카드가 어디에 위치해있는지 알아낼 것이다.
private void Start()
{
cardList = new List<GameObject>();
CreateCards();
ShuffleCards();
cardList = cardList.OrderBy(o => o.transform.position.y)
.ThenBy(o => o.transform.position.x)
.ToList();
for (int i = 0; i < cardList.Count; ++i)
cardList[i].GetComponent<Card>().cardNum = i;
}
연결될 수 있는 카드가 있는지 확인하는 IsCardConnected() 함수와 CheckCardConnectionRecursive()(재귀함수)를 구현했다. (미완성, 오류 많음)
bool IsCardConnected()
{
int turnCount = 0;
//Vector3 dir = secondCard.transform.position - firstCard.transform.position;
// first카드부터 출발해서 second카드까지
int dirNum = -1;
int tempCardNum = firstCard.GetComponent<Card>().cardNum;
bool[] visited = new bool[cardList.Count];
return CheckCardConnectionRecursive(turnCount, visited, tempCardNum, dirNum);
}
// 오른쪽에서 왼쪽은 되는데 왼쪽에서 오른쪽은 안됨
bool CheckCardConnectionRecursive(int turnCount, bool[] visited, int tempCardNum, int dirNum)
{
int[] dx = { 0, 0, -1, 1 };
int[] dy = { 1, -1, 0, 0 };
for (int i = 0; i < dx.Length; ++i)
{
int nx = tempCardNum % xCount + dx[i];
int ny = tempCardNum / yCount + dy[i];
tempCardNum = tempCardNum + dx[i] + (dy[i] * xCount);
if (tempCardNum < 0 || tempCardNum >= cardList.Count
|| nx < 0 || nx >= xCount
|| ny < 0 || ny >= yCount)
continue;
// 방향이 지금까지와 다르다면 ++turnCount
if (dirNum != i)
{
++turnCount;
if (turnCount > 3)
{
--turnCount;
continue;
}
dirNum = i;
}
// secondCard와 같은 자리라면 true
if (tempCardNum == secondCard.GetComponent<Card>().cardNum)
return true;
// 카드가 있는 자리라면
if (cardList[tempCardNum].activeSelf)
continue;
// 방문한 자리라면
if (visited[tempCardNum])
continue;
visited[tempCardNum] = true;
CheckCardConnectionRecursive(turnCount, visited, tempCardNum, dirNum);
}
return false;
}
재귀함수의 이름이 긴데, 뭐라 지어야할지 감이 안잡혀서 ChatGPT한테 물어봤다..
Update문에서 두 카드의 Sprite를 비교하는 부분에 IsCardConnected()함수를 조건으로 넣어줬다.
그리고 Destroy대신 SetActive(false)로 삭제된 것처럼 보이도록 했다.
if (firstCard.GetComponent<Card>().spriteNum
== secondCard.GetComponent<Card>().spriteNum
&& IsCardConnected())
{
firstCard.SetActive(false);
secondCard.SetActive(false);
firstCard = null;
secondCard = null;
}
지금 프로그램을 실행시키면 정말 느리고 잘 작동이 되지 않는다.
붙어있는 카드 중 오른쪽 카드를 먼저 클릭하고 왼쪽 카드를 클릭하면 카드가 잘 제거되지만 반대는 제거되지 않는다.
같은 맥락으로 위 -> 아래는 제거되지 않지만 아래->위는 제거된다.
그리고 떨어져 있는 카드도 제거되지 않는다.
내일 다시 손보는 걸로~
최적화도 게임이 완성되고 사전캠프 기간이 남으면 손봐야겠다.