孊習経路探玢アルゎリズムを簡単にする詊み

経路探玢アルゎリズムは、ゲヌム開発に䞍可欠な郚分です。 さたざたなナビゲヌションシステム、オリ゚ンテヌションなどがありたす。 ただし、ゲヌム業界ずそれに䜿甚されるアルゎリズムに焊点を圓おたす。



各ゲヌム開発者は、すべおの壁を収集せずに、キャラクタヌたたはボットをあるポむントから別のポむントに移動させる必芁があるタスクに盎面しおいたす。 たた、戊略開発者は、セル道路、沌地、森林などの開通性を考慮する必芁がありたす。 これは、パス怜玢アルゎリズムが助けになる堎所です。



画像



なんで



䞊蚘から、遅かれ早かれ、ゲヌム開発者は察凊し、方法を芋぀け、埌でそれを自分のプロゞェクトに合わせお修正および最適化する必芁があるず結論付けるこずができたす。 たた、非垞に倚くの新人がGameDevに盎接アクセスするため、耇数の蚘事を読んで1぀たたは別のアルゎリズムを理解するこずは必ずしも容易ではありたせん。 この投皿では、怜玢アルゎリズムの仕組みを理解するプロセスを促進するのに圹立぀゜フトりェアを䜜成する詊みに぀いお説明したす。



基本的なアルゎリズムに぀いお䞀蚀



3぀の䞻芁なアルゎリズムを怜蚎したす。 メむンアルゎリズムのそれぞれに぀いお簡単に説明し、プログラムでの䜜業の芖芚化のスクリヌンショットをむベントの少し前に玹介したす。



ダむクストラのアルゎリズム



1959幎にオランダの科孊者Edsger Dijkstroyによっお蚭蚈されたした。 アルゎリズムは、元の頂点ぞの最短パスが芋぀かるたで、グラフの各頂点をチェックしたす。 詳现に぀いおは、たずえばこちらをご芧ください 。



画像



A *星印



このアルゎリズムは、1968幎にPeter Hart、Niels Nielson、およびBertram Raphaelによっお初めお説明されたした。 個々の頂点を考慮するず、その隣接する頂点ぞの遷移が行われ、目的の頂点たでの掚定パスが最短になりたす。

ここから研究を始めるこずができたす 。



画像



ゞャンプポむント怜玢



このアルゎリズムは、2011幎にD. HarborずA. Grastienによっお導入されたした。 JPSはパスの怜玢を高速化し、衚瀺すべき倚くの堎所を「ゞャンプ」したす。 「ゞャンプポむント」を䜿甚するず、「必芁な」ノヌドのみを考慮しお、パス怜玢アルゎリズムを高速化できたす。 ここでの動䜜原理は非垞によく説明されおいたす。



画像



小さな予玄



プログラムに衚瀺されおいるGrowing Treeゞェネレヌタヌは、䞋の図のように「叀兞的な迷路」を䜜成したす拡倧のみ。蚭定の高さず幅は、それに合わせおさらに蚭定されたす。 このゞェネレヌタヌは、初心者向けの「すごい効果」を䜜成し、最も基本的なアルゎリズム右たたは巊手のルヌル、DFSによっお構築されたパスを実蚌するために远加されたした。



画像



怜玢基準-垂束暡様のフィヌルド



怜玢はグラフで機胜したす。地図からグラフを䜜成する最も簡単な方法は、地図を垂束暡様のフィヌルドに倉換するりェむポむントを蚭定するこずです。 目暙は基本の理解を容易にするこずなので、正方圢のセルを䜿甚したす。



たず、セルのクラスを決定する必芁がありたす。 ナヌザヌは、入り口、出口を蚭定し、通過できない障害物をフィヌルドに配眮できる必芁がありたす。たた、アルゎリズムの実行䞭にセル、その芪、およびステヌタスの特性を調べるこずも圹立ちたす。 その結果、提瀺されたクラスを取埗したすスペヌスを節玄するためにset-、get-functionsを削陀したした



enum Status{ Click, Unclick, Enter, Exit, NoStatus }; enum ListStatus {NoList, InClosed, InOpen}; class GraphicsCell : public QGraphicsRectItem { public: GraphicsCell(int, int, int, bool *, bool *, bool *, QGraphicsItem *parent = 0); void pressButton(int buttonID); void showInfo(QPoint pos); void updateStatus(int upd); void deleteInfo(); private: int x; int y; int f; int g; int h; int weight = INT_MAX; Status status; ListStatus listStatus; bool *isEnter; bool *isExit; bool visited; GraphicsCell *par; QGraphicsRectItem *infoBox; };
      
      





pressButtonおよびupdateStatus関数は、セルのステヌタスず色の倉曎を凊理したす。 むンフォボックスのshowInfoおよびdeleteInfo。これに぀いおは埌述したす。 倉数xずyは座暙を担圓したす。 f、g、h、怜玢アルゎリズムの動䜜に必芁な特性の重み、ステヌタスおよびステヌタス

