Untitled

 avatar
unknown
plain_text
2 months ago
8.7 kB
5
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
  #include <windows.h>  // For Sleep on Windows
  #define SLEEP(ms) Sleep(ms)
#else
  #include <unistd.h>   // For usleep on Linux/macOS
  #define SLEEP(ms) usleep((ms)*1000)
#endif

#define N 15

/*
 * Map legend (example):
 * '0' = obstacle
 * '1' = free/soil cell
 * '2' = start position
 * 'M' or '3' = mission spot(s) you must visit
 */

// Global map
char mapData[N][N];
int visited[N][N];
int startX, startY;

// For BFS or pathfinding
typedef struct {
    int r, c;
} Node;

// Directions: up, right, down, left
int dr[4] = {-1, 0, 1, 0};
int dc[4] = { 0, 1, 0,-1};

// Some “stats” to display
int fuelCost   = 0;  // each move can cost 1 fuel
int cellsScanned = 0; // how many distinct soil cells have been scanned

// Utility: clear screen and print map + stats
void printInterface() {
    // Clear screen
    #ifdef _WIN32
        system("cls");
    #else
        system("clear");
    #endif

    // Print map
    for(int i = 0; i < N; i++){
        for(int j = 0; j < N; j++){
            printf("%c ", mapData[i][j]);
        }
        printf("\n");
    }
    // Print “control panel”
    printf("\nFuel Used : %d\n", fuelCost);
    printf("Cells Scanned : %d\n", cellsScanned);
    printf("-----------------------\n");
}

// Check if (r, c) is inside the grid and not a '0'
int validCell(int r, int c) {
    if(r < 0 || r >= N || c < 0 || c >= N) return 0;
    if(mapData[r][c] == '0') return 0;
    return 1;
}

// BFS to find a path from (sr, sc) to (tr, tc).
// Returns path length, and fills path[] with the route in reverse order.
// If no path, returns -1.
int bfsPath(int sr, int sc, int tr, int tc, Node path[], int *pathLen) {
    if(sr == tr && sc == tc){
        *pathLen = 0; 
        return 0; // Already there
    }

    // Visited array for BFS
    int used[N][N];
    memset(used, 0, sizeof(used));

    // Parent array for reconstructing path
    Node parent[N][N];
    for(int i=0; i<N; i++){
        for(int j=0; j<N; j++){
            parent[i][j].r = -1;
            parent[i][j].c = -1;
        }
    }

    // BFS queue
    Node queue[N*N];
    int front=0, back=0;

    queue[back++] = (Node){sr, sc};
    used[sr][sc] = 1;

    // BFS
    while(front < back) {
        Node u = queue[front++];
        for(int i=0; i<4; i++){
            int rr = u.r + dr[i];
            int cc = u.c + dc[i];
            if(validCell(rr, cc) && !used[rr][cc]){
                used[rr][cc] = 1;
                parent[rr][cc] = u;
                queue[back++] = (Node){rr, cc};
                if(rr == tr && cc == tc) {
                    // Found it! Reconstruct path
                    int len=0;
                    Node cur = (Node){tr, tc};
                    while(cur.r != -1) {
                        path[len++] = cur;
                        cur = parent[cur.r][cur.c];
                    }
                    *pathLen = len;
                    return len;
                }
            }
        }
    }
    // Not found
    return -1;
}

// Move step-by-step along the path
// Mark each step with '*' in the map (except final mission spot if you want it intact)
void moveAlongPath(Node path[], int pathLen) {
    // The path[] is in reverse order (end -> start).
    // We want to traverse from start to end:
    for(int i = pathLen - 1; i >= 0; i--) {
        int r = path[i].r;
        int c = path[i].c;

        // “Move” to (r, c)
        // If it's not the starting cell and not a mission spot, mark visited
        if(mapData[r][c] != '2' && mapData[r][c] != 'M' && mapData[r][c] != '3') {
            mapData[r][c] = '*';
        }

        // Use 1 fuel
        fuelCost++;

        // If we are stepping onto a new soil (or mission spot), increment scanned
        // (You could refine logic if you only want to count '1' or 'M' once.)
        if(!visited[r][c]) {
            visited[r][c] = 1;
            cellsScanned++;
        }

        // Show the step
        printInterface();

        // Delay a bit so user can see the movement
        SLEEP(300);
    }
}

