명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다. 다양한 모양과 크기의 명함들을 모두 수납할 수 있으면서, 작아서 들고 다니기 편한 지갑을 만들어야 합니다. 이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다.
아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.
명함 번호 | 가로 길이 | 세로 길이 |
---|---|---|
1 | 60 | 50 |
2 | 30 | 70 |
3 | 60 | 30 |
4 | 80 | 40 |
가장 긴 가로 길이와 세로 길이가 각각 80, 70이기 때문에 80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할 수 있습니다. 하지만 2번 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로 모든 명함들을 수납할 수 있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.
모든 명함의 가로 길이와 세로 길이를 나타내는 2차원 배열 sizes가 매개변수로 주어집니다. 모든 명함을 수납할 수 있는 가장 작은 지갑을 만들 때, 지갑의 크기를 return 하도록 solution 함수를 완성해주세요.
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution
{
public int solution(int[,] sizes)
{
int answer = 0;
List<int> list1 = new List<int>();
List<int> list2 = new List<int>();
for (int i = 0; i < sizes.GetLength(0); i++)
{
for (int j = 0; j < sizes.GetLength(1); j++)
{
if (sizes[i, j] > sizes[i, j + 1])
{
list1.Add(sizes[i, j]);
list2.Add(sizes[i, j + 1]);
break;
}
else
{
list2.Add(sizes[i, j]);
list1.Add(sizes[i, j + 1]);
break;
}
}
}
int max = list1.Max();
int min = list2.Max();
answer += max * min;
return answer;
}
}
문제 설명은 좀 복잡하게 해뒀지만 결국은 2차원 배열을 내림차순이든 오름차순이든 정렬을 한 뒤 그 중 가장 큰 값 둘을 곱해주면 된다.
크기 비교 후 두 List에 값을 저장하고 List.Max() 메서드로 최대값을 추출하여 풀었다.
필요한 사항
1. 위의 사항을 점검하고 알맞게 두 스크립트의 수정이 필요해 보인다.
1. FSM에 맞게 강의에 따라 우선 구현을 시도한다.
2. 정상적으로 무기 공격이 동작한다면 상태이상 시스템을 적용해 본다. 요건 나중에
https://teamsparta.notion.site/231211-4c21f35ab2dc494eb063a324a94e54de
Player가 공격할 시 Monster에게 Knockback을 적용시키자. 2트
TwinDagger가 오른손에 쥐어졌을 때 이슈를 해결하자. 2트
Weapon.cs
private void OnTriggerEnter(Collider other)
{
if (other.GetComponent<Rigidbody>().isKinematic == true)
// isKinematic이 꺼지고 켜지면서 충돌이 두 번 발생하는 것을 배제한다.
{
return;
}
Attack(other.GetComponent<IHit>());
}
Weapon에서 isKinematic이 켜고 꺼지면서 피격이 두 번 되던 이슈를 조건문으로 한 번 필터를 하는 방식으로 구현하였다. console창에 보면 피격이 한 번 발생하는 것을 볼 수 있다.
ToolSystem.cs
public Transform leftHandPosition;
// TwinTool의 왼 손 도구를 저장할 컬렉션을 만든다.
private Dictionary<string, GameObject> _twinTools = new Dictionary<string, GameObject>();
private void Awake()
{
var twinTools = Managers.Resource.GetCacheGroup<GameObject>("Handable_L_");
// TwinTool의 왼 손 도구를 새로운 컬렉션에 저장한다.
foreach (var tool in twinTools)
{
var go = UnityEngine.Object.Instantiate(tool, leftHandPosition);
go.SetActive(false);
_twinTools.TryAdd(tool.name, go);
}
}
private void EquipTool(ItemSlot itemSlot)
{
ItemInUse = itemSlot;
// 아이템이 장착될 때 이름 중 Twin이 들어간다면 플레이어의 왼 손에 있는 도구를 활성화한다.
if (itemSlot.itemData.name.Contains("Twin"))
{
var twinToolName = GetTwinToolLeftHandName(itemSlot);
if (twinToolName.Contains("Handable_L_") == true)
{
_twinTools[twinToolName].SetActive(true);
}
}
ItemObject = _tools[toolName];
}
public void UnEquip(int part)
{
if (Equipments[part].itemSlot.itemData.name.Contains("Twin"))
{
var twinToolName = GetTwinToolLeftHandName(Equipments[part].itemSlot);
if (twinToolName.Contains("Handable_L_") == true)
{
_twinTools[twinToolName].SetActive(false);
}
}
}
public string GetTwinToolLeftHandName(ItemSlot itemSlot)
// TwinTool의 왼 손 도구의 이름을 재정의한다.
{
return "Handable_L_" + itemSlot.itemData.name.Replace("ItemData", "");
}
기존의 TwinDagger를 자식으로 가지던 프리팹을 삭제하고 왼쪽, 오른쪽 둘을 프리팹화 시켰다.
그 뒤에 기본이 되는 오른쪽 단검은 Handable_TwinDagger, 왼쪽은 Handable_L_TwinDagger로 명명하여 코드에서 처리를 한다. 이유는 추후에 새로운 두 손 도구가 추가되었을 경우 코드 수정 없이 사용하기 위함이다.
PlayerGroundedState.cs
protected override void AddInputActionsCallbacks()
{
base.AddInputActionsCallbacks();
Managers.Game.Player.ToolSystem.OnEquip += OnEquipTypeOfTool;
Managers.Game.Player.ToolSystem.OnUnEquip += OnUnEquipTypeOfTool;
}
protected override void RemoveInputActionsCallbacks()
{
base.RemoveInputActionsCallbacks();
Managers.Game.Player.ToolSystem.OnEquip -= OnEquipTypeOfTool;
Managers.Game.Player.ToolSystem.OnUnEquip -= OnUnEquipTypeOfTool;
}
protected virtual void OnEquipTypeOfTool(QuickSlot quickSlot)
{
// QuickSlot에 저장된 ItemData 값을 매개 변수로 받아서 TwoHandedTool에 저장
ItemData equippedItemData = quickSlot.itemSlot.itemData;
// ItemData에 종속된 class ToolItemData에 bool isTwoHandedTool 변수를 참조하기 위하여 형변환
ToolItemData equippedToolItemDate = (ToolItemData)equippedItemData;
// ToolSystem의 event OnEquip에 구독하여 아래의 조건문을 이용하여 애니메이션을 켜고 끈다.
if (equippedToolItemDate.isWeapon == true && equippedToolItemDate.isTwoHandedTool == true)
{
_stateMachine.ChangeState(_stateMachine.TwoHandedToolIdleState);
Debug.Log("두 손 도구애니메이션 시작");
}
else if (equippedToolItemDate.isWeapon == true && equippedToolItemDate.isTwinTool == true)
{
_stateMachine.ChangeState(_stateMachine.TwinToolIdleState);
Debug.Log("한 쌍 도구 애니메이션 시작");
}
else
{
_stateMachine.ChangeState(_stateMachine.IdleState);
}
}
관련된 이슈로 OnEquipTypeOfTool() 메서드 내부의 디버그 로그가 여러번 호출되는 이슈가 있었는데, 메서드 구독을 GroundedState의 생성자 부분에서 하다 보니 연결된 State에서 전부 구독이 실행되는 이슈였다. 준욱님이 InputActionsCallbacks()으로 구독 위치를 옮겨 주셔서 해결하였다.
도구를 장착한 상태에서 퀵슬롯의 맨 손을 선택했을 시 IdleAnimation이 바뀌지 않는 이슈가 있었고 OnUnEquip에도 메서드를 구독해주어 해결하였다. 이건 진영님의 마법.
넉백 시스템을 수정하였습니다.
ItemObjectData.cs를 삭제하였습니다.
퀵슬롯에서 맨 손 선택 시 Idle 애니메이션이 바뀌지 않는 이슈를 수정하였습니다.
두 손 도구를 창착했을 때의 이슈를 해결하였습니다.
두 손 도구 장착 이슈를 해결해서 참 다행이라는 생각이 든다. 비록 시간이 너무 많이 소요가 되었지만 . . . 아직 부족한 점도 많지만 . . . 더 노력해야겠다는 생각을 해본다.