Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Motivating scenario Suppose you have been hired by Amazon to build a package del

ID: 3676122 • Letter: M

Question

Motivating scenario

Suppose you have been hired by Amazon to build a package delivery robot. The goal of the robot is to deliver packages to addresses. To cut down on operational and maintenance costs, the robot should follow the shortest path between the packing station and the specified addresses.

Figure 1: Mail delivery paths with nine different addresses, where packages may have to be delivered.

Your tasks

As a starting point, you will write a regular C program to simulate the robot on a computer in this homework assignment. You will program this on the 3pi robot in HW4. The program will consist of three main modes: (a) Track Learning, (b) Getting delivery addresses, and (c) Delivery, described below. Following track learning, the robot will execute an infinite loop after track learning, where it repeats steps (b) and (c). You can terminate the program using the key combination Ctrl+C.

Track learning: Assuming the robot is placed on track at the dispatch station facing away from the station) the robot traverses the entire track in the clockwise direction and learns the track.

During the track learning phase, the robot will follow a left-hand-on-wall strategy. If the robot is not at a junction (straight path is available, and it is not possible to turn right or left), it moves straight. If it is at a junction (i.e left turn or right turn is available), the robot first attempts a left turn (L), and if that is not possible, it attempts to go straight (S), and if that is not possible, it attempt a right turn (R). If none of these options are available, it will perform a U turn (U). The robot traverses through the entire path once in the clockwise direction, while recording the sequence of turns at the junctions in an array. Specifically, at the junctions (when decisions have to be made) the program keeps record of the track in terms of left (L), right (R), straight (S), and U turns (U). Note that straight turns are recorded only at junctions. At the end of this step, a character array indicating the geometry of the track (eg “LRLULRLLR ..”) will be generated. The track and the starting position of the robot is specified in an input text file provided as a command-line argument to the program. You may assume that the maximum number of turns in the maze is 300.