// Find all mission spots (M or '3') and store them in an array
// Returns how many mission spots found
int findMissions(Node missions[]) {
    int count = 0;
    for(int i=0; i<N; i++){
        for(int j=0; j<N; j++){
            if(mapData[i][j] == 'M' || mapData[i][j] == '3'){
                missions[count++] = (Node){i, j};
            }
        }
    }
    return count;
}

// Euclidean or Manhattan distance (for “closest” mission)
int manhattanDist(int r1, int c1, int r2, int c2){
    return abs(r1 - r2) + abs(c1 - c2);
}

// Simple function to do “coverage” BFS (or “lawnmower”) after missions
// so you can show scanning of all soil cells. This is just a simple BFS from start.
void coverageBFS(int sr, int sc) {
    // Standard BFS
    int used[N][N];
    memset(used, 0, sizeof(used));
    Node queue[N*N];
    int front=0, back=0;

    queue[back++] = (Node){sr, sc};
    used[sr][sc] = 1;

    while(front < back) {
        Node u = queue[front++];
        for(int i=0; i<4; i++){
            int rr = u.r + dr[i];
            int cc = u.c + dc[i];
            if(validCell(rr, cc) && !used[rr][cc]){
                used[rr][cc] = 1;

                // Step onto (rr, cc)
                // Mark path if not 'M', '3', or '2'
                if(mapData[rr][cc] != 'M' && mapData[rr][cc] != '3' && mapData[rr][cc] != '2') {
                    mapData[rr][cc] = '*';
                }
                fuelCost++;
                if(!visited[rr][cc]) {
                    visited[rr][cc] = 1;
                    cellsScanned++;
                }
                printInterface();
                SLEEP(200);

                queue[back++] = (Node){rr, cc};
            }
        }
    }
}

// Read map from file
void readMap(const char *filename){
    FILE *fp = fopen(filename, "r");
    if(!fp){
        printf("Cannot open %s\n", filename);
        exit(1);
    }

    int foundStart = 0;
    for(int i=0; i<N; i++){
        fscanf(fp, "%s", mapData[i]);
        if(strlen(mapData[i]) < N){
            printf("Each row in the map file must have %d chars.\n", N);
            fclose(fp);
            exit(1);
        }
        for(int j=0; j<N; j++){
            if(mapData[i][j] == '2'){
                startX = i;
                startY = j;
                foundStart = 1;
            }
        }
    }
    fclose(fp);

    if(!foundStart){
        printf("No start cell ('2') found in the map!\n");
        exit(1);
    }
}

int main() {
    const char *filename = "input.txt";

    // 1) Read map and init
    readMap(filename);
    memset(visited, 0, sizeof(visited));

    // Mark the start as visited
    visited[startX][startY] = 1;
    cellsScanned = 1; // We start on '2'
    fuelCost = 0;

    // 2) Print initial
    printInterface();

    // 3) Find all mission spots
    Node missions[100];
    int missionCount = findMissions(missions);

    // Current robot position
    int currR = startX;
    int currC = startY;

    // 4) While missions remain, pick the closest one (by Manhattan distance),
    //    BFS to it, remove it from the list.
    while(missionCount > 0) {
        // Find the nearest mission
        int bestIdx = 0;
        int bestDist = 999999;
        for(int i=0; i<missionCount; i++){
            int dist = manhattanDist(currR, currC, missions[i].r, missions[i].c);
            if(dist < bestDist){
                bestDist = dist;
                bestIdx = i;
            }
        }
        // BFS from (currR, currC) to that mission
        Node path[500];
        int pathLen=0;
        int rTarg = missions[bestIdx].r;
        int cTarg = missions[bestIdx].c;
        int found = bfsPath(currR, currC, rTarg, cTarg, path, &pathLen);
        if(found == -1){
            // No path to that mission; skip it or break
            printf("No path to mission at (%d,%d). Skipping.\n", rTarg, cTarg);
        } else {
            // Follow the path
            moveAlongPath(path, pathLen);
            // We end on that mission cell
            currR = rTarg;
            currC = cTarg;
        }

        // Remove this mission from the array (swap with last, missionCount--)
        missionCount--;
        missions[bestIdx] = missions[missionCount];
    }

    // 5) After all missions are visited, do a coverage BFS from the final position
    coverageBFS(currR, currC);

    // 6) Final output
    printf("All missions visited (or attempted).\n");
    printf("Coverage BFS done.\n");
    printInterface();  // show final state
    printf("Program finished.\n");

    return 0;
}
Leave a Comment