본문 바로가기

유니티와 놀기

체스말을 잡기

 저번에 만든 것으로 폰부터 퀸까지의 말을 만들고 배치했다.

 

 

 다음으로 말을 잡는 법을 만들어보자. 지금까지 기능으로는 상대의 말이 내 경로에 있을 경우 자신의 말과 구분하지 못하고 막혀버린다. 그리고 폰의 경우 앞으로 전진하고 대각선으로 잡는 독특한 행마법을 가지고 있어서 행마처리를 일관적으로 만들기 어렵다. 그래서 보드에 해당칸이 비어있는지를 알려주는 IsCoordAvailable()에 더불어 해당 칸이 잡을 수 있는 칸인지를 알려주는 IsCoordCatchable()을 추가하고, 이동 가능한 칸을 계산하는 MoveableCoord()에서 말마다 각각 계산하기로 했다.

 

 퀸, 룩, 비숍은 이동 가능한 방향으로 나아가면서 막혀있는지 확인한다. 막혀있으면 잡을 수 있는 칸인지 확인하고 다음 방향으로 넘어간다.

 

public class Queen : PlayerMoveableChessman
{
    private static readonly Vector2Int[] directions = new Vector2Int[]
    {
        new Vector2Int(1, 0), new Vector2Int(1, -1), ...
    };

    public override List<Vector2Int> MoveableCoord()
    {
        List<Vector2Int> li = new List<Vector2Int>();
        foreach(Vector2Int direction in directions)
        {
            for (int i = 1; true; i++)
            {
                if (board.IsCoordAvailable(pos + direction * i))
                    li.Add(pos + direction * i);
                else
                {
                    if (board.IsCoordCatchable(pos + direction * i, color))
                        li.Add(pos + direction * i);
                    break;
                }
            }
        }
        return li;
    }
}

 

 나이트와 킹은 방향이 막힌다는 개념이 없으니 가능한 칸에 모두 이동 가능한지와 말을 잡을 수 있는지 확인한다.

 

public class Knight : PlayerMoveableChessman
{
    private static readonly Vector2Int[] direction = new Vector2Int[]
    {
        new Vector2Int(-1, 2), new Vector2Int(1, 2), ...
    };

    public override List<Vector2Int> MoveableCoord()
    {
        List<Vector2Int> li = new List<Vector2Int>();
        foreach (Vector2Int coord in direction)
            if (board.IsCoordAvailable(pos + coord) || board.IsCoordCatchable(pos + coord, color))
                li.Add(pos + coord);
        return li;
    }
}

 

 폰은 흑과 백에 따라 방향을 결정하는 bool을 넣고, 2칸 전진이 가능한지 알기 위해 첫 위치를 저장한다. 그 다음 앞의 칸으로는 이동가능한지를 확인하고, 대각선 칸으로는 잡을 수 있는 칸인지를 확인한다.

 

public class Pawn : PlayerMoveableChessman
{
    public bool inverseDirection = false;
    private Vector2Int startPos;

    protected override void Start()
    {
        base.Start();
        startPos = pos;
    }

    public override List<Vector2Int> MoveableCoord()
    {
        Vector2Int direction = new Vector2Int(0, 1);
        if (inverseDirection)
            direction = new Vector2Int(0, -1);

        List<Vector2Int> li = new List<Vector2Int>();
        if (board.IsCoordAvailable(pos + direction))
            li.Add(pos + direction);
        if (startPos == pos && board.IsCoordAvailable(pos + direction * 2))
            li.Add(pos + direction * 2);

        if (board.IsCoordCatchable(pos + direction + Vector2Int.left, color))
            li.Add(pos + direction + Vector2Int.left);
        if (board.IsCoordCatchable(pos + direction + Vector2Int.right, color))
            li.Add(pos + direction + Vector2Int.right);

        return li;
    }
}

 

 

 이제 말은 자신의 말에 막히면서 상대말을 잡을 수 있다.

 

 마지막으로 실제 보드에서 말을 지우는 기능을 추가한다. 이 기능은 일단 말을 보드 위에 놓는 PlaceChessman()에 이동하려는 칸에 말이 있을 경우 해당말을 잡힘처리하게 만들었다. 잡힘처리 당한 말은 자신을 보드 위에서 내리고 게임 상에서 스스로 삭제한다.

 

// class Board
public bool PlaceChessman(Chessman chessman, Vector2Int pos)
{
    if (chessmans[pos.x, pos.y] != null)
        CatchChessman(pos);
    chessmans[pos.x, pos.y] = chessman;
    return true;
}

public bool CatchChessman(Vector2Int pos)
{ 
    if (chessmans[pos.x, pos.y] == null)
        return false;
    chessmans[pos.x, pos.y].Catched();
    return true;
}

 

// class Chessman
public void Catched()
{
    board.DeplaceChessman(pos);
    Destroy(gameObject);
}

 

 

<결과물>

 다음에는 체스의 특수규칙인 앙파상, 프로모션, 캐슬링을 만들어보겠다.

'유니티와 놀기' 카테고리의 다른 글

delegate 사용하기  (0) 2023.04.04
간단한 단색 그래픽 만들기  (0) 2023.03.05
코루틴 뒤에 코루틴을 실행시키기  (0) 2022.11.10
체스말을 움직이기  (0) 2022.11.01