用c语言帮我写一个最短路径的地图可视化展示
时间: 2023-08-28 13:10:35 浏览: 163
好的,这个任务需要用到C语言和图形库,我推荐使用SDL库。以下是实现最短路径地图可视化展示的基本步骤:
1. 创建一个窗口和画布,用于显示地图和路径。
2. 读入地图数据,可以从文件中读取或者手动输入。
3. 实现一个最短路径算法,比如Dijkstra算法或者A*算法,用于计算从起点到终点的最短路径。
4. 将计算出来的最短路径标记在地图上,可以使用不同的颜色或者线条来表示。
5. 在窗口中绘制地图和路径,可以使用SDL库提供的绘图函数。
下面是一个简单的示例代码,实现了一个最短路径地图可视化展示的基本功能:
```c
#include <stdio.h>
#include <stdlib.h>
#include <SDL2/SDL.h>
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define TILE_SIZE 32
typedef struct {
int x, y;
} Point;
typedef struct {
int width, height;
int **grid;
} Map;
Map *map_create(int width, int height) {
Map *map = malloc(sizeof(Map));
map->width = width;
map->height = height;
map->grid = malloc(height * sizeof(int*));
for (int i = 0; i < height; i++) {
map->grid[i] = malloc(width * sizeof(int));
for (int j = 0; j < width; j++) {
map->grid[i][j] = 0;
}
}
return map;
}
void map_destroy(Map *map) {
if (map) {
for (int i = 0; i < map->height; i++) {
free(map->grid[i]);
}
free(map->grid);
free(map);
}
}
void map_draw(SDL_Renderer *renderer, Map *map) {
SDL_Rect rect = { 0, 0, TILE_SIZE, TILE_SIZE };
for (int i = 0; i < map->height; i++) {
for (int j = 0; j < map->width; j++) {
rect.x = j * TILE_SIZE;
rect.y = i * TILE_SIZE;
if (map->grid[i][j] == 1) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
} else {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
}
SDL_RenderFillRect(renderer, &rect);
}
}
}
void map_set(Map *map, int x, int y, int value) {
if (x >= 0 && x < map->width && y >= 0 && y < map->height) {
map->grid[y][x] = value;
}
}
int map_get(Map *map, int x, int y) {
if (x >= 0 && x < map->width && y >= 0 && y < map->height) {
return map->grid[y][x];
}
return 0;
}
int map_is_wall(Map *map, int x, int y) {
return map_get(map, x, y) == 1;
}
int map_distance(Point a, Point b) {
return abs(a.x - b.x) + abs(a.y - b.y);
}
typedef struct {
int x, y;
int f, g, h;
struct Node *parent;
} Node;
Node *node_create(int x, int y) {
Node *node = malloc(sizeof(Node));
node->x = x;
node->y = y;
node->f = 0;
node->g = 0;
node->h = 0;
node->parent = NULL;
return node;
}
void node_destroy(Node *node) {
free(node);
}
int node_equals(Node *a, Node *b) {
return a->x == b->x && a->y == b->y;
}
int node_compare(Node *a, Node *b) {
if (a->f < b->f) {
return -1;
} else if (a->f > b->f) {
return 1;
} else {
return 0;
}
}
typedef struct {
int count;
int capacity;
Node **nodes;
} PriorityQueue;
PriorityQueue *pq_create(int capacity) {
PriorityQueue *pq = malloc(sizeof(PriorityQueue));
pq->count = 0;
pq->capacity = capacity;
pq->nodes = malloc(capacity * sizeof(Node*));
return pq;
}
void pq_destroy(PriorityQueue *pq) {
if (pq) {
free(pq->nodes);
free(pq);
}
}
void pq_enqueue(PriorityQueue *pq, Node *node) {
if (pq->count < pq->capacity) {
pq->nodes[pq->count++] = node;
int i = pq->count - 1;
while (i > 0 && node_compare(pq->nodes[i], pq->nodes[(i-1)/2]) < 0) {
Node *temp = pq->nodes[(i-1)/2];
pq->nodes[(i-1)/2] = pq->nodes[i];
pq->nodes[i] = temp;
i = (i-1)/2;
}
}
}
Node *pq_dequeue(PriorityQueue *pq) {
if (pq->count > 0) {
Node *node = pq->nodes[0];
pq->nodes[0] = pq->nodes[--pq->count];
int i = 0;
while (i*2+1 < pq->count) {
int left = i*2+1;
int right = i*2+2;
int min = left;
if (right < pq->count && node_compare(pq->nodes[right], pq->nodes[left]) < 0) {
min = right;
}
if (node_compare(pq->nodes[min], pq->nodes[i]) < 0) {
Node *temp = pq->nodes[min];
pq->nodes[min] = pq->nodes[i];
pq->nodes[i] = temp;
i = min;
} else {
break;
}
}
return node;
}
return NULL;
}
int pq_contains(PriorityQueue *pq, Node *node) {
for (int i = 0; i < pq->count; i++) {
if (node_equals(pq->nodes[i], node)) {
return 1;
}
}
return 0;
}
Node *pq_find(PriorityQueue *pq, Node *node) {
for (int i = 0; i < pq->count; i++) {
if (node_equals(pq->nodes[i], node)) {
return pq->nodes[i];
}
}
return NULL;
}
void pq_update(PriorityQueue *pq, Node *node) {
int i;
for (i = 0; i < pq->count; i++) {
if (node_equals(pq->nodes[i], node)) {
break;
}
}
if (i < pq->count) {
while (i > 0 && node_compare(pq->nodes[i], pq->nodes[(i-1)/2]) < 0) {
Node *temp = pq->nodes[(i-1)/2];
pq->nodes[(i-1)/2] = pq->nodes[i];
pq->nodes[i] = temp;
i = (i-1)/2;
}
}
}
Node *path_create(Node *start, Node *end) {
Node *node = end;
while (node->parent != NULL && !node_equals(node, start)) {
node = node->parent;
}
if (node_equals(node, start)) {
return node;
} else {
return NULL;
}
}
Node *path_find(Map *map, Point start, Point end) {
PriorityQueue *open_set = pq_create(map->width * map->height);
PriorityQueue *closed_set = pq_create(map->width * map->height);
Node *start_node = node_create(start.x, start.y);
Node *end_node = node_create(end.x, end.y);
start_node->g = 0;
start_node->h = map_distance(start, end);
start_node->f = start_node->g + start_node->h;
pq_enqueue(open_set, start_node);
while (open_set->count > 0) {
Node *current = pq_dequeue(open_set);
pq_enqueue(closed_set, current);
if (node_equals(current, end_node)) {
Node *path = path_create(start_node, end_node);
pq_destroy(open_set);
pq_destroy(closed_set);
return path;
}
Point neighbors[4] = {
{ current->x-1, current->y },
{ current->x, current->y-1 },
{ current->x+1, current->y },
{ current->x, current->y+1 }
};
for (int i = 0; i < 4; i++) {
Point neighbor = neighbors[i];
if (map_is_wall(map, neighbor.x, neighbor.y)) {
continue;
}
Node *neighbor_node = node_create(neighbor.x, neighbor.y);
neighbor_node->g = current->g + 1;
neighbor_node->h = map_distance(neighbor, end);
neighbor_node->f = neighbor_node->g + neighbor_node->h;
neighbor_node->parent = current;
if (pq_contains(closed_set, neighbor_node)) {
node_destroy(neighbor_node);
continue;
}
Node *open_node = pq_find(open_set, neighbor_node);
if (open_node == NULL) {
pq_enqueue(open_set, neighbor_node);
} else if (neighbor_node->g < open_node->g) {
open_node->g = neighbor_node->g;
open_node->f = open_node->g + open_node->h;
open_node->parent = current;
pq_update(open_set, open_node);
node_destroy(neighbor_node);
} else {
node_destroy(neighbor_node);
}
}
}
pq_destroy(open_set);
pq_destroy(closed_set);
return NULL;
}
int main(int argc, char *argv[]) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Map Viewer", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
Map *map = map_create(SCREEN_WIDTH/TILE_SIZE, SCREEN_HEIGHT/TILE_SIZE);
Point start = { 0, 0 };
Point end = { map->width-1, map->height-1 };
Node *path = path_find(map, start, end);
int quit = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = 1;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
map_draw(renderer, map);
if (path != NULL) {
Node *node = path;
while (node->parent != NULL) {
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderDrawLine(renderer, node->x * TILE_SIZE + TILE_SIZE/2, node->y * TILE_SIZE + TILE_SIZE/2, node->parent->x * TILE_SIZE + TILE_SIZE/2, node->parent->y * TILE_SIZE + TILE_SIZE/2);
node = node->parent;
}
}
SDL_RenderPresent(renderer);
}
if (path != NULL) {
node_destroy(path);
}
map_destroy(map);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
```
这段代码实现了一个最短路径地图可视化展示的功能,可以自己定义地图数据,然后计算并显示从起点到终点的最短路径。你可以编译运行这段代码,看一下效果。
阅读全文