C#/WinUI3

[WinUI3] 체스 게임 만들기(1)

말하는 닭 2023. 2. 6. 02:11

간단하진 않겠지만, 체스 게임을 한 번 만들어보기로 했습니다. 

자꾸 말투가 높임말에서 왔다갔다 한 것 같다면 기분 탓입니다. (분명 기분 탓일 겁니다!)

 

글을 시작하기 앞서,

이 글은 체스 AI, 혹은 네트워크에 대해 다루지 않을 것입니다.

그냥 단순히 혼자서 흑백 다 움직이는 그런 프로그램을 짤겁니다.

 

뭐, 본론으로 돌아와서... 판 만들고 체스말 놓는데 2시간이 걸렸다면 믿으시겠나요 ㅎ..

 

 

우선 우리가 흔히 아는 8x8의 격자를 만들어봅시다. 

xaml로 처리할 수도 있지만, 64개를 쌩으로 만들기 싫었기 때문에 스크립트로 작성하고자 했습니다. 

private void SetBoard() {
    for(int i = 0; i < 8; i++) {
        RowDefinition row = new RowDefinition();
        ColumnDefinition column = new ColumnDefinition();
        row.Height = new GridLength(1, GridUnitType.Star);
        column.Width = new GridLength(1, GridUnitType.Star);

        Board.ColumnDefinitions.Add(column);
        Board.RowDefinitions.Add(row);
    }

    SolidColorBrush oddBrush = new SolidColorBrush(Color.FromArgb(255, 162, 59, 59));
    SolidColorBrush evenBrush = new SolidColorBrush(Color.FromArgb(255, 250, 232, 200));

    for(int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            Canvas canvas = new Canvas { Background = (i + j) % 2 == 0 ? evenBrush : oddBrush };

            Board.Children.Add(canvas);
            Grid.SetColumn(canvas, j);
            Grid.SetRow(canvas, i);
        }
    }
}

스크립트는 다음과 같습니다. 원래는 Rectangle로 하려 했는데, 이 위에 기물까지 올릴 생각이여서 캔버스로 바꿨습니다.

Definition 설정을 안 해주면 캔버스 하나가 그리드 전체를 잡아먹습니다. 반드시 설정해줍시다.

(Board는 xaml코드에 만들어놓은 그리드입니다)

 

GridUnitType은 Star로 설정하면 xaml에서 쓰던 "*"가 되며, Auto로 설정하면 "Auto"가 됩니다(이때, 숫자는 0으로 하는 듯합니다). 만일 타입을 넘기지 않을 경우, 그냥 픽셀 값으로 알아먹습니다. 

 

grid에는 margin과 borderThickness를 먹였습니다

 

 

2차전: 기물 놓기

for(int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
        Canvas canvas = new Canvas { Background = (i + j) % 2 == 0 ? evenBrush : oddBrush };

        /* 새로 작성한 부분 */
        if(i == 0 || i == 7) {
            Image image = new Image {
                Height = 50,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            switch(j) {
                case 0:
                    string img_uri1 = i == 0 ? "ms-appx:///Piece/white_rook.png" : "ms-appx:///Piece/black_rook.png";
                    image.Source = new BitmapImage(new Uri(img_uri1));
                    canvas.Children.Add(image); 
                    break;
                case 1:
                    string img_uri2 = i == 0 ? "ms-appx:///Piece/white_knight.png" : "ms-appx:///Piece/black_knight.png";
                    image.Source = new BitmapImage(new Uri(img_uri2));
                    canvas.Children.Add(image);
                    break;
                case 2:
                    string img_uri3 = i == 0 ? "ms-appx:///Piece/white_bishop.png" : "ms-appx:///Piece/black_bishop.png";
                    image.Source = new BitmapImage(new Uri(img_uri3));
                    canvas.Children.Add(image);
                    break;
                case 3:
                    string img_uri4 = i == 0 ? "ms-appx:///Piece/white_queen.png" : "ms-appx:///Piece/black_king.png";
                    image.Source = new BitmapImage(new Uri(img_uri4));
                    canvas.Children.Add(image);
                    break;
                case 4:
                    string img_uri5 = i == 0 ? "ms-appx:///Piece/white_king.png" : "ms-appx:///Piece/black_queen.png";
                    image.Source = new BitmapImage(new Uri(img_uri5));
                    canvas.Children.Add(image);
                    break;
                case 5:
                    img_uri3 = i == 0 ? "ms-appx:///Piece/white_bishop.png" : "ms-appx:///Piece/black_bishop.png";
                    image.Source = new BitmapImage(new Uri(img_uri3));
                    canvas.Children.Add(image);
                    break;
                case 6:
                    img_uri2 = i == 0 ? "ms-appx:///Piece/white_knight.png" : "ms-appx:///Piece/black_knight.png";
                    image.Source = new BitmapImage(new Uri(img_uri2));
                    canvas.Children.Add(image);
                    break;
                case 7:
                    img_uri1 = i == 0 ? "ms-appx:///Piece/white_rook.png" : "ms-appx:///Piece/black_rook.png";
                    image.Source = new BitmapImage(new Uri(img_uri1));
                    canvas.Children.Add(image);
                    break;
            }
        }
        else if(i == 1 || i == 6) {
            string img_uri = i == 2 ? "ms-appx:///Piece/white_pawn.png" : "ms-appx:///Piece/black_pawn.png";
            canvas.Children.Add(new Image { Source = new BitmapImage(new Uri(img_uri)), 
                                            Height = 50, 
                                            HorizontalAlignment = HorizontalAlignment.Center, 
                                            VerticalAlignment = VerticalAlignment.Center});
        }
        /* 새로 작성한 부분 */

        Board.Children.Add(canvas);
        Grid.SetColumn(canvas, j);
        Grid.SetRow(canvas, i);
    }
}

격자는 비교적 순조롭게 만들었으나, 기물 놓기가 생각보다 오래 걸렸습니다. 아래는 오래 걸린 이유이자 해결방법입니다. 

 

 

1. xaml과 달리 uri를 코드로 작성해서 쓰려면 "ms-apps:///"가 항상 경로 앞에 작성되어야 한다.

 

2. 사진을 불러오면 빌드 작업을 "내용"으로 바꿔야 한다.

 

기존 항목으로 사진들을 추가합니다

이걸 안 해줘서 당연히 안 나타난 것 뿐이었는데 왜 안되나 이것저것 뒤져보고 코드 고쳐보고... 허허..

 

그래도 잘 나오니까! (근데 분명히 센터로 정렬을 해줬는데 중앙에 딱 배치되지는 않습니다.)

 

판 만드는 것까지 끝! 

.

.

움직이는 거 구현하려면 얼마나 걸릴지 상상이 안 갑니다....