어떤 미로에 갇혔을 때, 오른쪽 벽에 손을 대고 계속 가다보면 출구를 찾을 수 있다는 개념이다.
사실, 최단거리를 찾아주는 것도 아니고 그냥 길을 가는 알고리즘이라고 볼 수 있다.
이전에 했던 플레이어 임의의 이동에서 바꿀 것이다.
이전에 했던 플레이어 임의의 이동링크
class Board
{
const char CIRCLE = '\u25cf';
public TileType[,] Tile { get; private set; }
public int Size { get; private set; }
public int DestY { get; private set; }
public int DestX { get; private set; }
Player _player;
public enum TileType
{
Empty,
Wall
}
public void Initialize(int size, Player player)
{
if(size % 2 == 0)
return;
Tile = new TileType[size,size];
_player = player;
Size = size;
DestY = Size - 2;
DestX = Size - 2;
GenerateBySideWinder(); // 이전 맵만들기 참조
}
public void Render()
{
ConsoleColor prevColor = Console.ForegroundColor;
for(int y = 0; y < Size; y++)
{
for(int x = 0; x < Size; x++)
{
if(y == _player.PosY && x == _player.PosX) //플레이어좌표 파란색
{
Console.ForegroundColor = ConsoleColor.Blue;
}
else if( y == DestY && x == DestX) //목적지좌표 노란색
{
Console.ForegroundColor = ConsoleColor.Yellow;
}
else
{
Console.ForegroundColor = GetTileColor(Tile[y,x]);
}
Console.Write(CIRCLE);
}
Console.WriteLine();
}
Console.ForegroundColor = prevColor;
}
public ConsoleColor GetTileColor(TileType type)
{
switch(type)
{
case TileType.Empty:
return ConsoleColor.Green;
case TileType.Wall:
return ConsoleColor.Red;
default:
return ConsoleColor.Green;
}
}
}
이전 플레이어 임의의 이동에서 목적지 좌표를 Player 에서 Board로 옮겨 주었다.
목적지 좌표를 노란색으로 표시
class Pos
{
public Pos(int y,int x) { Y = y; X = x;}
public int Y;
public int X;
}
class Player
{
public int PosY{ get; private set; }
public int PosX{ get; private set; }
Random _random = new Random();
Board _board;
enum Dir // 내가 바라보는 방향
{ //반시계방향
Up = 0,
Left = 1,
Down = 2,
Right = 3
}
int _dir = (int)Dir.Up; // (int를 쓰는 이유)방향을 계산할때 용이함
//기본 위치 추가
List<Pos> _points = new List<Pos>();
public void Initialize(int PosY,int PosX,Board board)
{
PosY = posY;
PosX = posX;
_board = board;
//현재 바라보는 방향을 기준으로 좌표 변화
int[] frontY = new int[] { -1, 0, 1, 0};
int[] frontX = new int[] { 0, -1, 0, 1};
//right축{위 왼쪽 아래 오른쪽} 바라보는 방향으로부터 오른쪽방향의 좌표 변화
int[] rightY = new int[] { 0, -1, 0, 1};
int[] rightX = new int[] { 1, 0, -1, 0};
_points.Add(new Pos(PosY,PosX));
//목적지 좌표에 도착할 때까지 실행
while(PosY != board.DestY || PosX != board.DestX)
{
if(_board.Tile[PosY + rightY[_dir], PosX + rightX[_dir] == Board.TileType.Empty)
{
//1.오른쪽으로 갈 수 있으니 오른쪽으로 90도 회전
_dir = (_dir - 1 + 4 ) % 4;
//한칸 전진
PosY = PosY + frontY[_dir];
PosX = PosX + frontX[_dir];
_points.Add(new Pos(PosY,PosX));
}
else if(_board.Tile[PosY + frontY[_dir], PosX + frontX[_dir] == Board.TileType.Empty)
{
//2.현재 바라보는 방향을 기준으로 전진할 수 있으면 한칸 전진
PosY = PosY + frontY[_dir];
PosX = PosX + frontX[_dir];
_points.Add(new Pos(PosY,PosX));
}
else
{
//3.오른쪽도 못가고 앞으로도 못가니 //왼쪽으로 90도 회전
_dir = (_dir + 1 + 4 ) % 4;
}
}
}
const int MOVE_TICK = 100;
int _sumTick = 0;
int _lastTick = 0;
public void Update(int deltaTick)
{
_sumTick += deltaTick;
if(_sumTick >= MOVE_TICK)
{
if(_lastTick >= _points.Count)
return;
_sumTick = 0;
PosY = _points[_lastIndex].Y;
PosX = _points[_lastIndex].X;
_lastIndex++;
}
}
}
Update 로직은 Initialize에서 목적지좌표에 도착할 때까지 y,x좌표를 List에 저장하여 하나씩 꺼내어 업데이트 해주는 방식으로 바꿔 주었다.
Intialize를 보면,
방향을 열거형으로 하여 오른쪽으로 갈수 있으면 오른쪽으로 90도 회전 후 앞으로 전진
_dir = (_dir - 1 + 4 ) % 4;
실제 계산을 해보면 Up 은 (Up(0) - 1 + 4 ) % 4 = 3 이 나오므로 Right가 제대로 나온다.
그리고 앞으로 전진은 frontY 와 frontX 의 int배열로 처리하였는데
enum Dir 바라보는 방향
{
Up,
Left,
Down,
Right
}
을 기준으로
frontY를 살펴보면
frontX를 살펴보면
rightY를 살펴보면
rightX를 살펴보면
이렇게 정리해서 배열로 만들 수 있다.
int[] frontY = new int[] { -1, 0, 1, 0 }
int[] frontX = new int[] { 0, -1, 0, 1 }
int[] rightY = new int[] { 0, -1, 0, 1 }
int[] rightX = new int[] { 1, 0, -1, 0 }
class Pos
{
public Pos(int y,int x){Y = y; X = x;}
public int Y;
public int X;
}
List를 생성하여 목적지 좌표까지 y,x좌표를 저장하고
Update를 통해 y,x좌표를 갱신하고 메인함수에서 렌더링하여 사용한다.
그 결과,
마지막 목적지까지 파란색원이 도착한것을 볼 수 있다.