Sebelum Dijkstra bisa berjalan, kita perlu mengubah grid 2D menjadi graph berbobot. Pada bagian ini kita mendefinisikan struktur Grid, lokasi Cell, dan fungsi neighbors() yang mengembalikan sel-sel tetangga yang dapat dilalui dari suatu sel. Edge memiliki bobot seragam 1 — modifikasi ke bobot variabel (terrain cost) mudah dilakukan dengan menambah atribut biaya per sel.
Struktur Grid #
Grid direpresentasikan sebagai std::vector<std::string> di mana setiap string adalah satu baris. Konvensi karakter:
.— sel kosong, dapat dilalui, bobot 1.#— rintangan, tidak dapat dilalui.S— titik start, dapat dilalui (diperlakukan seperti.).G— titik goal, dapat dilalui.
struct Cell {
int row, col;
bool operator==(const Cell& o) const { return row == o.row && col == o.col; }
};
struct Grid {
std::vector<std::string> cells;
int rows, cols;
Grid(std::vector<std::string> g) : cells(std::move(g)) {
rows = (int)cells.size();
cols = rows > 0 ? (int)cells[0].size() : 0;
}
bool inBounds(int r, int c) const {
return r >= 0 && r < rows && c >= 0 && c < cols;
}
bool walkable(int r, int c) const {
if (!inBounds(r, c)) return false;
char ch = cells[r][c];
return ch != '#';
}
};Fungsi neighbors #
Untuk sel tertentu, tetangga yang valid adalah empat sel di atas, bawah, kiri, kanan yang walkable(). Fungsi ini mengembalikan std::vector<Cell>:
std::vector<Cell> neighbors(const Grid& g, const Cell& c) {
static const int dr[] = {-1, 1, 0, 0};
static const int dc[] = {0, 0, -1, 1};
std::vector<Cell> result;
for (int i = 0; i < 4; ++i) {
int nr = c.row + dr[i];
int nc = c.col + dc[i];
if (g.walkable(nr, nc)) result.push_back({nr, nc});
}
return result;
}Program Verifikasi #
Berikut program yang membangun grid contoh dan mencetak tetangga setiap sel yang dapat dilalui.
#include <iostream>
#include <vector>
struct Cell {
int row, col;
bool operator==(const Cell& o) const { return row == o.row && col == o.col; }
};
struct Grid {
std::vector<std::string> cells;
int rows, cols;
Grid(std::vector<std::string> g) : cells(std::move(g)) {
rows = (int)cells.size();
cols = rows > 0 ? (int)cells[0].size() : 0;
}
bool inBounds(int r, int c) const {
return r >= 0 && r < rows && c >= 0 && c < cols;
}
bool walkable(int r, int c) const {
if (!inBounds(r, c)) return false;
char ch = cells[r][c];
return ch != '#';
}
};
std::vector<Cell> neighbors(const Grid& g, const Cell& c) {
static const int dr[] = {-1, 1, 0, 0};
static const int dc[] = {0, 0, -1, 1};
std::vector<Cell> result;
for (int i = 0; i < 4; ++i) {
int nr = c.row + dr[i];
int nc = c.col + dc[i];
if (g.walkable(nr, nc)) result.push_back({nr, nc});
}
return result;
}
void printGrid(const Grid& g) {
std::cout << "Grid " << g.rows << "x" << g.cols << ":\n";
for (const auto& row : g.cells) std::cout << " " << row << "\n";
std::cout << "\n";
}
int main() {
Grid g({
".....",
".###.",
".S.#.",
"...#.",
"...G."
});
printGrid(g);
Cell sample = {2, 1}; // sel 'S'
std::cout << "Tetangga sel (2,1):\n";
for (const auto& nb : neighbors(g, sample)) {
std::cout << " -> (" << nb.row << "," << nb.col << ") = '"
<< g.cells[nb.row][nb.col] << "'\n";
}
return 0;
}Output yang Dihasilkan:
Grid 5x5:
.....
.###.
.S.#.
...#.
...G.
Tetangga sel (2,1):
-> (3,1) = '.'
-> (2,0) = '.'
-> (2,2) = '.'Tiga tetangga: sel (1,1) adalah # (rintangan) sehingga walkable() mengembalikan false dan sel tersebut tidak dimasukkan. Tetangga lain yang valid adalah (3,1), (2,0), dan (2,2) — semuanya dapat dilalui.
Bedah Baris Penting #
struct Celldenganoperator==: diperlukan untuk membandingkan apakah dua sel sama — digunakan saat mendeteksi start dan goal, serta saat berhenti jika start = goal.Grid(std::vector<std::string> g): konstruktor mengambil ownership vector lewatstd::move. Setelah konstruksi, pemanggil tidak bisa lagi mengakses vector asli — kepindahan eksplisit menghindari salinan tidak perlu.static const int dr[] = {-1, 1, 0, 0}: arah gerak baris untuk empat tetangga.staticdi dalam fungsi diinisialisasi sekali;constmenjamin tidak diubah. Urutan atas-bawah-kiri-kanan dipilih agar konsisten dengan konvensi grafik.g.walkable(nr, nc): encapsulasi pengecekan. Tanpa fungsi ini, kode Dijkstra harus mengecekinBoundsdan karakter#di setiap tempat — error-prone.result.push_back({nr, nc}): aggregate initialization membuatCelltanpa konstruktor eksplisit. Sintaks ringkas dan jelas.
Ringkasan Bagian 1 #
Kita telah mendefinisikan struktur Grid dan Cell, fungsi neighbors() yang mengembalikan empat tetangga valid, dan konvensi karakter ./#/S/G. Pada Bagian 2, struktur ini menjadi masukan untuk algoritma Dijkstra.