iT邦幫忙

0

Day28 部分C程式碼2

c
  • 分享至 

  • xImage
  •  

search.h

#ifndef SEARCH_H
#define SEARCH_H
#include "maze_gen.h"

/* Search function prototypes:
 * Each returns pathLength and expanded nodes.
 * For AStar, additionally fills path array (sequence of coordinates) and returns len.
 */
void DFS_Search(Maze *maze, int *pathLength, int *expanded);
void BFS_Search(Maze *maze, int *pathLength, int *expanded);
int AStar_Search(Maze *maze, int *pathLength, int *expanded, int path[][2], int maxpath);

#endif

search.c

#include "search.h"
#include <stdlib.h>
#include <string.h>

typedef struct Node {
    int x, y;
    int g, h;
    struct Node *parent;
} Node;

static int heuristic(int x, int y, int gx, int gy) {
    int dx = x - gx; if (dx < 0) dx = -dx;
    int dy = y - gy; if (dy < 0) dy = -dy;
    return dx + dy;
}

/* DFS (stack) */
void DFS_Search(Maze *maze, int *pathLength, int *expanded) {
    int w = maze->width, h = maze->height;
    char visited[h][w];
    memset(visited, 0, sizeof(visited));
    *expanded = 0; *pathLength = 0;

    Node *stack[100000];
    int top = 0;

    Node *start = malloc(sizeof(Node));
    start->x = maze->startX; start->y = maze->startY; start->parent = NULL;
    stack[top++] = start;

    int dirs[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};

    while (top > 0) {
        Node *cur = stack[--top];
        if (visited[cur->y][cur->x]) { free(cur); continue; }
        visited[cur->y][cur->x] = 1;
        (*expanded)++;
        if (cur->x == maze->endX && cur->y == maze->endY) {
            Node *p = cur;
            while (p) {
                if (maze->grid[p->y][p->x] == ' ') maze->grid[p->y][p->x] = '.';
                (*pathLength)++;
                p = p->parent;
            }
            // free remaining stack
            while (top--) free(stack[top]);
            free(cur);
            return;
        }
        for (int i = 0; i < 4; i++) {
            int nx = cur->x + dirs[i][0], ny = cur->y + dirs[i][1];
            if (nx >= 0 && ny >= 0 && nx < w && ny < h && maze->grid[ny][nx] != '#' && !visited[ny][nx]) {
                Node *n = malloc(sizeof(Node));
                n->x = nx; n->y = ny; n->parent = cur;
                stack[top++] = n;
            }
        }
    }
}

/* BFS (queue) */
void BFS_Search(Maze *maze, int *pathLength, int *expanded) {
    int w = maze->width, h = maze->height;
    char visited[h][w];
    memset(visited, 0, sizeof(visited));
    *expanded = 0; *pathLength = 0;

    Node **queue = malloc(sizeof(Node*) * (w*h + 10));
    int qf = 0, qr = 0;

    Node *start = malloc(sizeof(Node));
    start->x = maze->startX; start->y = maze->startY; start->parent = NULL;
    queue[qr++] = start;

    int dirs[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};

    while (qf < qr) {
        Node *cur = queue[qf++];
        if (visited[cur->y][cur->x]) { free(cur); continue; }
        visited[cur->y][cur->x] = 1;
        (*expanded)++;
        if (cur->x == maze->endX && cur->y == maze->endY) {
            Node *p = cur;
            while (p) {
                if (maze->grid[p->y][p->x] == ' ') maze->grid[p->y][p->x] = '.';
                (*pathLength)++;
                p = p->parent;
            }
            // free queue
            for (int i = qf; i < qr; i++) free(queue[i]);
            free(queue);
            free(cur);
            return;
        }
        for (int i = 0; i < 4; i++) {
            int nx = cur->x + dirs[i][0], ny = cur->y + dirs[i][1];
            if (nx >= 0 && ny >= 0 && nx < w && ny < h && maze->grid[ny][nx] != '#' && !visited[ny][nx]) {
                Node *n = malloc(sizeof(Node));
                n->x = nx; n->y = ny; n->parent = cur;
                queue[qr++] = n;
            }
        }
    }
    free(queue);
}

/* A* (returns path array length):
 * path[][] will be filled as path[0..len-1] with coordinates from start->...->goal
 * returns len (0 if no path)
 */
int AStar_Search(Maze *maze, int *pathLength, int *expanded, int path[][2], int maxpath) {
    int w = maze->width, h = maze->height;
    char closed[h][w];
    memset(closed, 0, sizeof(closed));
    *expanded = 0; *pathLength = 0;

    Node **open = malloc(sizeof(Node*) * (w*h*4 + 10));
    int openCount = 0;

    Node *start = malloc(sizeof(Node));
    start->x = maze->startX; start->y = maze->startY; start->g = 0;
    start->h = heuristic(start->x, start->y, maze->endX, maze->endY); start->parent = NULL;
    open[openCount++] = start;

    int dirs[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};

    while (openCount > 0) {
        // find best f = g + h
        int best = 0;
        for (int i = 1; i < openCount; i++) {
            if (open[i]->g + open[i]->h < open[best]->g + open[best]->h) best = i;
        }
        Node *cur = open[best];
        open[best] = open[--openCount];

        if (closed[cur->y][cur->x]) { free(cur); continue; }
        closed[cur->y][cur->x] = 1;
        (*expanded)++;

        if (cur->x == maze->endX && cur->y == maze->endY) {
            // reconstruct path into array
            Node *p = cur;
            int len = 0;
            while (p && len < maxpath) {
                path[len][0] = p->x;
                path[len][1] = p->y;
                len++;
                p = p->parent;
            }
            // mark path on grid
            for (int i = 0; i < len; i++) {
                int x = path[i][0], y = path[i][1];
                if (maze->grid[y][x] == ' ') maze->grid[y][x] = '.';
            }
            *pathLength = len;
            // free open list
            for (int i = 0; i < openCount; i++) free(open[i]);
            free(open);
            free(cur);
            return len;
        }

        for (int i = 0; i < 4; i++) {
            int nx = cur->x + dirs[i][0], ny = cur->y + dirs[i][1];
            if (nx >= 0 && ny >= 0 && nx < w && ny < h && maze->grid[ny][nx] != '#' && !closed[ny][nx]) {
                Node *n = malloc(sizeof(Node));
                n->x = nx; n->y = ny;
                n->g = cur->g + 1;
                n->h = heuristic(nx, ny, maze->endX, maze->endY);
                n->parent = cur;
                open[openCount++] = n;
            }
        }
    }

    free(open);
    return 0; // no path
}

player.h

#ifndef PLAYER_H
#define PLAYER_H
#include "maze_gen.h"

void playerPlay(Maze *maze, int *steps, double *timeUsed);

#endif

player.c

#include "player.h"
#include "display.h"
#include <stdio.h>
#include <time.h>

void playerPlay(Maze *maze, int *steps, double *timeUsed) {
    int x = maze->startX;
    int y = maze->startY;
    char buf[16];
    *steps = 0;
    clock_t t0 = clock();

    while (!(x == maze->endX && y == maze->endY)) {
        // clear screen and display
        printf("\x1b[2J\x1b[H");
        displayMazeWithPlayer(maze, x, y);
        printf("\nMove (W/A/S/D) and press Enter: ");
        if (fgets(buf, sizeof(buf), stdin) == NULL) continue;
        char move = buf[0];
        int nx = x, ny = y;
        if (move == 'W' || move == 'w') ny--;
        else if (move == 'S' || move == 's') ny++;
        else if (move == 'A' || move == 'a') nx--;
        else if (move == 'D' || move == 'd') nx++;
        else {
            printf("Invalid input. Use W/A/S/D.\n");
            continue;
        }

        // bounds & wall check
        if (nx < 0 || ny < 0 || nx >= maze->width || ny >= maze->height || maze->grid[ny][nx] == '#') {
            printf("Invalid move! There's a wall. Press Enter to continue...");
            fgets(buf, sizeof(buf), stdin);
            continue;
        }
        x = nx; y = ny; (*steps)++;
    }

    clock_t t1 = clock();
    *timeUsed = (double)(t1 - t0) / CLOCKS_PER_SEC;
    // final display
    printf("\x1b[2J\x1b[H");
    displayMazeWithPlayer(maze, x, y);
    printf("\n🎉 You escaped the maze in %d steps, %.2f seconds!\n", *steps, *timeUsed);
}

圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言