Getting delivery addresses: At the end of the learning process, the robot will return to the dispatch station. It will then wait for the user input. The user will provide a list of addresses (between 0 and the maximum # addresses), not necessarily in a sorted order. The robot should record the list of addresses in a sorted order in an array. If the user enters an address twice, the robot should print a message indicating that the address was already entered and discard it. Since the onboard memory

on the robot is limited, you should determine the maximum number of delivery addresses during the learning phase and dynamically allocate memory.

Delivery: Once the delivery addresses are obtained from the user, the robot have to travel from the dispatch to the specified addresses in the clockwise sense through the shortest route (i.e, by skipping the visit to the addresses not in the list of delivery addresses). You may use the function initMazeAndRobotFromCLArgs to initialize the location of the robot to simulate the user picking up the 3 pi robot, entering the addresses, and placing it back at the initial location.

The addresses to which there is no delivery need to be skipped. The main component of this step is to determine the shortest path from the dispatch to the specified addresses and back. Starting with the complete path learned in Step 1, the program should generate an optimized path. For example, if the target addresses are 5 & 7, it should skip all other addresses in the clockwise traversal. The program will compute the optimal path and display it using the printTurns function. Then the robot will traverse the optimal path, one step at a time (use getch() to wait for user press), until it reaches the specified station. Since the onboard memory on the robot is limited, you should dynamically allocate memory to store the optimized path.

Your program should be written in the hw3.cpp file in your homework/HW3 directory. You are also required to include standard documentation blocks above any functions that you may use and at the top of your file. In your top documentation block, please also include high-level pseudocode for your program.

You can compile the program using the included codeblocks projects or from command line. Your program should be written so that it will work with any maze. To ensure this, the program need to be tested using the mazes in maze.txt and largeMaze.txt. Since the first maze is smaller, it may be easier to work with during the development of your program. Your submission will be tested using a different maze.

Helper functions provided to you

To help you writing the program, you are provided with the following helper functions:

Part 1: Track learning

The functions

•    blackToLeft

•    blackToRight

•    blackInFront

•    onBlack

returns the robot sensor readings based on the position of the robot (value of the members of the robot structure: row and col) and the shape of the path (value of the member of the maze structure: mazearray). You need to check these sensors to determine the next step of the path. Based on the status of the above sensor readings, you need to use one of the following functions to move the robot on the track.

•    moveStraight

•    uTurn

•    turnLeft

•    turnRight

These functions update the members of the robot structure (i.e., row, col, and dir) to change the position or the direction of the robot. Following the update of the data, you need to call printMazePlusCurrentPos to display the current state of the maze and robot, followed by getch() to wait for key press. See description of these functions below.

Part 2: Getting delivery addresses:

You may use the insertion sort program developed in lect12ma to sort the array. You also need to check if an address has been entered previously.

Part 3: Delivery to the addresses

The function

copyAndSimplify copies the path of length numturns from inturns to outturns and simplifies it. Specifically, it will delete segments corresponding to visit to addresses involving U turns. It will return the length of the optimized path. This function may need to be called several times with different arguments to obtain the optimized path. Although, the function copyAndSimplify is provided to you, we strongly recommend that you try to understand how the function works. Additional descriptions are provided in the documentation of the function simplifyTurns to help you understand the logic. You can also refer to its use in in examples-libpololu-avr/3pi-mazesolver/maze-solve.c

The function

printMazePlusCurrentPos prints the maze and the position of the robot in the maze.

The function

getch() waits for the user to input a character from the keyboard. Using this function in each step of the program enables the visualization of the maze traversal step by step. If this line is not used, the program will execute all the steps before the screen is refreshed; only the last state of the maze and robot will be displayed on the screen.

Explanation / Answer

main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "useCurses.h"
#include "robotModel.h"
#include "maze.h"

/* function prototypes */
int initMazeAndRobotFromCLArgs(int argc, char *argv[], Maze *maze, RobotModel *robot);
int copyAndSimplify(char *inturns, char *outturns, int numturns);
int simplifyTurns(char *turns, int *numTurns);
int inDispatch(Maze maze, RobotModel robot);
int in_array(const int *arr, int arr_size, int test);
void sort_array(int *arr, int arr_size);


int main( int argc, char *argv[] )
{
    // Maze and related variables
    Maze maze;              /* structure to store maze */
    RobotModel robot;       /* structure to model robot (current position + direction) */
    char c;

    // ADDITIONAL VARIABLES
    int moves = 0;                  // Count the number of moves we've made
    int mailbox = -2;               // User-supplied mailbox number
    int addresses = 0;              // Count the number of addresses we've encountered
    int turns = 0;                  // Count the turns
    char path[300] = {NULL};        // Save the path
    int disp = 0;                   // Hack to center bot in dispatch upon returning
    int *delivery_addresses;        // Array to store delivery addresses
    char *optimized_path;           // Optimized path array

    /* initialize curses mode... */
    initscr();
    /* ...with color!! */
    start_color();
    init_pair(1, COLOR_GREEN, COLOR_BLACK);
    init_pair(2, COLOR_BLACK, COLOR_RED);
    /* (requires changes in maze.cpp as well) */

    // Allow user to resize window for large maze
    printw(" You may want to resize the window to 160x60 for the large maze. ");
    printw(" Then press 's' and hit Return to start: ");
    do scanw("%c", &c);
    while (c != 's');

    // If successfully have initialized robot and maze, solve maze
    if (initMazeAndRobotFromCLArgs(argc, argv, &maze, &robot))
    {

        int done = 0;   // When we've learned the track, exit the loop

        while (!done)
        {
            // Draw maze + robot in its current position (redraws every loop!)
            clear();
            printMazePlusCurrentPos(maze, robot);

            // Print welcome message
            printw(" *** Robot Mail Delivery Game! *** ");
            attron(COLOR_PAIR(1));
            printw(" ** PART 1: Learning the Route ** ");
            attroff(COLOR_PAIR(1));

            // Print number of steps, turns & addresses tallied
            printw(" Steps: %d", moves);
            printw(" Turns: %d", turns);
            printw(" Mailboxes: %d ", addresses);

            // Are we in the dispatch station?
            if (inDispatch(maze, robot) == 1)
            {
                if (moves > 50) printw(" Back in the dispatch station! ");
                else printw(" In the dispatch station! ");
            }
            else
            {
                printw(" Exploring the route... ");
            }
            printw(" Press (and/or hold) spacebar to move: ");
            c = getch();
            if (c != ' ') continue;

            // If we're in the dispatch station...
            // (This logic assumes that the robot is 'pointed' toward the exit)
            if (inDispatch(maze, robot) == 1)
            {
                // If we've returned to dispatch after traveling a bit, exit the loop
                if (moves > 50)
                {
                    disp++; // take one more step after entering
                    if (disp > 1) done = 1;
                }
                // Go straight to exit/enter dispatch
                moveStraight(&robot);
            }

            // If left turn available, go fast & turn left (aka "the NASCAR algorithm")
            else if (onBlack(maze, robot) == 1 && blackToLeft(maze, robot) == 1)
            {
                turnLeft(&robot);
                turns++;
                path[turns] = 'L';
            }

            // If no left turn available, try going straight
            else if (onBlack(maze, robot) == 1 && blackInFront(maze, robot) == 1)
            {
                moveStraight(&robot);
                // Don't count straights in path[]
            }

            // If only a right turn is available, turn right
            else if (onBlack(maze, robot) == 1 && blackToRight(maze, robot) == 1)
            {
                turnRight(&robot);
                turns++;
                path[turns] = 'R';
            }

            // If we're at an address, make a u-turn & tag the address
            else if (onBlack(maze, robot) == 1 &&
                    blackInFront(maze, robot) == 0 &&
                    blackToLeft(maze, robot) == 0 &&
                    blackToRight(maze, robot) == 0)
            {
                uTurn(&robot);
                turns++;
                path[turns] = 'U';
                // Tag a new address
                addresses++;
            }

            moves++;
        }

        clearMaze(&maze);
    }
    else
    {
        endwin();
        printf(" ** Error initializing maze and robot. ** ");
        printf(" **        Program terminated.         ** ");
        exit(1);
    }

    // Print the solved maze info
    printw(" Route familiarization complete!");
    printw(" Turns made: ");
    for (int i=0; i<300; i++)
    {
        printw("%c", path[i]);
    }

    // Wait for input
    printw(" Press 'c' and hit Return to to continue the game: ");
    do scanw("%c", &c);
    while (c != 'c');
    // Array to hold delivery addresses
    delivery_addresses = (int *) malloc(addresses * sizeof(int));

    for (int i=0; i<addresses; i++)
    {
        delivery_addresses[i] = -1;
    }

    if (initMazeAndRobotFromCLArgs(argc, argv, &maze, &robot))
    {
        int j = 0; // array iterator
        int loop = 0; // # times through the loop (used in error messages logic)

        while (mailbox != -1)
        {
            // Draw maze + robot in its current position (redraws every loop!)
            clear();
            printMazePlusCurrentPos(maze, robot);

            // Print welcome message
            printw(" *** Robot Mail Delivery Game *** ");
            attron(COLOR_PAIR(1));
            printw(" ** PART 2: Getting Delivery Addresses ** ");
            attroff(COLOR_PAIR(1));

            // Print instructions
            printw(" Below, enter several mailbox numbers (integers between 0 and %d)", addresses-1);
            printw(" to which you'd like the robot to deliver the mail. ");

            // Handle input errors from previous loop
            if (mailbox >= addresses || mailbox < -1)
            {
                if (loop != 0)
                {
                    printw(" ");
                    attron(COLOR_PAIR(2));
                    printw(" ERROR: Mailbox %d is out of range ", mailbox);
                    attroff(COLOR_PAIR(2));
                }
            }
            else if (in_array(delivery_addresses, addresses, mailbox))
            {
                printw(" ");
                attron(COLOR_PAIR(2));
                printw(" ERROR: You've already selected Mailbox %d ", mailbox);
                attroff(COLOR_PAIR(2));
            }
            else
            {
                delivery_addresses[j] = mailbox;
                j++;
            }

            // Print selected addresses
            printw(" Selected mailboxes: ");
            for (int i=0; i<addresses; i++)
            {
                if (delivery_addresses[i] != -1)
                {
                    printw("%d ", delivery_addresses[i]);
                }
                else
                {
                    printw("__ ");
                }
            }

            // Query user for new address
            printw(" Type a new mailbox number (or -1 if you're done) and press Return: ");
            scanw("%d", &mailbox);

            loop++;
        }
    }
    else
    {
        endwin();
        printf(" ** Error initializing maze and robot. ** ");
        printf(" **        Program terminated.         ** ");
        exit(1);
    }

    // Sort the Delivery Addresses array
    sort_array(delivery_addresses, addresses);
    // Array to hold optimized path
    optimized_path = (char *) malloc(turns * sizeof(char));

    // Number of turns in optimized path
    int optimized_turns;

    // Haul the mail
    if (initMazeAndRobotFromCLArgs(argc, argv, &maze, &robot))
    {
        int done = 0;
        int disp = 0;
        int moves = 0;
        int out_turns = 1;
        int count_u;

        int t = 1; // should I move this out of the loop?

        int stop = 0; // count how many stops we've made
        while (delivery_addresses[stop] == -1)
        {
            // The first, non-negative address is our first stop
            stop++;
        }

        while (!done)
        {
            // Draw maze + robot in its current position (redraws every loop!)
            clear();
            printMazePlusCurrentPos(maze, robot);

            // Print welcome message
            printw(" *** Robot Mail Delivery Game *** ");
            attron(COLOR_PAIR(1));
            printw(" ** PART 3: Haulin' the Mail ** ");
            attroff(COLOR_PAIR(1));

            // Print selected addresses
            printw(" Mailbox addresses to visit: ");
            for (int i=0; i<addresses; i++)
            {
                if (delivery_addresses[i] != -1)
                {
                    printw("%d ", delivery_addresses[i]);
                }
            }

            printw(" ");
            char * ptr2path = path[t];

            count_u = -1;
          
            while (t<turns)
            {
                if (ptr2path[t] == 'U') count_u++;
                if (count_u == delivery_addresses[stop]) break;
                t++;
            }

            printw(" Original route to mailbox #%d: ", delivery_addresses[stop]);

            for (int i=0; i < t; i++)
            {
                printw("%c", path[i]);
            }

            // Plan route to current address
            optimized_turns = copyAndSimplify(ptr2path, optimized_path, t+1);
            // Print optimized path
            printw(" Optimized route to mailbox #%d: ", delivery_addresses[stop]);
            for (int i=0; i < optimized_turns; i++)
            {
                printw("%c", optimized_path[i]);
            }

            // Let's GO!!!
            printw(" Press (and/or hold) spacebar to move: ");
            c = getch();
            if (c != ' ') continue;

            // If we're in the dispatch station...
            // (This logic assumes that the robot is 'pointed' toward the exit)
            if (inDispatch(maze, robot) == 1)
            {
                // If we've returned to dispatch after traveling a bit, exit the loop
                if (moves > 50)
                {
                    disp++; // take one more step after entering
                    if (disp > 1) done = 1;
                }
                // Go straight to exit/enter dispatch
                moveStraight(&robot);
            }

            // On a straightaway...
            else if (onBlack(maze, robot) == 1 &&
                     blackInFront(maze, robot) == 1 &&
                     blackToLeft(maze, robot) == 0 &&
                     blackToRight(maze, robot) == 0
                     )
            {
                moveStraight(&robot);
            }

            // Otherwise, use the optimized path
            else
            {
                if (optimized_path[out_turns] == 'L')
                {
                    turnLeft(&robot);
                    out_turns++;
                }
                else if (optimized_path[out_turns] == 'R')
                {
                    turnRight(&robot);
                    out_turns++;
                }
                else if (optimized_path[out_turns] == 'S')
                {
                    moveStraight(&robot);
                    out_turns++;
                }
                else if (optimized_path[out_turns] == 'U')
                {
                    uTurn(&robot);
                    out_turns++;
                    // Go to the next stop
                    stop++;
                }
            }

            moves++;
        }

        clearMaze(&maze);
    }
    else
    {
        endwin();
        printf(" ** Error initializing maze and robot. ** ");
        printf(" **        Program terminated.         ** ");
        exit(1);
    }

    // Done delivering
    attron(COLOR_PAIR(1));
    printw(" All deliveries complete!");
    attroff(COLOR_PAIR(1));

    // Wait for quit input
    printw(" Press 'q' and hit Return to to quit: ");
    do scanw("%c", &c);
    while (c != 'q');

    endwin();
    return 0;
}
int inDispatch(Maze maze, RobotModel robot)
{
    if (onBlack(maze, robot) == 1 && blackInFront(maze, robot) == 1 &&
        blackToRight(maze, robot) == 1 && blackToLeft(maze, robot) == 1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

int in_array(const int *arr, int arr_size, int test)
{
    for(int i=0; i < arr_size; i++)
    {
        if (arr[i] == test) return 1;
    }
    return 0;
}
void sort_array(int *arr, int arr_size)
{
    int i, j, temp;
  
    for(i=1; i <= arr_size-1; i++)
    {
        j = i;

        while(j > 0 && arr[j] < arr[j-1])
        {
            /* Swap! */
            temp = arr[j];
            arr[j] = arr[j-1];
            arr[j-1] = temp;
            j--;
        }
    }
}

int initMazeAndRobotFromCLArgs(int argc, char *argv[], Maze *maze, RobotModel *robot)
{
    int success = 1;
    char *inputFileName;    /* input file name containing maze */
    /* obtain input filename from command line */
    if (argc >= 2) /* require at least two command-line arguments */
    {
        inputFileName = argv[1];
    }
    else
    {
        /* when incorrect number of command-line arguments are passed,
           print message indicating proper usage of program */
        printw("Usage: %s inputFileName.txt ", argv[0]);
        success = 0;
    }

    if (success)
    {
        success = readMaze(inputFileName, maze, robot);
    }

    return success;
}
int copyAndSimplify(char *inturns, char *outturns, int numturns)
    {
        int i;
        int optturns = 0;
        for (i=0; i<numturns; i++) {
            outturns[optturns] = inturns[i];
            optturns++;
            simplifyTurns(outturns, &optturns);
        }
        return(optturns);
    }
int simplifyTurns(char *turns, int *numTurns)
{
    int done = 1;
    int n = *numTurns;
    if (n >= 3 && turns[n-2] == 'U')
    {
        int total_angle = 0;
        int i;
        for (i=1; i<=3; i++)
        {
            switch(turns[n-i])
            {
                case 'R':
                    total_angle += 90;
                    break;
                case 'L':
                    total_angle += 270;
                    break;
                case 'U':
                    total_angle += 180;
                    break;
            }
        }

        total_angle = total_angle % 360;

        switch(total_angle)
        {
            case 0:
                turns[n-3] = 'S';
                break;
            case 90:
                turns[n-3] = 'R';
                break;
            case 180:
                turns[n-3] = 'U';
                done = 0;
                break;
            case 270:
                turns[n-3] = 'L';
                break;
        }

        *numTurns = *numTurns - 2;
     }
    return(done);

}

largeMaze.txt
40 50

11 8 1

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 8 8 8 8 0 0 0 0 8 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0


maze.cpp
/* set to zero if you aren't using curses */
#define CURSESPRINT 1

#include "maze.h"
#include <stdio.h>
#include <stdlib.h>
#if CURSESPRINT /* if using curses */
#include "useCurses.h"    /* include header */
#define PRINT printw      /* define macro for printing in curses */
#define MOVE00 move(0,0); /* define macro for calling move(0,0); */
#else /* if not using curses */
#define PRINT printf /* define macro for printing using printf */
#define MOVE00       /* define MOVE00 macro to do nothing */
#endif

int readMaze(const char *fileName, Maze *m, RobotModel *robot)
{
    int r, c;           /* current row and column indices */
    FILE *inputFile;    /* file pointer to input file */
    int success = 0;    /* whether we succeeded */

    /* open input file */
    inputFile = fopen(fileName, "r");

    /* fill data array */
    if (inputFile != NULL)
    {
        fscanf(inputFile, "%d %d", &(m->rows), &(m->cols));
        fscanf(inputFile, "%d %d %d", &(robot->row), &(robot->col), &(robot->dir));
        m->mazeArray = (int *) malloc((m->rows)*(m->cols)*sizeof(int));
        int *arr = m->mazeArray;
        success = 1;
        for (r = 0; r < m->rows; r++)
        {
            for (c = 0; c < m->cols; c++)
            {
                if (fscanf(inputFile, "%d", &(arr[r*m->cols + c])) == EOF)
                {
                    success = 0;
                }
            }
        }

        fclose(inputFile);
    }
    else {

   printw(" ** Couldn't open maze file! ** ");
    }

    return success;
}

void clearMaze(Maze *m)
{
    if (m->mazeArray != NULL)
    {
        free(m->mazeArray);
        m->mazeArray = NULL;
    }

    m->rows = 0;
    m->cols = 0;
}

void printMazePlusCurrentPos(Maze m, RobotModel robot)
{
    MOVE00 /* move(0,0); in curses mode */
    int r, c;
    for (r=0; r < m.rows; r++)
    {
        for (c=0; c < m.cols; c++)
        {
            if (r == robot.row && c == robot.col)
            {
                /* the 3pi robot - in color! */
                attron(COLOR_PAIR(1));
                PRINT("@");
                attroff(COLOR_PAIR(1));
                PRINT(" ");
            }
            else if (m.mazeArray[r*m.cols + c] > 0)
            {
                PRINT(". ");
            }
            else
            {
                PRINT(" ");
            }
        }
        PRINT(" ");
    }
}


int blackToLeft(Maze m, RobotModel robot)
{
    int bToL = 0;

    if ((robot.dir == 0 && m.mazeArray[(robot.row-1)*m.cols + robot.col ] > 0) ||   /* moving in increasing column direction */
        (robot.dir == 1 && m.mazeArray[    robot.row*m.cols + robot.col-1] > 0) ||   /* moving in decreasing row direction */
        (robot.dir == 2 && m.mazeArray[(robot.row+1)*m.cols + robot.col ] > 0) ||   /* moving in decreasing column direction */
        (robot.dir == 3 && m.mazeArray[    robot.row*m.cols + robot.col+1] > 0) )    /* moving in increasing row direction */
    {
        bToL = 1;
    }

    return bToL;
}

int blackToRight(Maze m, RobotModel robot)
{
    int bToR = 0;

    if ((robot.dir == 0 && m.mazeArray[(robot.row+1)*m.cols + robot.col ] > 0) ||   /* moving in increasing column direction */
        (robot.dir == 1 && m.mazeArray[    robot.row*m.cols + robot.col+1] > 0) ||   /* moving in decreasing row direction */
        (robot.dir == 2 && m.mazeArray[(robot.row-1)*m.cols + robot.col ] > 0) ||   /* moving in decreasing column direction */
        (robot.dir == 3 && m.mazeArray[    robot.row*m.cols + robot.col-1] > 0))     /* moving in increasing row direction */
    {
        bToR = 1;
    }

    return bToR;
}

int blackInFront(Maze m, RobotModel robot)
{
    int bInF = 0;

    if ((robot.dir == 0 && m.mazeArray[    robot.row*m.cols + robot.col+1] > 0) ||   /* moving in increasing column direction */
        (robot.dir == 1 && m.mazeArray[(robot.row-1)*m.cols + robot.col ] > 0) ||   /* moving in decreasing row direction */
        (robot.dir == 2 && m.mazeArray[    robot.row*m.cols + robot.col-1] > 0) ||   /* moving in decreasing column direction */
        (robot.dir == 3 && m.mazeArray[(robot.row+1)*m.cols + robot.col ] > 0))     /* moving in increasing row direction */
    {
        bInF = 1;
    }

    return bInF;
}

int onBlack(Maze m, RobotModel robot)
{
    int>     if (m.mazeArray[robot.row*m.cols + robot.col] > 0)
    {
       >     }

    return onB;
}

maze.h
#ifndef MAZE_H
#define MAZE_H

#include "robotModel.h"

/* struct maze is a data type to model a robot maze */
struct maze {
    int *mazeArray; /* array to store maze */
    int rows;       /* number of rows of maze */
    int cols;       /* number of columns of maze */
};

typedef struct maze Maze; /* new type name for struct maze */

struct deadEnd {
    int row;
    int col;
    int dir;
    int turn;
    int pathIndex;
};
typedef struct deadEnd DeadEnd;
int readMaze(const char *fileName, Maze *m, RobotModel *robot);
void clearMaze(Maze *m);
void printMazePlusCurrentPos(Maze m, RobotModel robot);
int blackToLeft(Maze m, RobotModel robot);
int blackToRight(Maze m, RobotModel robot);
int blackInFront(Maze m, RobotModel robot);
int onBlack(Maze m, RobotModel robot);


#endif // MAZE_H

maze.txt
16 30

8 3 1

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 0 0 0 0 0 0
0 0 0 8 8 8 8 8 8 8 8 8 8 8 0 0 0 8 0 0 0 0 0 8 0 0 0 0 0 0
0 0 0 8 0 0 0 0 0 0 0 0 0 8 0 0 0 8 0 0 0 0 0 8 8 8 8 8 0 0

robotModel.cpp
#include "robotModel.h"

void moveStraight(RobotModel *robot)
{
    if (robot->dir == 0)
    {
        (robot->col)++;
    }
    else if (robot->dir == 1)
    {
        (robot->row)--;
    }
    else if (robot->dir == 2)
    {
        (robot->col)--;
    }
    else if (robot->dir == 3)
    {
        (robot->row)++;
    }
}

void turnLeft(RobotModel *robot)
{
    if (robot->dir == 0)
    {
        (robot->row)--;
        robot->dir = 1;
    }
    else if (robot->dir == 1)
    {
        (robot->col)--;
        robot->dir = 2;
    }
    else if (robot->dir == 2)
    {
        (robot->row)++;
        robot->dir = 3;
    }
    else if (robot->dir == 3)
    {
        (robot->col)++;
        robot->dir = 0;
    }
}

void turnRight(RobotModel *robot)
{
    if (robot->dir == 0)
    {
        (robot->row)++;
        robot->dir = 3;
    }
    else if (robot->dir == 1)
    {
        (robot->col)++;
        robot->dir = 0;
    }
    else if (robot->dir == 2)
    {
        (robot->row)--;
        robot->dir = 1;
    }
    else if (robot->dir == 3)
    {
        (robot->col)--;
        robot->dir = 2;
    }
}

void uTurn(RobotModel *robot)
{
    if (robot->dir == 0)
    {
        (robot->col)--;
        robot->dir = 2;
    }
    else if (robot->dir == 1)
    {
        (robot->row)++;
        robot->dir = 3;
    }
    else if (robot->dir == 2)
    {
        (robot->col)++;
        robot->dir = 0;
    }
    else if (robot->dir == 3)
    {
        (robot->row)--;
        robot->dir = 1;
    }
}

void reverse(RobotModel *robot)
{
    if (robot->dir == 0)
    {
        (robot->col)--;
    }
    else if (robot->dir == 1)
    {
        (robot->row)++;
    }
    else if (robot->dir == 2)
    {
        (robot->col)++;
    }
    else if (robot->dir == 3)
    {
        (robot->row)--;
    }
}

robotModel.h
#ifndef ROBOTMODEL_H
#define ROBOTMODEL_H


/* struct robotModel is a data type to model a robot */
struct robotModel {
    int row; /* current row position */
    int col; /* current column position */
    int dir; /* current direction (0=East ->, 1=North ^, 2=West <-, 3=South v) */
};

typedef struct robotModel RobotModel; /* new type name for struct robotModel */
void moveStraight(RobotModel *robot);
void turnLeft(RobotModel *robot);
void turnRight(RobotModel *robot);
void uTurn(RobotModel *robot);
void reverse(RobotModel *robot);


#endif // ROBOTMODEL_H

simpleMaze.txt
16 30

8 3 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 0 0 0 0 0 0
0 0 0 0 0 0 8 8 8 8 8 8 8 8 0 0 0 8 0 0 0 0 0 8 0 0 0 0 0 0

useCurses.h
#ifndef USECURSES_H
#define USECURSES_H

#ifndef WIN32
#include <ncurses.h> /* for linux/mac */
#else
//#include "pdcurses/curses.h" /* for windows */
#endif

#endif

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote