我正在和Qt一起创建一个国际象棋游戏,现在我要加入人工智能来对抗电脑,但是我有一个大问题……我使用mouseReleaseEvent()函数通过拖放来移动碎片,所以现在我不知道如何不使用它来移动它们。当然,我必须创建一个函数,其中包含移动工件的坐标,但是如何使其移动呢?我想我需要更多地解释一下这个游戏,所以这里有一些基本的代码可以让您了解它是如何工作的:
Piece.h
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中,当我开始游戏时,我设置了棋子
void MainWindow::start()
{
scene.setSceneRect(-400, -250, 1024, 768);
Piece* pieces = new Piece[32];
ChessBoard::setBoard(scene, pieces);
}在ChessBoard.cpp中,我在场景中画出棋盘,并在上面添加棋子。
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中,我通过拖放移动它们
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,假设它决定这么做
void Game::run()
{
defaultBoardState[3][4] = -1;
defaultBoardState[1][4] = 0;
emit aiMoved();
}信号连接到应该移动该部分的MainWindow函数(我在这里编写了该函数,因为场景是MainWindow类中的一个QGraphicsScene变量,我可以在这里轻松地访问它)
connect(game, SIGNAL(aiMoved()), this, SLOT(aiMove()));
void MainWindow::aiMove()
{
//here I don't know how to make it move
}我正在考虑把这些部分变成全局的,这样我就可以在这个函数中访问它们,并在这个位置上做一些类似piece[1].setPos()的事情,但是我不能使一个QGraphicsPixmapItem成为全局的。如何创建一个只知道要移动的片段和目标位置的函数来移动碎片?
发布于 2020-12-07 17:39:32
您需要在MainWindow中保留指向片段的指针。类似于:
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);
}而且:不要使用全局变量。它们是不必要的,它们是有问题的,它们隐藏了程序中模块之间的耦合。你需要显式地传递一些东西,因为这会让你真正思考到哪里去了,你必须做一些设计工作,而不是仅仅让所有的东西都可以使用。
要对这种代码进行推理是非常困难的。--就好像你把车停在服务站,把你家的钥匙给他们,以防他们想问你一个问题。不,如果他们想问,他们必须经过一个明确的界面:他们打电话给你,给你发短信,或者给你发邮件,或者送一只信鸽。不管它是什么,它都需要有意识的选择。你得好好想想然后做个决定。
https://stackoverflow.com/questions/65186451
复制相似问题