首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过函数移动QGraphicsPixmapItem

通过函数移动QGraphicsPixmapItem
EN

Stack Overflow用户
提问于 2020-12-07 17:27:24
回答 1查看 55关注 0票数 1

我正在和Qt一起创建一个国际象棋游戏,现在我要加入人工智能来对抗电脑,但是我有一个大问题……我使用mouseReleaseEvent()函数通过拖放来移动碎片,所以现在我不知道如何不使用它来移动它们。当然,我必须创建一个函数,其中包含移动工件的坐标,但是如何使其移动呢?我想我需要更多地解释一下这个游戏,所以这里有一些基本的代码可以让您了解它是如何工作的:

Piece.h

代码语言:javascript
复制
class Piece : public QGraphicsPixmapItem
{
public:
    Piece(QGraphicsItem *parent = nullptr);

    void setPieceScene(QGraphicsScene *graphicsScene) { pieceScene = graphicsScene; }
    QGraphicsScene *getPieceScene() { return pieceScene; }
    void setPieceName(QString pieceName) { name = pieceName; }
    QString getPieceName() { return name; }
    void setPrevPos(QPointF pos) { prevPos = pos; }
    QPointF getPrevPos() { return prevPos; }

    bool leftStart = false;      
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
private:
    QString name;
    QGraphicsScene *pieceScene;
    QPointF prevPos;
 };

在MainWindow.cpp中,当我开始游戏时,我设置了棋子

代码语言:javascript
复制
void MainWindow::start()
{
    scene.setSceneRect(-400, -250, 1024, 768);

    Piece* pieces = new Piece[32];
    ChessBoard::setBoard(scene, pieces);
}

在ChessBoard.cpp中,我在场景中画出棋盘,并在上面添加棋子。

代码语言:javascript
复制
void ChessBoard::setBoard(QGraphicsScene &scene, Piece piece[])
{
   setSquares(scene); //just drawing the squares by adding QGraphicsRectItem
   
   //...
   piece[8].setPixmap(QPixmap(":/images/rook_w.svg").scaled(80, 80));
   piece[8].setPos(-200, 360);
   piece[8].setPieceName("W_Rook");
   scene.addItem(&piece[8]);
   // and so on for the other pieces

}

最后,在Piece.cpp中,我通过拖放移动它们

代码语言:javascript
复制
void Piece::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
        
        Piece::setPrevPos(Piece::pos()); 
}

void Piece::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
     QPointF lastPoint = mapToScene(event->lastPos());
     Piece::setPos(lastPoint.x() - 40, lastPoint.y() - 40);
}

void Piece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    Game* game = Game::getInstance();
    game->setTurn();

    QList<QGraphicsItem*> colliders = Piece::collidingItems();
    int prevRow, prevCol, nextRow, nextCol;

    //...other checks for the capture before this, but it's not important
    if (colliders.length() == 1) //1 collider means it's a square
    {
      if ((this->name == "W_Pawn" && game->turn=="white") || (this->name == "B_Pawn" && game->turn=="black"))
        {
          
            if (Pawn::pawnMove(this, colliders[0], defaultBoardState))
              //here I check if the move is valide, then the drop is accepted
              //...same thing for the other pieces
        }
    }

    else 
    {
        this->setPos(this->prevPos);
    }
}

defaultBoardState是一个简单的带有片段值的全局int matrix8,当移动完成时,我会更新它。所以我们现在面临的问题是:在Game.cpp中,我运行AI,假设它决定这么做

代码语言:javascript
复制
void Game::run()
{

    defaultBoardState[3][4] = -1;
    defaultBoardState[1][4] = 0;
        
    emit aiMoved();
    
}

信号连接到应该移动该部分的MainWindow函数(我在这里编写了该函数,因为场景是MainWindow类中的一个QGraphicsScene变量,我可以在这里轻松地访问它)

代码语言:javascript
复制
connect(game, SIGNAL(aiMoved()), this, SLOT(aiMove()));

void MainWindow::aiMove()
{
    
    //here I don't know how to make it move

}

我正在考虑把这些部分变成全局的,这样我就可以在这个函数中访问它们,并在这个位置上做一些类似piece[1].setPos()的事情,但是我不能使一个QGraphicsPixmapItem成为全局的。如何创建一个只知道要移动的片段和目标位置的函数来移动碎片?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-07 17:39:32

您需要在MainWindow中保留指向片段的指针。类似于:

代码语言:javascript
复制
class MainWindow : public (whatever, most likely should be QWidget not QMainWindow) {
  Piece *pieces[8*4] = {}; // so they are null be default

  ...
};

void MainWindow::start()
{
    scene.setSceneRect(-400, -250, 1024, 768);

    for (auto *& piece: m_pieces)
         piece = new Piece;

    ChessBoard::setBoard(scene, m_pieces);
}

而且:不要使用全局变量。它们是不必要的,它们是有问题的,它们隐藏了程序中模块之间的耦合。你需要显式地传递一些东西,因为这会让你真正思考到哪里去了,你必须做一些设计工作,而不是仅仅让所有的东西都可以使用。

要对这种代码进行推理是非常困难的。--就好像你把车停在服务站,把你家的钥匙给他们,以防他们想问你一个问题。不,如果他们想问,他们必须经过一个明确的界面:他们打电话给你,给你发短信,或者给你发邮件,或者送一只信鸽。不管它是什么,它都需要有意识的选择。你得好好想想然后做个决定。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65186451

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档