C#/WinUI3

[WinUI3] 체스 게임 만들기(2) : 말 선택하기

말하는 닭 2023. 2. 10. 02:08

 

 

체스 말을 설정하고 선택 가능한지, 선택하는 것까지 만들 것입니다. 

 

말이 가질 공통적인 내용을 담은 클래스를 상속시킬 계획이기에, Piece를 하나 만들었습니다.

public class Piece {
    public Side Side { get; set; }
    public PieceType Type { get; set; }
}

//체스에 올려질 말 6종류를 모두 이렇게 만들어 놓는다
public class King : Piece {
    public King(Side side, PieceType type) {
        this.Side = side;
        this.Type = type;
    }
}

enum타입을 만들어 말의 정보를 담을 수 있게 하였습니다. 

public enum PieceType
{
    King, Queen, Bishop, Knight, Rook, Pawn
}

public enum Side
{
    White, Black
}

그리고 체스 말들을 담을 보드를 하나 만들어줬습니다.

public class Board {
    public Board(Grid board) {
        gridBoard = board;
        SetBoard();
        SetGrid(gridBoard);
    }

    public static Grid gridBoard;
    public static Piece[,] board = new Piece[8,8];

    SolidColorBrush hoverBrush = new SolidColorBrush(Color.FromArgb(255, 117, 123, 149));
    SolidColorBrush clickedBrush = new SolidColorBrush(Color.FromArgb(255, 232, 187, 63));
    
    //이전 글에 있던 그 SetGrid함수가 맞다. 전 글과는 달리 매개변수를 넣고 리턴 값을 없앴다.
    private void SetGrid(Grid board) {...}
}

 

그 다음에는 보드(배열)에 말을 배치합니다.

private void SetBoard() {
            board[0, 0] = new Rook(Side.White, PieceType.Rook);
            board[0, 1] = new Knight(Side.White, PieceType.Knight);
            board[0, 2] = new Bishop(Side.White, PieceType.Bishop);
            board[0, 3] = new Queen(Side.White, PieceType.Queen);
            board[0, 4] = new King(Side.White, PieceType.King);
            
            ....생략
}

 

캔버스에 마우스 커서가 올라갈 때, 나올 때 선택가능한 타일을 알려주기 위해, 혹은 클릭 시 선택되었음을 알려주기 위해 코드(PointerEntered, PointerExited, PointerPressed)를 추가해줍시다. 

//이 코드는 SetGrid안에 캔버스를 생성할 때의 코드임
Canvas canvas = new Canvas { Background = (i + j) % 2 == 0 ? evenBrush : oddBrush };

canvas.PointerEntered += (sender, e) => {
    if(Game.isSelected) {
        return;
    }

    Piece piece = GetBoardPiece((Canvas)sender);
    if(piece != null && piece.Side == Game.currentTurn) {
        canvas.Background = hoverBrush; 
    }
};

canvas.PointerExited += (sender, e) => {
    if(Game.isSelected) {
        return;
    }

    if(Utils.isOddTile((Canvas)sender)) {
        canvas.Background = oddBrush;
    }
    else {
        canvas.Background = evenBrush;
    }
};

canvas.PointerPressed += (sender, e) => {
    Piece piece = GetBoardPiece((Canvas)sender);

    if(piece == null) {
        if(Utils.isOddTile((Canvas)sender)) {
            canvas.Background = oddBrush;
        }
        else {
            canvas.Background = evenBrush;
        }
    }

    if(piece != null && piece.Side == Game.currentTurn) {
        canvas.Background = clickedBrush;
        Game.isClickedState = !Game.isClickedState;
    }
};

//아래의 코드는 Board클래스 안에 넣으면 됨
public Piece GetBoardPiece(Canvas tile) {
    return board[Grid.GetRow(tile), Grid.GetColumn(tile)];
}

Game클래스를 만들어 현재 어떤 플레이어의 턴인지, 선택된 상태인지를 알 수 있게 하였고,

Utils클래스를 만들어 몇몇 함수들을 담게 하였습니다. 

public class Game {
    public Game(Grid gridBoard) {
        board = new Board(gridBoard);
    }

    public static bool isSelected = false;
    public static Side currentTurn = Side.Black;

    private Board board;
}

 

 

! 체스판의 타일의 홀짝을 체크할 때 row값과 column값에 꼭 괄호를 씌워 우선순위를 맞출 것.

 안 하면 나누기 연산자가 먼저 실행되는지 원하는 대로 작동을 안 함!

...생략

if((row + column) % 2 == 0) {
    return false;
}

...생략

 

 

마지막으로 MainWindow.cs에 Game클래스를 넣어서 실행해주면 됩니다. 

아직 선택 취소를 구현을 안 해서 부족하지만...

 

 

 

여담: 

WinUI를 공부하면서 오류 해결한 거나 몰랐던 것들을 적어놓으려고 블로그에 글을 썼는데, 

오류 해결은 커녕 코드만 복붙에 놓는 수준이라 이래도 되나 싶은데..

설령 나중에 뭐했는지 혹은 참고하러 이 글을 다시 본다고 해도 이게 뭔지 알 수 있을까 싶다. 

글을 이렇게 작성해도 되려나...