在WPF中创建国际象棋图形用户界面

7
首先,如果这是一个重复的帖子,我表示歉意。由于我正在尝试同时发布/注册,事情有点混乱。
我开始研究如何从简单的WPF窗口运行UCI国际象棋引擎,掌握了将国际象棋引擎运行在不同线程上的技巧,并创建了一个相当可靠的基于文本的前端界面。
现在我更加雄心勃勃,想要开始构建一个带有国际象棋棋子的GUI,它可以将玩家的移动传递给国际象棋引擎,并在棋盘上表示引擎的移动。我想实现可拖动的棋子而不是点击方格。
我的当前尝试涉及在元素上使用可拖动的用户控件来表示棋子。我很想听听其他更有经验的WPF/.NET程序员如何处理此问题,因为我并不完全确信自己走在正确的轨道上。
例如:是否最好使用统一网格并在子元素之间拖动棋子数据?我应该创建一个抽象的“棋子”类,从中派生像兵这样的棋子吗?类似这样的问题。
有什么想法吗?这不是任何作业任务,只是我在闲暇时间里进行的练习。

1
这个问题不是你的重复,但你可能会感兴趣:https://dev59.com/ZUvSa4cB1Zd3GeqPawPO - Colin Pickard
在http://www.valil.com/winfx/上有一个WPF棋类应用程序示例。如果您正在构建此应用程序,这可能会对您有所帮助。 - Bhuvan
谢谢Colin,非常有趣的帖子 :) - dogsolitude_uk
1个回答

3

我为我的Silverlight 在线棋盘系统实现了一个国际象棋棋盘。

这是我是如何做到的:

  1. 我为棋盘制作了一个单独的用户控件。
  2. 我在控件上添加了一个8x8的网格。
  3. 然后我添加了64个边框,每个边框都有不同的颜色(深色和浅色),确保给每个边框命名。每个边框都使用Grid.Row和Grid.Col属性放置在网格上。
  4. 在每个边框内,我添加了一个图像,用于容纳棋子图像。
  5. 您需要编写一些方法来设置图像以根据当前游戏状态正确显示棋子。
  6. 每个图像都接收相同的事件(这很重要),所有64个调用相同的代码:

    MouseLeftButtonDown="Image_MouseLeftButtonDown" MouseMove="Image_MouseMove" MouseLeftButtonUp="Image_MouseLeftButtonUp"

这三个事件的想法是:当我点击图片(MouseLeftButtonDown)时,记录点击的起始位置,然后在鼠标移动时调用事件,以便在棋子移动时更新屏幕。最后一个事件是记录松开鼠标按钮(MouseLeftButtonUp),这允许我获取目的地并将移动发送给我的国际象棋引擎。一旦国际象棋引擎记录了移动,我只需重新绘制国际象棋棋盘即可。
private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Image image = (Image)sender;
    Border border = (Border)image.Parent;

    image.CaptureMouse();
    isMouseCapture = true;
    mouseXOffset = e.GetPosition(border).X;
    mouseYOffset = e.GetPosition(border).Y;

    var chessPiece = (Image) sender;
    var chessSquare = (Border) chessPiece.Parent;

    var row = (byte) (Grid.GetRow(chessSquare));
    var column = (byte) (Grid.GetColumn(chessSquare) - 1);

    if (engine.HumanPlayer == ChessPieceColor.White)
    {
        SelectionChanged(row, column, false);
    }
    else
    {
        SelectionChanged((byte)(7 - row), (byte)(7 - column), false);
    }
}

SelectionChanged是我自己的方法,用于记录用户选择的源方格。 isMouseCapture也是我自己的变量,用于记录用户何时开始拖动棋子。

private void Image_MouseMove(object sender, MouseEventArgs e)
{

    Image image = (Image)sender;
    Border border = (Border)image.Parent;


    if (!currentSource.Selected)
    {
        image.ReleaseMouseCapture();
        isMouseCapture = false;

        translateTransform = new TranslateTransform();

        translateTransform.X = 0;
        translateTransform.Y = 0;

        mouseXOffset = 0;
        mouseYOffset = 0;
    }



    if (isMouseCapture)
    {
        translateTransform = new TranslateTransform();

        translateTransform.X = e.GetPosition(border).X - mouseXOffset;
        translateTransform.Y = e.GetPosition(border).Y - mouseYOffset;

        image.RenderTransform = translateTransform;

        CalculateSquareSelected((int)translateTransform.X, (int)translateTransform.Y, false);


    }
}

在上面的CalculareSquareSelected函数中,将移动的像素转换为我认为棋子在8x8棋盘上所移动的位置。例如,假设我移动了100个像素,而棋盘方格只有50个像素,那么我就移动了2个棋盘方格。
private void Image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    if (translateTransform == null)
    {
        return;
    }

    Image image = (Image)sender;

    image.ReleaseMouseCapture();
    isMouseCapture = false;

    if (translateTransform.X > 10 || translateTransform.Y > 10 || translateTransform.X < -10 || translateTransform.Y < -10)
    {
        CalculateSquareSelected((int)translateTransform.X, (int)translateTransform.Y, true);
    }
    translateTransform = new TranslateTransform();

    translateTransform.X = 0;
    translateTransform.Y = 0;

    mouseXOffset = 0;
    mouseYOffset = 0;

    image.RenderTransform = translateTransform;

}

如果您有任何问题,请随时与我联系。


太棒了,非常感谢Adam!这正是我在寻找的 :) 今晚是星期五,我想我会尝试一下,我一定会好好查看你的网站的。我一直在尝试将UniformGrid的内容绑定到数组的内容上...你的方法看起来更加合理。还有一个问题:你从哪里获取象棋棋子的图形?它们看起来非常熟悉,类似于Fritz、Peshka等软件中的棋子。它们是某个标准的象棋图形集吗? - dogsolitude_uk
我实际上在rentacoder.com上付费请人开发了那些棋子图形,只花了我大约40美元。如果您想了解更多有关开发国际象棋引擎的信息,请访问我的计算机国际象棋博客www.chessbin.com。那里有很多代码示例。此外,随时从adamberent.com获取我的联系信息并通过电子邮件向我提出任何问题。 - Adam Berent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接