From c5f514229bbbe21af8f641afc8c822e5b0f04aa2 Mon Sep 17 00:00:00 2001 From: aj Date: Sat, 9 Feb 2019 18:50:58 +0000 Subject: [PATCH] initial commit --- assessment1date/date1.c | 106 +++++++++ assessment1date/date2.c | 139 ++++++++++++ assessment1date/date3.c | 208 +++++++++++++++++ assessment2employee/employee1.c | 295 ++++++++++++++++++++++++ assessment2employee/employee2.c | 336 +++++++++++++++++++++++++++ assessment2employee/employee3.c | 391 ++++++++++++++++++++++++++++++++ assessment3gameOfLife/life1.c | 248 ++++++++++++++++++++ assessment3gameOfLife/life2.c | 251 ++++++++++++++++++++ assessment3gameOfLife/life3.c | 307 +++++++++++++++++++++++++ 9 files changed, 2281 insertions(+) create mode 100644 assessment1date/date1.c create mode 100644 assessment1date/date2.c create mode 100644 assessment1date/date3.c create mode 100644 assessment2employee/employee1.c create mode 100644 assessment2employee/employee2.c create mode 100644 assessment2employee/employee3.c create mode 100644 assessment3gameOfLife/life1.c create mode 100644 assessment3gameOfLife/life2.c create mode 100644 assessment3gameOfLife/life3.c diff --git a/assessment1date/date1.c b/assessment1date/date1.c new file mode 100644 index 0000000..09d936e --- /dev/null +++ b/assessment1date/date1.c @@ -0,0 +1,106 @@ +#include +#include +#include + +struct _date { + int day; + int month; + int year; +}; + +typedef struct _date date; + +date getDate(); +int dateDiff(date date1, date date2); + +main(){ + + date date1 = getDate(); + date date2 = getDate(); + + int diff = dateDiff(date1, date2); + + printf("%i\n", diff); + +} + +/* + getDate function to get user entry of a valid date and + returns a date variable type +*/ +date getDate(){ + date entrydate = {0,0,0}; + int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + char mark[2]; + + /* + loop to get entry of date that quits when a valid date is given + should only run once if a valid date is entered, any errors result in continue statement + */ + while(1){ + + char input[12]; + + scanf("%s", input); + + sscanf(input,"%i%c%i%c%i", &entrydate.day, &mark[0], &entrydate.month, &mark[1], &entrydate.year); + //printf("%i\t%i\t%i\n", entrydate.day, entrydate.month, entrydate.year); + + if(mark[0] != mark[1]) + { + fprintf(stderr, "ERROR: Use Consistent Delimeters\n"); + continue; + } + + if(mark[0] != '/' && mark[0] != '-') + { + fprintf(stderr, "ERROR: Use either / or - as delimiters\n"); + continue; + } + + if(entrydate.year > 10000 | entrydate.year < 1) + { + fprintf(stderr, "ERROR: Enter A Valid Year, Less than 10000 and Greater Than 0\n"); + continue; + } + + if(entrydate.month > 12 | entrydate.year < 1) + { + fprintf(stderr, "ERROR: Enter A Valid Month\n"); + continue; + } + + //checks that day entered is not outside range for month + if(entrydate.day > days[(entrydate.month) - 1] | entrydate.day < 1) + { + fprintf(stderr, "ERROR: Enter A Valid Day For The Month Entered\n"); + continue; + } + + break; + } + + return entrydate; +} + +/* + Function to find difference between two dates + + Calculated based on turning dates into number of days since 0/0/0000 + and finding difference between these two numbers +*/ +int dateDiff(date date1, date date2){ + + int date1day = 0, date2day = 0; + int days[] = {0,31,59,90,120,151,181,212,243,273,304,334}; //Cumulative Day Array + + date1day += date1.day; + date1day += days[(date1.month) - 1]; + date1day += (365*(date1.year)); + + date2day += date2.day; + date2day += days[(date2.month) - 1]; + date2day += (365*(date2.year)); + + return (date2day - date1day); +} diff --git a/assessment1date/date2.c b/assessment1date/date2.c new file mode 100644 index 0000000..6b19311 --- /dev/null +++ b/assessment1date/date2.c @@ -0,0 +1,139 @@ +#include +#include +#include + +struct _date { + int day; + int month; + int year; +}; + +typedef struct _date date; + +date getDate(); +int dateDiff(date date1, date date2); + +main(){ + + date date1 = getDate(); + date date2 = getDate(); + + int diff = dateDiff(date1, date2); + + printf("%i\n", diff); + +} + +/* + getDate function to get user entry of a valid date and + returns a date variable type +*/ +date getDate(){ + date entrydate = {0,0,0}; + int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + int leapdays[12] = {31,29,31,30,31,30,31,31,30,31,30,31}; + char mark[2]; + + /* + loop to get entry of date that quits when a valid date is given + should only run once if a valid date is entered, any errors result in continue statement + */ + while(1){ + + char input[12]; + + scanf("%s", input); + + sscanf(input,"%i%c%i%c%i", &entrydate.day, &mark[0], &entrydate.month, &mark[1], &entrydate.year); + //printf("%i\t%i\t%i\n", entrydate.day, entrydate.month, entrydate.year); + + if(mark[0] != mark[1]) + { + fprintf(stderr, "ERROR: Use Consistent Delimeters\n"); + continue; + } + + if(mark[0] != '/' && mark[0] != '-') + { + fprintf(stderr, "ERROR: Use either / or - as delimiters\n"); + continue; + } + + if(entrydate.year > 10000 | entrydate.year < 1) + { + fprintf(stderr, "ERROR: Enter A Valid Year, Less than 10000 and Greater Than 0\n"); + continue; + } + + if(entrydate.month > 12 | entrydate.year < 1) + { + fprintf(stderr, "ERROR: Enter A Valid Month\n"); + continue; + } + + //checks that day entered is not outside range for month + + if(entrydate.year % 4 == 0){ + + if(entrydate.day > leapdays[(entrydate.month) - 1] | entrydate.day < 1){ + + fprintf(stderr, "ERROR: Enter A Valid Day For The Month Entered\n"); + continue; + } + } + else{ + + if(entrydate.day > days[(entrydate.month) - 1] | entrydate.day < 1){ + + fprintf(stderr, "ERROR: Enter A Valid Day For The Month Entered\n"); + continue; + } + } + + break; + } + + return entrydate; +} + +/* + Function to find difference between two dates + + Calculated based on turning dates into number of days since 0/0/0000 + and finding difference between these two numbers +*/ +int dateDiff(date date1, date date2){ + + int date1day = 0, date2day = 0; + int days[] = {0,31,59,90,120,151,181,212,243,273,304,334}; //Cumulative Day Array + + //DATE 1 CONVERSION + date1day += date1.day; + date1day += days[(date1.month) - 1]; + date1day += (365*(date1.year)); + + if(date1.year % 4 == 0){ //Leap Year Handling + date1day += ((date1.year / 4) - 1); + if(date1.month > 2){ + date1day++; + } + }else{ + date1day += (date1.year / 4); + } + + //DATE 2 CONVERSION + date2day += date2.day; + date2day += days[(date2.month) - 1]; + date2day += (365*(date2.year)); + + if(date2.year % 4 == 0){ //Leap Year Handling + date2day += ((date2.year / 4) - 1); + if(date2.month > 2){ + date2day++; + } + }else{ + date2day += (date2.year / 4); + } + + return (date2day - date1day); +} diff --git a/assessment1date/date3.c b/assessment1date/date3.c new file mode 100644 index 0000000..bdf8d74 --- /dev/null +++ b/assessment1date/date3.c @@ -0,0 +1,208 @@ +/* + + Program works by letting a user input an amount of dates and converting each into an integer value + representing the number of days since 0/0/0000 in the same way as date2.c + + From here those integer values are copied onto another array and sorted into ascending order + + In theory to print the dates because the unsorted array matches up to the date array in position, + going through the sorted array one value at a time and for each one finding the same value in the + unsorted array will give the position of the date to be printed + + In practice this was done with a while loop nested in a for loop. + + The outside for loop goes through the array of sorted integers + The inside while loop checks if the i element of the sorted integers is equal to the first element of the non sorted array + + If it is it will skip the loop and print the first date + + If not it will increment elementnum and check it against this integers element of the unsorted array + This will continue through the unsorted array until the matching integer value is found + + At this point the elementnum is the element number of the date to be printed + +*/ + +#include +#include +#include + +struct _date { + int day; + int month; + int year; +}; + +typedef struct _date date; + +date getDate(); +int dayConvert(date date1); +void printDate(date date1); + +main(){ + + date *datearray; //array for inputted dates + int *intarray; //array for inputted dates after conversion to days + int *sorted_intarray; //sorted array of converted days + + int num_dates; + scanf("%i", &num_dates); + + datearray = (date *)malloc(sizeof(date) * num_dates); + intarray = (int *)malloc(sizeof(int) * num_dates); + sorted_intarray = (int *)malloc(sizeof(int) * num_dates); + + + int i, j, temp; + for(i = 0; i < num_dates; i++) //GET DATES + { + datearray[i] = getDate(); + } + + for(i = 0; i < num_dates; i++) //CONVERT DATES TO INTEGERS + { + intarray[i] = dayConvert(datearray[i]); + } + + for(i = 0; i < num_dates; i++) //MAKE COPY OF INTEGERS + { + sorted_intarray[i] = intarray[i]; + } + + for(i = 0; i < num_dates; i++){ //SORT INTEGERS + + for(j = i + 1; j < num_dates; j++){ + + if(sorted_intarray[i] > sorted_intarray[j]){ + + temp = sorted_intarray[i]; + sorted_intarray[i] = sorted_intarray[j]; + sorted_intarray[j] = temp; + + } + } + } + + for(i = 0; i < num_dates; i++){ //FIND MATCHING INTEGER AND PRINT DATE + + int elementnum = 0; + + while(sorted_intarray[i] != intarray[elementnum]) + { + elementnum++; + } + + printDate(datearray[elementnum]); + } + + free(datearray); + free(intarray); + free(sorted_intarray); + +} + +/* + getDate function to get user entry of a valid date and + returns a date variable type +*/ +date getDate(){ + date entrydate = {0,0,0}; + int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + int leapdays[12] = {31,29,31,30,31,30,31,31,30,31,30,31}; + char mark[2]; + + /* + loop to get entry of date that quits when a valid date is given + should only run once if a valid date is entered, any errors result in continue statement + */ + while(1){ + + char input[12]; + + scanf("%s", input); + + sscanf(input,"%i%c%i%c%i", &entrydate.day, &mark[0], &entrydate.month, &mark[1], &entrydate.year); + //printf("%i\t%i\t%i\n", entrydate.day, entrydate.month, entrydate.year); + + if(mark[0] != mark[1]) + { + fprintf(stderr, "ERROR: Use Consistent Delimeters\n"); + continue; + } + + if(mark[0] != '/' && mark[0] != '-') + { + fprintf(stderr, "ERROR: Use either / or - as delimiters\n"); + continue; + } + + if(entrydate.year > 10000 | entrydate.year < 1) + { + fprintf(stderr, "ERROR: Enter A Valid Year, Less than 10000 and Greater Than 0\n"); + continue; + } + + if(entrydate.month > 12 | entrydate.year < 1) + { + fprintf(stderr, "ERROR: Enter A Valid Month\n"); + continue; + } + + //checks that day entered is not outside range for month + + if(entrydate.year % 4 == 0){ + + if(entrydate.day > leapdays[(entrydate.month) - 1] | entrydate.day < 1){ + + fprintf(stderr, "ERROR: Enter A Valid Day For The Month Entered\n"); + continue; + } + } + else{ + + if(entrydate.day > days[(entrydate.month) - 1] | entrydate.day < 1){ + + fprintf(stderr, "ERROR: Enter A Valid Day For The Month Entered\n"); + continue; + } + } + + break; + } + + return entrydate; +} + +/* + Function to convert date into number of days since 0/0/0000 used for sorting +*/ +int dayConvert(date date1){ + + int date1day = 0; + int days[] = {0,31,59,90,120,151,181,212,243,273,304,334}; + + date1day += date1.day; + date1day += days[(date1.month) - 1]; + date1day += (365*(date1.year)); + + //Leap Year Handling + if(date1.year % 4 == 0){ + date1day += ((date1.year / 4) - 1); + if(date1.month > 2){ + date1day++; + } + }else{ + date1day += (date1.year / 4); + } + + return date1day; +} + +/* + Function to print dates +*/ +void printDate(date date1){ + + printf("%i/%i/%i\n", date1.day, date1.month, date1.year); + +} \ No newline at end of file diff --git a/assessment2employee/employee1.c b/assessment2employee/employee1.c new file mode 100644 index 0000000..ae011cc --- /dev/null +++ b/assessment2employee/employee1.c @@ -0,0 +1,295 @@ +#include +#include +#include + +/* maximum number of employees that can be stored at once (relevant only + to storage using an array) */ +#define MAX_EMPLOYEES 200 + +#define MAX_NAME_LENGTH 100 +#define MAX_JOB_LENGTH 100 + +/* Employee structure + */ +struct Employee +{ + /* Employee details */ + char name[MAX_NAME_LENGTH+1]; /* name string */ + char sex; /* sex identifier, either 'M' or 'F' */ + int age; /* age */ + char job[MAX_JOB_LENGTH+1]; /* job string */ + + /* pointers to previous and next employee structures in the linked list + (for if you use a linked list instead of an array) */ + struct Employee *prev, *next; +}; + +typedef struct Employee emp; + +emp *list_root = NULL; + +/* read_line(): + * + * Read line of characters from file pointer "fp", copying the characters + * into the "line" string, up to a maximum of "max_length" characters, plus + * one for the string termination character '\0'. Reading stops upon + * encountering the end-of-line character '\n', for which '\0' is substituted + * in the string. If the end of file character EOF is reached before the end + * of the line, the failure condition (-1) is returned. If the line is longer + * than the maximum length "max_length" of the string, the extra characters + * are read but ignored. Success is returned (0) on successfully reading + * a line. + */ +static int read_line ( FILE *fp, char *line, int max_length ) +{ + int i; + char ch; + + /* initialize index to string character */ + i = 0; + + /* read to end of line, filling in characters in string up to its + maximum length, and ignoring the rest, if any */ + for(;;) + { + /* read next character */ + ch = fgetc(fp); + + /* check for end of file error */ + if ( ch == EOF ) + return -1; + + /* check for end of line */ + if ( ch == '\n' ) + { + /* terminate string and return */ + line[i] = '\0'; + return 0; + } + + /* fill character in string if it is not already full*/ + if ( i < max_length ) + line[i++] = ch; + } + + /* the program should never reach here */ + return -1; +} + +/* read_string(): + * + * Reads a line from the input file pointer "fp", starting with the "prefix" + * string, and filling the string "string" with the remainder of the contents + * of the line. If the start of the line does not match the "prefix" string, + * the error condition (-1) is returned. Having read the prefix string, + * read_string() calls read_line() to read the remainder of the line into + * "string", up to a maximum length "max_length", and returns the result. + */ +static int read_string ( FILE *fp, + char *prefix, char *string, int max_length ) +{ + int i; + + /* read prefix string */ + for ( i = 0; i < strlen(prefix); i++ ) + if ( fgetc(fp) != prefix[i] ) + /* file input doesn't match prefix */ + return -1; + + /* read remaining part of line of input into string */ + return ( read_line ( fp, string, max_length ) ); +} + +/* menu_add_employee(): + * + * Add new employee to database + */ +static void menu_add_employee(void) +{ + /* fill in the code here in part 1, and add any extra functions you need */ + + emp *newemp; + newemp = (emp *)malloc(sizeof(emp)); + + + fprintf(stderr, "Enter Name: "); + read_line(stdin, newemp->name, MAX_NAME_LENGTH + 1); + + char gender; /* Infinite loop to get correctly formatted gender */ + for(;;){ + + fprintf(stderr, "Enter Gender: "); + + gender = getchar(); + + if(gender == '\n') gender = getchar(); + if(gender == 'F' || gender == 'M') break; + fprintf(stderr, "Enter either M or F\n"); + } + newemp->sex = gender; + + int age; + for(;;){ /* Infinite loop with checks for age */ + + fprintf(stderr, "Enter Age: "); + + scanf("%i", &age); + + if(age > 0) break; + fprintf(stderr, "Enter a Positive Integer\n"); + } + newemp->age = age; + getchar(); + + fprintf(stderr, "Enter Job: "); + read_line(stdin, newemp->job, MAX_JOB_LENGTH + 1); + + /* Following inserts employee into list, sorting at entry */ + if(list_root == NULL){ /*No Employees*/ + newemp->prev = NULL; + newemp->next = list_root; + list_root = newemp; + }else{ + + if(strcmp(newemp->name, list_root->name) < 1){ /* Checks if needs to be new first employee */ + newemp->prev = NULL; + newemp->next = list_root; + list_root = newemp; + }else{ + + emp* marker = list_root; /* Marker moves through to end of list */ + while(marker->next != NULL){ + marker = marker->next; + } + if(strcmp(newemp->name, marker->name) > 0){ /* Checks if employee needs to be new last employee */ + marker->next = newemp; + newemp->prev = marker; + newemp->next = NULL; + }else{ + marker = list_root; + while(marker->next != NULL){ /* Checks rest of list inbetween */ + if(strcmp(newemp->name, marker->name) > 0 && strcmp(newemp->name, marker->next->name) <= 0){ + newemp->next = marker->next; + newemp->prev = marker; + marker->next->prev = newemp; + marker->next = newemp; + } + + marker = marker->next; + } + } + } + } +} + +/* menu_print_database(): + * + * Print database of employees to standard output. + */ +static void menu_print_database(void) +{ + /* fill in the code here in part 1, and add any extra functions you need */ + + if(list_root != NULL){ /* Only prints if list root is not empty */ + + emp* marker = list_root; + + do{ + printf("Name: %s\n", marker->name); + printf("Sex: %c\n", marker->sex); + printf("Age: %i\n", marker->age); + printf("Job: %s\n\n", marker->job); + marker = marker->next; + }while(marker->name != NULL); + + }else{ fprintf(stderr, "Nothing To Print"); } + +} + +/* menu_delete_employee(): + * + * Delete new employee from database. + */ +static void menu_delete_employee(void) +{ + /* fill in the code here in part 2, and add any extra functions you need */ +} + +/* read file containing database of employees */ +static void read_employee_database ( char *file_name ) +{ + /* fill in the code here in part 3, and add any extra functions you need */ +} + +/* codes for menu */ +#define ADD_CODE 0 +#define DELETE_CODE 1 +#define PRINT_CODE 2 +#define EXIT_CODE 3 + +int main ( int argc, char *argv[] ) +{ + /* check arguments */ + if ( argc != 1 && argc != 2 ) + { + fprintf ( stderr, "Usage: %s []\n", argv[0] ); + exit(-1); + } + + /* read database file if provided, or start with empty database */ + if ( argc == 2 ) + read_employee_database ( argv[1] ); + + for(;;) + { + int choice, result; + char line[301]; + + /* print menu to standard error */ + fprintf ( stderr, "\nOptions:\n" ); + fprintf ( stderr, "%d: Add new employee to database\n", ADD_CODE ); + fprintf ( stderr, "%d: Delete employee from database\n", DELETE_CODE ); + fprintf ( stderr, "%d: Print database to screen\n", PRINT_CODE ); + fprintf ( stderr, "%d: Exit database program\n", EXIT_CODE ); + fprintf ( stderr, "\nEnter option: " ); + + if ( read_line ( stdin, line, 300 ) != 0 ) continue; + + result = sscanf ( line, "%d", &choice ); + if ( result != 1 ) + { + fprintf ( stderr, "corrupted menu choice\n" ); + continue; + } + + switch ( choice ) + { + case ADD_CODE: /* add employee to database */ + menu_add_employee(); + break; + + case DELETE_CODE: /* delete employee from database */ + menu_delete_employee(); + break; + + case PRINT_CODE: /* print database contents to screen + (standard output) */ + menu_print_database(); + break; + + /* exit */ + case EXIT_CODE: + break; + + default: + fprintf ( stderr, "illegal choice %d\n", choice ); + break; + } + + /* check for exit menu choice */ + if ( choice == EXIT_CODE ) + break; + } + + return 0; +} diff --git a/assessment2employee/employee2.c b/assessment2employee/employee2.c new file mode 100644 index 0000000..782d5a7 --- /dev/null +++ b/assessment2employee/employee2.c @@ -0,0 +1,336 @@ +#include +#include +#include + +/* maximum number of employees that can be stored at once (relevant only + to storage using an array) */ +#define MAX_EMPLOYEES 200 + +#define MAX_NAME_LENGTH 100 +#define MAX_JOB_LENGTH 100 + +/* Employee structure + */ +struct Employee +{ + /* Employee details */ + char name[MAX_NAME_LENGTH+1]; /* name string */ + char sex; /* sex identifier, either 'M' or 'F' */ + int age; /* age */ + char job[MAX_JOB_LENGTH+1]; /* job string */ + + /* pointers to previous and next employee structures in the linked list + (for if you use a linked list instead of an array) */ + struct Employee *prev, *next; +}; + +typedef struct Employee emp; + +emp *list_root = NULL; + +/* read_line(): + * + * Read line of characters from file pointer "fp", copying the characters + * into the "line" string, up to a maximum of "max_length" characters, plus + * one for the string termination character '\0'. Reading stops upon + * encountering the end-of-line character '\n', for which '\0' is substituted + * in the string. If the end of file character EOF is reached before the end + * of the line, the failure condition (-1) is returned. If the line is longer + * than the maximum length "max_length" of the string, the extra characters + * are read but ignored. Success is returned (0) on successfully reading + * a line. + */ +static int read_line ( FILE *fp, char *line, int max_length ) +{ + int i; + char ch; + + /* initialize index to string character */ + i = 0; + + /* read to end of line, filling in characters in string up to its + maximum length, and ignoring the rest, if any */ + for(;;) + { + /* read next character */ + ch = fgetc(fp); + + /* check for end of file error */ + if ( ch == EOF ) + return -1; + + /* check for end of line */ + if ( ch == '\n' ) + { + /* terminate string and return */ + line[i] = '\0'; + return 0; + } + + /* fill character in string if it is not already full*/ + if ( i < max_length ) + line[i++] = ch; + } + + /* the program should never reach here */ + return -1; +} + +/* read_string(): + * + * Reads a line from the input file pointer "fp", starting with the "prefix" + * string, and filling the string "string" with the remainder of the contents + * of the line. If the start of the line does not match the "prefix" string, + * the error condition (-1) is returned. Having read the prefix string, + * read_string() calls read_line() to read the remainder of the line into + * "string", up to a maximum length "max_length", and returns the result. + */ +static int read_string ( FILE *fp, + char *prefix, char *string, int max_length ) +{ + int i; + + /* read prefix string */ + for ( i = 0; i < strlen(prefix); i++ ) + if ( fgetc(fp) != prefix[i] ) + /* file input doesn't match prefix */ + return -1; + + /* read remaining part of line of input into string */ + return ( read_line ( fp, string, max_length ) ); +} + +/* menu_add_employee(): + * + * Add new employee to database + */ +static void menu_add_employee(void) +{ + /* fill in the code here in part 1, and add any extra functions you need */ + + emp *newemp; + newemp = (emp *)malloc(sizeof(emp)); + + + fprintf(stderr, "Enter Name: "); + read_line(stdin, newemp->name, MAX_NAME_LENGTH + 1); + + char gender; + for(;;){ + + fprintf(stderr, "Enter Gender: "); + + gender = getchar(); + + if(gender == '\n') gender = getchar(); + if(gender == 'F' || gender == 'M') break; + fprintf(stderr, "Enter either M or F\n"); + } + newemp->sex = gender; + + int age; + for(;;){ + + fprintf(stderr, "Enter Age: "); + + scanf("%i", &age); + + if(age > 0) break; + fprintf(stderr, "Enter a Positive Integer\n"); + } + newemp->age = age; + getchar(); + + fprintf(stderr, "Enter Job: "); + read_line(stdin, newemp->job, MAX_JOB_LENGTH + 1); + + if(list_root == NULL){ + newemp->prev = NULL; + newemp->next = list_root; + list_root = newemp; + }else{ + + if(strcmp(newemp->name, list_root->name) < 1){ + newemp->prev = NULL; + newemp->next = list_root; + list_root = newemp; + }else{ + + emp* marker = list_root; + while(marker->next != NULL){ + marker = marker->next; + } + if(strcmp(newemp->name, marker->name) > 0){ + marker->next = newemp; + newemp->prev = marker; + newemp->next = NULL; + }else{ + marker = list_root; + while(marker->next != NULL){ + if(strcmp(newemp->name, marker->name) > 0 && strcmp(newemp->name, marker->next->name) <= 0){ + newemp->next = marker->next; + newemp->prev = marker; + marker->next->prev = newemp; + marker->next = newemp; + } + + marker = marker->next; + } + } + } + } +} + +/* menu_print_database(): + * + * Print database of employees to standard output. + */ +static void menu_print_database(void) +{ + /* fill in the code here in part 1, and add any extra functions you need */ + + if(list_root != NULL){ + + emp* marker = list_root; + do{ + printf("Name: %s\n", marker->name); + printf("Sex: %c\n", marker->sex); + printf("Age: %i\n", marker->age); + printf("Job: %s\n\n", marker->job); + marker = marker->next; + }while(marker->name != NULL); + + }else{ fprintf(stderr, "Nothing To Print"); } +} + +/* menu_delete_employee(): + * + * Delete new employee from database. + */ +static void menu_delete_employee(void) +{ + /* fill in the code here in part 2, and add any extra functions you need */ + + fprintf(stderr, "Enter Name To Be Deleted: "); + char name[MAX_NAME_LENGTH + 1]; + //read_line(stdin, name, MAX_NAME_LENGTH + 1); + fgets(name, MAX_NAME_LENGTH + 1, stdin); + + int found = 0; /* boolean check to mark if employee was found */ + + emp* marker = list_root; + for(;;){ + if(strcmp(marker->name, name) == 0){ + + if(marker == list_root){ /* First Employee */ + if(marker->next == NULL){ /* Only Employee */ + free(marker); + list_root = NULL; + }else{ /* First Employee */ + list_root = marker->next; + marker->next->prev = NULL; + free(marker); + } + }else{ + if(marker->next == NULL){ /* Last Employee */ + marker->prev->next = NULL; + free(marker); + }else{ /* Somewhere in Middle Of List */ + marker->prev->next = marker->next; + marker->next->prev = marker->prev; + free(marker); + } + } + found = 1; + break; + }else{ + if(marker->next != NULL){ /* Progresses List */ + marker = marker->next; + }else{ + break; + } + } + } + if(found = 0) fprintf(stderr, "Name not Found\n"); + +getchar(); +} + +/* read file containing database of employees */ +static void read_employee_database ( char *file_name ) +{ + /* fill in the code here in part 3, and add any extra functions you need */ +} + +/* codes for menu */ +#define ADD_CODE 0 +#define DELETE_CODE 1 +#define PRINT_CODE 2 +#define EXIT_CODE 3 + +int main ( int argc, char *argv[] ) +{ + /* check arguments */ + if ( argc != 1 && argc != 2 ) + { + fprintf ( stderr, "Usage: %s []\n", argv[0] ); + exit(-1); + } + + /* read database file if provided, or start with empty database */ + if ( argc == 2 ) + read_employee_database ( argv[1] ); + + for(;;) + { + int choice, result; + char line[301]; + + /* print menu to standard error */ + fprintf ( stderr, "\nOptions:\n" ); + fprintf ( stderr, "%d: Add new employee to database\n", ADD_CODE ); + fprintf ( stderr, "%d: Delete employee from database\n", DELETE_CODE ); + fprintf ( stderr, "%d: Print database to screen\n", PRINT_CODE ); + fprintf ( stderr, "%d: Exit database program\n", EXIT_CODE ); + fprintf ( stderr, "\nEnter option: " ); + + if ( read_line ( stdin, line, 300 ) != 0 ) continue; + + result = sscanf ( line, "%d", &choice ); + if ( result != 1 ) + { + fprintf ( stderr, "corrupted menu choice\n" ); + continue; + } + + switch ( choice ) + { + case ADD_CODE: /* add employee to database */ + menu_add_employee(); + break; + + case DELETE_CODE: /* delete employee from database */ + menu_delete_employee(); + break; + + case PRINT_CODE: /* print database contents to screen + (standard output) */ + menu_print_database(); + break; + + /* exit */ + case EXIT_CODE: + break; + + default: + fprintf ( stderr, "illegal choice %d\n", choice ); + break; + } + + /* check for exit menu choice */ + if ( choice == EXIT_CODE ) + break; + } + + return 0; +} diff --git a/assessment2employee/employee3.c b/assessment2employee/employee3.c new file mode 100644 index 0000000..a454a14 --- /dev/null +++ b/assessment2employee/employee3.c @@ -0,0 +1,391 @@ +#include +#include +#include + +/* maximum number of employees that can be stored at once (relevant only + to storage using an array) */ +#define MAX_EMPLOYEES 200 + +#define MAX_NAME_LENGTH 100 +#define MAX_JOB_LENGTH 100 + +/* Employee structure + */ +struct Employee +{ + /* Employee details */ + char name[MAX_NAME_LENGTH+1]; /* name string */ + char sex; /* sex identifier, either 'M' or 'F' */ + int age; /* age */ + char job[MAX_JOB_LENGTH+1]; /* job string */ + + /* pointers to previous and next employee structures in the linked list + (for if you use a linked list instead of an array) */ + struct Employee *prev, *next; +}; + +typedef struct Employee emp; + +emp *list_root = NULL; + +/* read_line(): + * + * Read line of characters from file pointer "fp", copying the characters + * into the "line" string, up to a maximum of "max_length" characters, plus + * one for the string termination character '\0'. Reading stops upon + * encountering the end-of-line character '\n', for which '\0' is substituted + * in the string. If the end of file character EOF is reached before the end + * of the line, the failure condition (-1) is returned. If the line is longer + * than the maximum length "max_length" of the string, the extra characters + * are read but ignored. Success is returned (0) on successfully reading + * a line. + */ +static int read_line ( FILE *fp, char *line, int max_length ) +{ + int i; + char ch; + + /* initialize index to string character */ + i = 0; + + /* read to end of line, filling in characters in string up to its + maximum length, and ignoring the rest, if any */ + for(;;) + { + /* read next character */ + ch = fgetc(fp); + + /* check for end of file error */ + if ( ch == EOF ) + return -1; + + /* check for end of line */ + if ( ch == '\n' ) + { + /* terminate string and return */ + line[i] = '\0'; + return 0; + } + + /* fill character in string if it is not already full*/ + if ( i < max_length ) + line[i++] = ch; + } + + /* the program should never reach here */ + return -1; +} + +/* read_string(): + * + * Reads a line from the input file pointer "fp", starting with the "prefix" + * string, and filling the string "string" with the remainder of the contents + * of the line. If the start of the line does not match the "prefix" string, + * the error condition (-1) is returned. Having read the prefix string, + * read_string() calls read_line() to read the remainder of the line into + * "string", up to a maximum length "max_length", and returns the result. + */ +static int read_string ( FILE *fp, + char *prefix, char *string, int max_length ) +{ + int i; + + /* read prefix string */ + for ( i = 0; i < strlen(prefix); i++ ) + if ( fgetc(fp) != prefix[i] ) + /* file input doesn't match prefix */ + return -1; + + /* read remaining part of line of input into string */ + return ( read_line ( fp, string, max_length ) ); +} + + +/* Moved sorting into separate function so it could be called by either add employee + or read database function */ + +static void insert_employee(emp* newemp){ + + if(list_root == NULL){ + newemp->prev = NULL; + newemp->next = list_root; + list_root = newemp; + }else{ + + if(strcmp(newemp->name, list_root->name) < 1){ + newemp->prev = NULL; + newemp->next = list_root; + list_root = newemp; + }else{ + + emp* marker = list_root; + while(marker->next != NULL){ + marker = marker->next; + } + if(strcmp(newemp->name, marker->name) > 0){ + marker->next = newemp; + newemp->prev = marker; + newemp->next = NULL; + }else{ + marker = list_root; + while(marker->next != NULL){ + if(strcmp(newemp->name, marker->name) > 0 && strcmp(newemp->name, marker->next->name) <= 0){ + newemp->next = marker->next; + newemp->prev = marker; + marker->next->prev = newemp; + marker->next = newemp; + } + + marker = marker->next; + } + } + } + } + +} + +/* menu_add_employee(): + * + * Add new employee to database + */ +static void menu_add_employee(void) +{ + /* fill in the code here in part 1, and add any extra functions you need */ + + emp *newemp; + newemp = (emp *)malloc(sizeof(emp)); + + + fprintf(stderr, "Enter Name: "); + read_line(stdin, newemp->name, MAX_NAME_LENGTH + 1); + + char gender; + for(;;){ + + fprintf(stderr, "Enter Gender: "); + + gender = getchar(); + + if(gender == '\n') gender = getchar(); + if(gender == 'F' || gender == 'M') break; + fprintf(stderr, "Enter either M or F\n"); + } + newemp->sex = gender; + + int age; + for(;;){ + + fprintf(stderr, "Enter Age: "); + + scanf("%i", &age); + + if(age > 0) break; + fprintf(stderr, "Enter a Positive Integer\n"); + } + newemp->age = age; + getchar(); + + fprintf(stderr, "Enter Job: "); + read_line(stdin, newemp->job, MAX_JOB_LENGTH + 1); + + insert_employee(newemp); +} + +/* menu_print_database(): + * + * Print database of employees to standard output. + */ +static void menu_print_database(void) +{ + /* fill in the code here in part 1, and add any extra functions you need */ + + if(list_root != NULL){ + + emp* marker = list_root; + do{ + printf("Name: %s\n", marker->name); + printf("Sex: %c\n", marker->sex); + printf("Age: %i\n", marker->age); + printf("Job: %s\n\n", marker->job); + marker = marker->next; + }while(marker->name != NULL); + + }else{ fprintf(stderr, "Nothing To Print"); } +} + +/* menu_delete_employee(): + * + * Delete new employee from database. + */ +static void menu_delete_employee(void) +{ + /* fill in the code here in part 2, and add any extra functions you need */ + + fprintf(stderr, "Enter Name To Be Deleted: "); + char name[MAX_NAME_LENGTH + 1]; + read_line(stdin, name, MAX_NAME_LENGTH + 1); + + int found = 0; + + emp* marker = list_root; + for(;;){ + if(strcmp(marker->name, name) == 0){ + + if(list_root == marker){ //FIRST EMPLOYEE + if(marker->next == NULL){ + free(marker); + list_root = NULL; + }else{ + list_root = marker->next; + marker->next->prev = NULL; + free(marker); + } + }else{ + if(marker->next == NULL){//LAST EMPLOYEE + marker->prev->next = NULL; + free(marker); + }else{ + marker->prev->next = marker->next; + marker->next->prev = marker->prev; + free(marker); + } + } + found = 1; + break; + }else{ + if(marker->next != NULL){ + marker = marker->next; + }else{ + break; + } + } + } + if(found = 0) fprintf(stderr, "Name not Found\n"); + +getchar(); +} + +/* read file containing database of employees */ +static void read_employee_database ( char *file_name ) +{ + /* fill in the code here in part 3, and add any extra functions you need */ + + FILE *empfile; + empfile = fopen(file_name, "r"); + + if(empfile == NULL){ /* Checks file has opened correctly */ + fprintf(stderr, "Error Opening %s File to Read", file_name); + exit(EXIT_FAILURE); + } + + for(;;){ /*Infinite loop that reads in employees until can't read any more*/ + emp* newemp; + newemp = (emp *)malloc(sizeof(emp)); + + int name_check = read_string(empfile, "Name: ", newemp->name, MAX_NAME_LENGTH+1); + if(name_check == -1) break; /* This line exits loop when no new name can be found */ + + char gender[2]; /* sends string to be read to */ + read_string(empfile, "Sex: ", gender, 2); + if(gender[0] != 'M' && gender[0] != 'F'){ /* Gender Check */ + fprintf(stderr, "Incorrect Gender Format Found For Employee %s\n", newemp->name); + exit(EXIT_FAILURE); + } + newemp->sex = gender[0]; /* Takes first character of array for gender char */ + + + int age; + char char_age[10]; + read_string(empfile, "Age: ", char_age, 10); + age = atoi(char_age); /* Uses function to cast string as int, read_string only reads to strings */ + if(age < 1){ + fprintf(stderr, "Negative Age Found For Employee %s\n", newemp->name); + exit(EXIT_FAILURE); + } + newemp->age = age; + + read_string(empfile, "Job: ", newemp->job, MAX_JOB_LENGTH+1); + + insert_employee(newemp); /* Correctly sorts and inserts employee */ + + char carriage[2]; + read_line(empfile, carriage, 1); /* Important line to skip blank line inbetween employees */ + } + + fclose(empfile); /* Close File */ + + +} + +/* codes for menu */ +#define ADD_CODE 0 +#define DELETE_CODE 1 +#define PRINT_CODE 2 +#define EXIT_CODE 3 + +int main ( int argc, char *argv[] ) +{ + /* check arguments */ + if ( argc != 1 && argc != 2 ) + { + fprintf ( stderr, "Usage: %s []\n", argv[0] ); + exit(-1); + } + + /* read database file if provided, or start with empty database */ + if ( argc == 2 ) + read_employee_database ( argv[1] ); + + for(;;) + { + int choice, result; + char line[301]; + + /* print menu to standard error */ + fprintf ( stderr, "\nOptions:\n" ); + fprintf ( stderr, "%d: Add new employee to database\n", ADD_CODE ); + fprintf ( stderr, "%d: Delete employee from database\n", DELETE_CODE ); + fprintf ( stderr, "%d: Print database to screen\n", PRINT_CODE ); + fprintf ( stderr, "%d: Exit database program\n", EXIT_CODE ); + fprintf ( stderr, "\nEnter option: " ); + + if ( read_line ( stdin, line, 300 ) != 0 ) continue; + + result = sscanf ( line, "%d", &choice ); + if ( result != 1 ) + { + fprintf ( stderr, "corrupted menu choice\n" ); + continue; + } + + switch ( choice ) + { + case ADD_CODE: /* add employee to database */ + menu_add_employee(); + break; + + case DELETE_CODE: /* delete employee from database */ + menu_delete_employee(); + break; + + case PRINT_CODE: /* print database contents to screen + (standard output) */ + menu_print_database(); + break; + + /* exit */ + case EXIT_CODE: + break; + + default: + fprintf ( stderr, "illegal choice %d\n", choice ); + break; + } + + /* check for exit menu choice */ + if ( choice == EXIT_CODE ) + break; + } + + return 0; +} diff --git a/assessment3gameOfLife/life1.c b/assessment3gameOfLife/life1.c new file mode 100644 index 0000000..dd7e788 --- /dev/null +++ b/assessment3gameOfLife/life1.c @@ -0,0 +1,248 @@ + +#include +#include +#include + +/* + Function to check 3 x 3 grid around cell defined by co-ordinates given by + the arguments "row" and "column" for live neighbours +*/ +int checkNeighbours(char **board, int row, int column){ + + int neighbours = 0; + + int start_x = column - 1; /* Moves start co-ordinate to top left of 3 x 3 grid */ + int start_y = row - 1; + int x,y; + for(y = 0; y < 3; y++){ /* Nested Loops to cycle through 3 x 3 grid */ + for(x = 0; x < 3; x++){ + if(board[start_y + y][start_x + x] == 'X'){ + neighbours++; + } + } + } + + if(board[row][column] == 'X') neighbours--; + + /* Remove one neighbour if given cell is alive to avoid it being counted as a neighbour */ + + return neighbours; +} + +/* + Function to return an empty board array with dimensions given in arguments r and c +*/ +char** getBoard(int r, int c){ + + r+=2; + c+=2; + + /* + Adding 2 to r and c is done to add a border of empty cells around the board + + This avoids trying to access unallocated memory + */ + + int i, j; + char **board; + + board = (char **)malloc(r * sizeof(char *)); + for(i = 0; i < r; i++){ + board[i] = (char *)malloc(c * sizeof(char)); /* Fill array with arrays */ + } + + for(i = 0; i < r; i++) + for(j = 0; j < c; j++) + board[i][j] = ' '; /* Fills board with dead cells */ + + return board; +} + +/* + Function that takes board input and applies rules to it, + returning a new board and deleting the old one +*/ +char** getNextBoard(char **oldboard, int r, int c){ + + char** board = getBoard(r, c); + + r+=2; + c+=2; + + int x, y, neighbour; + for(y = 1; y < r - 1; y++){ /* Nested Loops to run through whole board */ + for(x = 1; x < c - 1; x++){ + neighbour = checkNeighbours(oldboard, y, x); + + if(oldboard[y][x] == 'X'){ + + if(neighbour < 2) /* Rule 1 */ + { + board[y][x] = 'o'; + } + + + if(neighbour == 2 || neighbour == 3) /* Rule 2 */ + { + board[y][x] = 'X'; + } + + if(neighbour > 3) /* Rule 3 */ + { + board[y][x] = 'o'; + } + + }else{ + + if(neighbour == 3) /* Rule 4 */ + { + board[y][x] = 'X'; + } + } + } + } + + free(oldboard); + return board; +} + +void printBoard(char **board, int row, int column){ + + int x; + + printf("*"); /* Top Line */ + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n"); + + + int y; + for(y = 1; y < row + 1; y++){ /* Board */ + + printf("|"); + + for(x = 1; x < column + 1; x++){ + + /* Loop starts at 1 to take into account border around board */ + + if(board[y][x] == 'X'){ + + printf("X"); + + }else printf(" "); + } + + printf("|\n"); + } + + printf("*"); /* Bottom Line */ + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n\n"); +} + +/* + TESTING FUNCTION FOR DEBUGGING NOT USED IN PROGRAM + + prints out board with x's and spaces replaced by integers + denoting number of neighbours each cell has +*/ +void printNeighbourBoard(char **board, int row, int column){ + + int x; + + printf("*"); + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n"); + + int y; + for(y = 1; y < row + 1; y++){ + printf("|"); + for(x = 1; x < column + 1; x++){ + printf("%i", checkNeighbours(board, y, x)); + } + printf("|\n"); + } + + printf("*"); + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n"); + +} + +/* + Function called at runtime to open file and fill with cells +*/ +char** populateBoard(char** board, char* filename, int row, int column){ + + FILE* file = fopen(filename, "r"); + + if(file == NULL){ + fprintf(stderr, "ERROR: File %s Failed To Open\n", filename); + exit(EXIT_FAILURE); + } + + int cells; /* Top line gives number of cells */ + fscanf(file, "%i", &cells); + + int i, r, c; + for(i = 0; i < cells; i++){ + fscanf(file, "%i %i", &r, &c); + + if(r > row || c > column){ + fprintf(stderr, "ERROR: Co-ordinate found outside Board\n"); + exit(EXIT_FAILURE); + } + + board[r + 1][c + 1] = 'X'; + /* +1 in each case takes into account border around board */ + } + + fclose(file); + + return board; +} + +void main(int argc, char * argv[]) { + + int rounds = atoi(argv[4]); + int column = atoi(argv[2]); + int row = atoi(argv[3]); + + if(rounds < 1){ + fprintf(stderr, "ERROR: Positive Rounds Required\n"); + exit(EXIT_FAILURE); + } + if(column < 1){ + fprintf(stderr, "ERROR: Positive Width Required\n"); + exit(EXIT_FAILURE); + } + if(row < 1){ + fprintf(stderr, "ERROR: Positive Height Required\n"); + exit(EXIT_FAILURE); + } + + char ** board = getBoard(row, column); /* Create First Board */ + + board = populateBoard(board, argv[1], row, column); /* Fill Board */ + + printBoard(board, row, column); /* Print Board */ + + int x; + for(x = 0; x < rounds; x++){ + putchar('\n'); + board = getNextBoard(board, row, column); + printBoard(board, row, column); + } + + printf("Finished\n"); + + free(board); + +} diff --git a/assessment3gameOfLife/life2.c b/assessment3gameOfLife/life2.c new file mode 100644 index 0000000..d46423c --- /dev/null +++ b/assessment3gameOfLife/life2.c @@ -0,0 +1,251 @@ +/* + array of chars replaced with array of ints +*/ + + +#include +#include +#include + +/* + Function to check 3 x 3 grid around cell defined by co-ordinates given by + the arguments "row" and "column" for live neighbours +*/ +int checkNeighbours(int **board, int row, int column){ + + int neighbours = 0; + + int start_x = column - 1; /* Moves start co-ordinate to top left of 3 x 3 grid */ + int start_y = row - 1; + int x,y; + for(y = 0; y < 3; y++){ /* Nested Loops to cycle through 3 x 3 grid */ + for(x = 0; x < 3; x++){ + if(board[start_y + y][start_x + x] >= 0){ + neighbours++; + } + } + } + + if(board[row][column] >= 0) neighbours--; + + /* Remove one neighbour if given cell is alive to avoid it being counted as a neighbour */ + + return neighbours; +} + +/* + Function to return an empty board array with dimensions given in arguments r and c +*/ +int** getBoard(int r, int c){ + + r+=2; + c+=2; + + /* + Adding 2 to r and c is done to add a border of empty cells around the board + + This avoids trying to access unallocated memory + */ + + int i, j; + int **board; + + board = (int **)malloc(r * sizeof(int *)); + for(i = 0; i < r; i++){ + board[i] = (int *)malloc(c * sizeof(int)); /* Fill array with arrays */ + } + + for(i = 0; i < r; i++) + for(j = 0; j < c; j++) + board[i][j] = -1; /* Fills board with dead cells denoted by -1 */ + + return board; +} + +/* + Function that takes board input and applies rules to it, + returning a new board and deleting the old one +*/ +int** getNextBoard(int **oldboard, int r, int c){ + + int** board = getBoard(r, c); + + r+=2; + c+=2; + + int x, y, neighbour; + for(y = 1; y < r - 1; y++){ /* Nested Loops to run through whole board */ + for(x = 1; x < c - 1; x++){ + neighbour = checkNeighbours(oldboard, y, x); + + if(oldboard[y][x] >= 0){ + + if(neighbour < 2) /* Rule 1 */ + { + board[y][x] = -1; + } + + + if(neighbour == 2 || neighbour == 3) /* Rule 2 */ + { + board[y][x] = oldboard[y][x] + 1; /* adds one to cell if staying alive */ + } + + if(neighbour > 3) /* Rule 3 */ + { + board[y][x] = -1; + } + + }else{ + + if(neighbour == 3) /* Rule 4 */ + { + board[y][x] = 0; /* 0 means new cell */ + } + } + } + } + + free(oldboard); + return board; +} + +void printBoard(int **board, int row, int column){ + + int x; + + printf("*"); /* Top Line */ + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n"); + + + int y; + for(y = 1; y < row + 1; y++){ /* Board */ + printf("|"); + for(x = 1; x < column + 1; x++){ + /* Loop starts at 1 to take into account border around board */ + + if(board[y][x] >= 0){ /*if alive*/ + + if(board[y][x] <= 9) + printf("%i", board[y][x]); + else putchar('x'); + + }else printf(" "); /*if dead*/ + + } + printf("|\n"); + } + + printf("*"); /* Bottom Line */ + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n\n"); +} + +/* + TESTING FUNCTION FOR DEBUGGING NOT USED IN PROGRAM + + prints out board with x's and spaces replaced by integers + denoting number of neighbours each cell has +*/ +void printNeighbourBoard(int **board, int row, int column){ + + int x; + + printf("*"); + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n"); + + int y; + for(y = 1; y < row + 1; y++){ + printf("|"); + for(x = 1; x < column + 1; x++){ + printf("%i", checkNeighbours(board, y, x)); + } + printf("|\n"); + } + + printf("*"); + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n"); + +} + +/* + Function called at runtime to open file and fill with cells +*/ +int** populateBoard(int** board, char* filename, int row, int column){ + + FILE* file = fopen(filename, "r"); + + if(file == NULL){ + fprintf(stderr, "ERROR: File %s Failed To Open\n", filename); + exit(EXIT_FAILURE); + } + + int cells; /* Top line gives number of cells */ + fscanf(file, "%i", &cells); + + int i, r, c; + for(i = 0; i < cells; i++){ + fscanf(file, "%i %i", &r, &c); + + if(r > row || c > column){ + fprintf(stderr, "ERROR: Co-ordinate found outside Board\n"); + exit(EXIT_FAILURE); + } + + board[r + 1][c + 1] = 0; + /* +1 in each case takes into account border around board */ + } + + fclose(file); + + return board; +} + +void main(int argc, char * argv[]) { + + int rounds = atoi(argv[4]); + int column = atoi(argv[2]); + int row = atoi(argv[3]); + + if(rounds < 1){ + fprintf(stderr, "ERROR: Positive Rounds Required\n"); + exit(EXIT_FAILURE); + } + if(column < 1){ + fprintf(stderr, "ERROR: Positive Width Required\n"); + exit(EXIT_FAILURE); + } + if(row < 1){ + fprintf(stderr, "ERROR: Positive Height Required\n"); + exit(EXIT_FAILURE); + } + + int ** board = getBoard(row, column); /* Create First Board */ + + board = populateBoard(board, argv[1], row, column); /* Fill Board */ + + printBoard(board, row, column); /* Print Board */ + + int x; + for(x = 0; x < rounds; x++){ + putchar('\n'); + board = getNextBoard(board, row, column); + printBoard(board, row, column); + } + + printf("Finished\n"); + + free(board); + +} diff --git a/assessment3gameOfLife/life3.c b/assessment3gameOfLife/life3.c new file mode 100644 index 0000000..5e40999 --- /dev/null +++ b/assessment3gameOfLife/life3.c @@ -0,0 +1,307 @@ + +#include +#include +#include + +/* + Function to check 3 x 3 grid around cell defined by co-ordinates given by + the arguments "row" and "column" for live neighbours +*/ +int checkNeighbours(int **board, int row, int column){ + + int neighbours = 0; + + int start_x = column - 1; /* Moves start co-ordinate to top left of 3 x 3 grid */ + int start_y = row - 1; + int x,y; + for(y = 0; y < 3; y++){ /* Nested Loops to cycle through 3 x 3 grid */ + for(x = 0; x < 3; x++){ + if(board[start_y + y][start_x + x] >= 0){ + neighbours++; + } + } + } + + if(board[row][column] >= 0) neighbours--; + + /* Remove one neighbour if given cell is alive to avoid it being counted as a neighbour */ + + return neighbours; +} + +int** getBoard(int r, int c){ + + r+=2; + c+=2; + + /* + Adding 2 to r and c is done to add a border of empty cells around the board + + This avoids trying to access unallocated memory + */ + + int i, j; + int **board; + + board = (int **)malloc(r * sizeof(int *)); + for(i = 0; i < r; i++){ + board[i] = (int *)malloc(c * sizeof(int)); /* Fill array with arrays */ + } + + for(i = 0; i < r; i++) + for(j = 0; j < c; j++) + board[i][j] = -1; /* Fills board with dead cells denoted by -1 */ + + return board; +} + +/* + Function that takes board input and applies rules to it, + returning a new board +*/ +int** getNextBoard(int **oldboard, int r, int c){ + + int** board = getBoard(r, c); + + r+=2; + c+=2; + + int x, y, neighbour; /* Nested Loops to run through whole board */ + for(y = 1; y < r - 1; y++){ + for(x = 1; x < c - 1; x++){ + neighbour = checkNeighbours(oldboard, y, x); + + if(oldboard[y][x] >= 0){ + + if(neighbour < 2) /* Rule 1 */ + { + board[y][x] = -1; + } + + + if(neighbour == 2 || neighbour == 3) /* Rule 2 */ + { + board[y][x] = oldboard[y][x] + 1; /* adds one to cell if staying alive */ + } + + if(neighbour > 3) /* Rule 3 */ + { + board[y][x] = -1; + } + + }else{ + + if(neighbour == 3) /* Rule 4 */ + { + board[y][x] = 0; /* 0 means new cell */ + } + } + } + } + + //free(oldboard); + /* Board not deleted here anymore as must be saved in array for later checking for patterns */ + return board; +} + +void printBoard(int **board, int row, int column){ + + int x; + + printf("*"); /* Top Line */ + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n"); + + + int y; + for(y = 1; y < row + 1; y++){ /* Board */ + printf("|"); + for(x = 1; x < column + 1; x++){ + /* Loop starts at 1 to take into account border around board */ + + if(board[y][x] >= 0){ /*if alive*/ + + if(board[y][x] <= 9) + printf("%i", board[y][x]); + else putchar('x'); + + }else printf(" "); /*if dead*/ + } + printf("|\n"); + } + + printf("*"); /* Bottom Line */ + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n\n"); +} + +/* + TESTING FUNCTION FOR DEBUGGING NOT USED IN PROGRAM + + prints out board with x's and spaces replaced by integers + denoting number of neighbours each cell has +*/ +void printNeighbourBoard(int **board, int row, int column){ + + int x; + + printf("*"); + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n"); + + int y; + for(y = 1; y < row + 1; y++){ + printf("|"); + for(x = 1; x < column + 1; x++){ + printf("%i", checkNeighbours(board, y, x)); + } + printf("|\n"); + } + + printf("*"); + for(x = 0; x < column; x++){ + printf("-"); + } + printf("*\n"); + +} + +/* + Function called at runtime to open file and fill with cells +*/ +int** populateBoard(int** board, char* filename, int row, int column){ + + FILE* file = fopen(filename, "r"); + + if(file == NULL){ + fprintf(stderr, "ERROR: File %s Failed To Open\n", filename); + exit(EXIT_FAILURE); + } + + int cells; /* Top line gives number of cells */ + fscanf(file, "%i", &cells); + + int i, r, c; + for(i = 0; i < cells; i++){ + fscanf(file, "%i %i", &r, &c); + + if(r > row || c > column){ + fprintf(stderr, "ERROR: Co-ordinate found outside Board\n"); + exit(EXIT_FAILURE); + } + + board[r + 1][c + 1] = 0; + /* +1 in each case takes into account border around board */ + } + + fclose(file); + + return board; +} + +/* + Function for checking if two boards are the same called exclusively by checkBoard + + returns 0 if two boards are different + returns 1 if two boards are the same +*/ +int cellChecker(int** board, int** oldboard, int row, int column){ + + int i, j; + for(i = 1; i < row + 1; i++){ + for(j = 1; j < column + 1; j++){ + if(oldboard[i][j] >= 0 && board[i][j] < 0){ /* two if statements for both ways cells can be different */ + return 0; + } + if(oldboard[i][j] < 0 && board[i][j] >= 0){ + return 0; + } + } + } + + return 1; +} + +/* + Function for storing and checking the last four boards for patterns + + returns 0 for no pattern inbetween boards + returns period of pattern if one found +*/ +int checkBoard(int** board, int row, int column){ + + static int** arr[4] = {NULL, NULL, NULL, NULL}; /* Array to store last 4 boards */ + + int x, returned; + for(x = 0; x < 4; x++){ /* Loop to check all 4 boards */ + if(arr[x] != NULL){ + + returned = cellChecker(board, arr[x], row, column); + if(returned != 0) break; + + } + } + + free(arr[3]); /* Deletes last board, shifts all up and stores new board */ + arr[3] = arr[2]; + arr[2] = arr[1]; + arr[1] = arr[0]; + arr[0] = board; + + if(returned != 0) return x + 1; + else return 0; + +} + +void main(int argc, char * argv[]) { + + int rounds = atoi(argv[4]); + int column = atoi(argv[2]); + int row = atoi(argv[3]); + + if(rounds < 1){ + fprintf(stderr, "ERROR: Positive Rounds Required\n"); + exit(EXIT_FAILURE); + } + if(column < 1){ + fprintf(stderr, "ERROR: Positive Width Required\n"); + exit(EXIT_FAILURE); + } + if(row < 1){ + fprintf(stderr, "ERROR: Positive Height Required\n"); + exit(EXIT_FAILURE); + } + + int ** board = getBoard(row, column); /* Create First Board */ + + board = populateBoard(board, argv[1], row, column); /* Fill Board */ + + checkBoard(board, row, column); /* Initially call check board in order to + store first board in array for later checking */ + + printBoard(board, row, column); /* Print Board */ + + int x = 0; + + int i; + for(i = 0; i < rounds; i++){ + putchar('\n'); + board = getNextBoard(board, row, column); + printBoard(board, row, column); + x = checkBoard(board, row, column); + if(x != 0) break; /* Break if pattern found */ + } + + if(x != 0)printf("Period detected (%i): exiting\n", x); + else printf("Finished\n"); + + free(board); + +} +