안녕하세요. 로디소프트 대표 임세원입니다.
문제의 조건이 많고 상어의 움직임, 충돌 처리 등 고려할 사항이 많아 구현이 까다로운 문제입니다. 코드를 살펴보니 연결리스트를 이용해 컬럼별로 상어를 관리하는 독창적인 아이디어를 사용하셨네요. 하지만 아쉽게도 몇가지 논리적 오류가 있어 정상적으로 동작하지 않을 겁니다.
ChatGPT와 같은 AI가 종종 복잡한 시뮬레이션 문제에서 논리적 허점을 찾지 못하는 경우가 있습니다. 코드의 핵심 로직과 자료구조의 상호작용을 깊이 있게 파악해야 하기 때문이죠. 코드를 분석하며 문제점을 찾아보겠습니다.
코드의 주된 문제점은 상어 이동과 자료구조 관리 부분에 집중돼 있습니다.
1. 상어 이동 로직(moveAllShark)의 연결 리스트 순회 오류
가장 치명적인 문제입니다. moveAllShark 함수에서 연결 리스트를 순회하며 노드를 분리(separateNode)하고 재배치하는데 이 과정에서 순회 로직이 깨지게 됩니다.
separateNode(target, i)가 호출되면 target 노드는 기존 리스트와의 연결이 모두 끊어집니다. 즉 target->prev와 target->next는 모두 nullptr가 됩니다.
그런데도 불구하고 target = target->next; 코드가 실행되면 이미 nullptr가 된 target->next를 다음 target으로 삼으려고 시도합니다. 결국 while 루프는 두 번째 상어부터는 처리하지 못하고 종료됩니다.
next 변수에 미리 다음 노드를 저장해두셨으니 루프의 마지막에서 target = next;로 수정해야 합니다.
2. 상어의 동시 이동 시뮬레이션 오류
문제의 조건은 모든 상어가 동시에 이동한 후 같은 칸에 모인 상어들 중 가장 큰 상어만 살아남는 것입니다. 하지만 현재 코드는 한 마리의 상어를 이동시키고 바로 visit 배열(새로운 격자판)에 위치시키며 충돌 검사를 합니다.
이 방식은 상어를 어떤 순서로 이동시키는지에 따라 결과가 달라질 수 있습니다. 작은 상어가 먼저 이동해서 어떤 칸은 차지했는데 나중에 더 큰 상어가 같은 칸으로 이동하면 그제야 작은 상어가 잡아먹힙니다. 하지만 만약 큰 상어가 먼저 이동했다면 뒤늦게 온 작은 상어는 바로 잡아먹히겠죠. 동시이동이라는 규칙을 정확히 반영하지 못하게 됩니다.
해결책입니다.
- 모든 상어의 이동 후 위치를 임시 격자판에 기록합니다.
- 이 과정에서 만약 임시 격자판의 특정 칸에 이미 다른 상어가 있다면 크기를 비교해 더 큰 상어만 남깁니다.
- 모든 상어에 대한 계산이 끝나면 임시 격자판을 원래의 격자판으로 삼습니다.
3. 복잡한 상어 위치 계산 (moveShark)
벽에 부딪혔을 때 위치를 계산하는 현재 로직이 매우 복잡하고 오류가 발생할 가능성이 큽니다.
이런 수식은 경계 값이나 특정 상황에서 잘못된 위치를 계산하기 쉽습니다.
속력 % ((칸 수 - 1) * 2) 공식을 활용하면 더 간결하고 정확하게 구현할 수 있습니다. 위아래로 움직이는 상어는 (R-1)*2를 주기로 왕복 운동을 합니다. 이 점을 이용해 실제 이동해야 할 유효 거리를 계산하고 현재 위치와 방향을 기준으로 최종 위치와 방향을 결정하는게 좋습니다.
마지막 조언입니다.
성능 때문에 그리하셨는지는 모르겠지만 연결 리스트 대신에 2차원 배열 SHARK* board[101][101]을 사용해 각 칸의 상어 정보를 직접 관리하는게 훨씬 직관적이고 간단합니다. R, C, M 초기 정보를 입력받은 다음에 M개의 상어 정보를 SHARK* board[r][c]에 저장하는 것이죠. 이상의 자세한 풀이 방법은 질문자님의 몫으로 남겨두겠습니다.