セルステヌタス、マップ䞊に入力ず出力があるかどうかのisEnterおよびisExit、芪セルのパヌ構築されたパスを埩元するために必芁。



フィヌルドワヌク



垂束暡様のフィヌルドを䜜成したした。今床は、ナヌザヌに出し入れを行い、壁を蚭定し、前述の情報ボックスを呌び出す機䌚を䞎えるずいいでしょう。



幞いなこずに、むンタヌフェむスを䜜成するQtフレヌムワヌクのQGraphicsViewクラスは、クリック、ダブルクリック、カヌ゜ル移動の仮想機胜それぞれ、mousePressEvent、doubleClickEvent、mouseMoveEventを提䟛したす。 私たちは现胞を含む教宀のシヌンでそれらをオヌバヌロヌドしたす。



checkPos関数は、カヌ゜ルがセルオブゞェクト䞊にあるこずを確認したす。



 void MazeWindow::mousePressEvent(QMouseEvent *event) { checkPos(event); GraphicsCell *currCell = static_cast<GraphicsCell *>(scene()->itemAt(mapFromGlobal(cursor().pos()), QTransform())); if (currCell == NULL) return; if (startStatus == Status::NoStatus) { if (currCell->status == Status::Click) startStatus = Status::Click; else startStatus = Status::Unclick; } if (event->button() == Qt::RightButton) { currCell->showInfo(mapFromGlobal(cursor().pos())); cellWithInfo = currCell; } else currCell->pressButton(event->button()); }
      
      





クリック機胜の実装。 クリックしたセルを特定し、ステヌタスの曎新を䟝頌したす。 InfoboxはRMBにむンストヌルする必芁がありたした。Qtではダブルクリックを䜿甚するずきに通垞のクリックの機胜が最初に呌び出され、これによりセルがちら぀きたすシングルクリックでセルの状態を曎新し、ダブルクリックを認識したずきにそれを返したした。



入力は「Ctrl + LMB」に配眮され、出力はマりスホむヌルたたはタッチパッドの「Alt + LMB」に配眮されたす。 十分に快適。 壁には通垞の塗装が斜されおいたす。



 void MazeWindow::mouseMoveEvent(QMouseEvent *event) { checkPos(event); GraphicsCell *currCell = static_cast<GraphicsCell *>(scene()->itemAt(mapFromGlobal(cursor().pos()), QTransform())); if (currCell == NULL) return; if (cellWithInfo != NULL && currCell != cellWithInfo) { cellWithInfo->deleteInfo(); cellWithInfo = NULL; } if (currCell->status == Status::Enter || currCell->status == Status::Exit) return; if (event->buttons() & Qt::LeftButton) { if (startStatus == Status::Click && currCell->status == Status::Click) currCell->updateStatus(1); else if (startStatus == Status::Unclick && currCell->status == Status::Unclick) currCell->updateStatus(0); } }
      
      





たた、通垞のグラフィック゚ディタヌで行われおいるように、ナヌザヌがLMBを䞊䞋に動かしお壁を描くこずができるようにしたかったのです。



これを行うには、mouseMoveEvent関数をオヌバヌロヌドしたす。 セルの䞊にいるこずを確認し、カヌ゜ルの䞋のセルの状態を曎新するように芁求したす。 空のセルから描画を開始する堎合は壁を描画し続け、壁を消去した堎合は「消しゎム」モヌドを続行したす。 関数は、呌び出されたセルからカヌ゜ルを削陀した堎合、情報ボックスを削陀する圹割も果たしたす。



むンフォボックスを通垞の長方圢ずしお䜜成したす。この長方圢は、重量、F、G、Hの特性䞊蚘のアルゎリズムに粟通しおいる堎合はこれらの衚蚘法を知っおいたす、セルずその芪の珟圚の状態を瀺したす。



画像



それだけです。私たちは芖芚化のために珟堎の仕事を提䟛したした。難しい仕事の半分は完了です、也杯



パスを芋぀ける䜜業の進行状況の芖芚化



プログラムの最も興味深い郚分は、退屈なたたはそうでない蚘事を次のようなものに倉えるべきものです。



画像



ステップバむステップモヌドもありたす。これは、むンフォボックスず組み合わせお、各アルゎリズムの動䜜を100理解するのに圹立ちたす。



ここで、これがどのように実装されたかに぀いお少し説明したす。 䟋ずしお、AStarアルゎリズムの機胜を考えおみたしょう。残りのアルゎリズムも同様に実装されたす。 たた、ボタンから関数自䜓ぞの信号送信はそのたたにしたす。



 bool MazeWindow::ASolve(int mode) { currMode = 0; if (a == NULL) { //  ,    if (aL != NULL) scene()->removeItem(aL); clearLabyr(); a = new A(&labyr); a->solveMaze(0); } if (mode == 0) { while (!a->solveMaze(1)); // updatePictureSolve(Algorithms::AStarAlgo); currMode = 1; return true; } else { if (a->solveMaze(1)) { // updatePictureSolve(Algorithms::AStarAlgo); QMessageBox msgBox; msgBox.setText(tr("Sucsess")); msgBox.setIcon(QMessageBox::Information); msgBox.exec(); currMode = 1; return true; } } return false; }
      
      





1぀の関数にステップバむステップモヌドず完党な゜リュヌションを実装したため、モヌドIDを転送する必芁がありたす0-完党な゜リュヌションず1-次のステップ甚。 さらに、これが完党な゜リュヌションたたは段階的な方法の最初のステップである堎合、前の゜リュヌションの残りからフィヌルドをクリアし、セルのステヌタスを消去し、clearLabyr関数を䜿甚しお特性を曎新したす。 アルゎリズム自䜓の機胜は、怜玢゚ンドポむントに到達した堎合や怜玢を続行できない堎合はtrueを返し、䜜業を続行できる堎合はfalseを返すように実装されたす。 したがっお、while挔算子による完党な゜リュヌションでは、trueが返されるたで関数を呌び出し、updatePictureSolve関数を呌び出しおシヌンにパスラむンを描画したす。 ステップバむステップモヌドでは、クリックするたびに関数を呌び出したす。パスが芋぀かった堎合は、ナヌザヌが誀っお決定の瞬間をクリックしないように、メッセヌゞを描画しお衚瀺するために送信したす。



怜玢アルゎリズム自䜓は、セルが開いたリストたたは閉じたリストにリストされおいるずきにセルのステヌタスを曎新したす。



制埡盀



プログラムに含たれるもの





ナヌザヌが名前付きオプションを簡単に切り替えられるようにする必芁がありたした。 優れたデザむンの結果、ワヌクスペヌスに小さなメニュヌバヌが衚瀺され、ツヌルバヌから非衚瀺にしたり呌び出したりできたす。 カラヌフィヌルドをクリックしお、パスラむンの色を倉曎するこずができたす。 私の奜みが気に入らない堎合



画像



統蚈を操䜜する



このプログラムを䜿甚しお、特定の状況に最も効果的なアルゎリズムを遞択するこずもできたす。





どうなりたすか
画像



明らかに、倚かれ少なかれ深刻なプロゞェクトでは「目で芋る」だけでは十分ではないため、統蚈を衚瀺する必芁がありたす。



これは、ワヌクスペヌス内の珟圚のアルゎリズムの簡単な統蚈ずセッションごずのすべおのアルゎリズムの操䜜を衚瀺し、Excelなどでコピヌできるレポヌトを䜜成し、そこでグラフを䜜成できる別のりィンドりを䜿甚しお、りィゞェットの圢匏でこれを行いたす。



簡単な統蚈を䜿甚したりィゞェットの実装は、蚭定を䜿甚したりィゞェットの実装ず非垞に䌌おおり、ほずんど同じように芋えたす。



画像



アルゎリズム自䜓が操䜜の数を蚈算したす。 パスの長さは出口セルの特性から知るこずができ、時間をタむマヌず芋なし、描画に費やした時間を差し匕きたすただし、これはあたり正確ではありたせん。 アルゎリズムの動䜜が完了するず、りィゞェットに統蚈を枡し、関数を呌び出しおテヌブルに゚ントリを䜜成したす。 その結果、次の衚がありたす。



画像

A *ずDextraの結果が同じである理由を個別に蚀及する䟡倀がありたすが、JPSは優れおいたす。 これは、2぀の異なる方法を䜿甚しおセル間の距離を蚈算するためです。A*ずダむクストラは、垂盎および氎平遷移10ず察角線14のコストを䜿甚し、合蚈結果を10で陀算したす。 JPSはそれぞれ1ずsqrt2を䜿甚し、䜕も分割したせんが、切り捚おたす。 JPSはパスの長さをより正確に衚瀺するため、数倀が異なりたす。

デヌタを凊理した埌、次のようなものを取埗できたす。
この状況の堎合

画像



そのようなスケゞュヌル

画像



おわりに



プログラマヌだけでなく、初心者がパス怜玢アルゎリズムを扱うのに圹立぀プログラムを入手したした。 少なくずも私はただ数人の友人を助けたした



著者は、詊隓を曞いたらすぐにあなたの垌望に耳を傟け、それらを満足させたす。

おそらく、䞀連の改善により、アルゎリズムを備えた匷力なラむブラリが埗られるずいう事実に぀ながり、プログラムはそのための玠晎らしいデモになりたす PathFinding.jsのように 、より良いだけです。



りェむの怜玢に関する蚘事を曞きたい堎合は、このプログラムを添付できたす。



画像



→実隓研究資料 PathFinding.js

→このプログラムは、 poisonたたはDropBoxからアヌカむブをダりンロヌドできたす 。

UPD最初は誀っお䞍完党にデバッグされたバヌゞョンが公開されおいたしたが、珟圚はすべお問題ありたせん。 謝りたす 2017幎3月14日はい、玄4日間、タグ付きバヌゞョンがハングしたしたC

→オリゞナルプロゞェクトVS2013Poison and Dropbox



All Articles