Programming Fundamentals

Information

  • This page contains additional revision exercises for week 06.
  • These exercises are not compulsory, nor do they provide any marks in the course.
  • You cannot submit any of these exercises, however autotests may be available for some them (Command included at bottom of each exercise if applicable).

Exercise — individual:
String Manipulation (Revision Session Exercise)

Copy the file(s) for this exercise to your CSE account using the following command:

1511 fetch-revision 06

Implement the different functions listed in the string_manipulation.c file.

No autotests are provided for this question.

Examples

dcc struct_tutorial.c -o struct_tutorial
./struct_tutorial
Hello, World!
Goodbye
Goodbye is before World.
Sample solution for string_manipulation.c
// Strings
// Some string practice:
//      - declaring & initialising
//      - printing
//      - scanning a string
//      - count vowels and consonants
//      - check string equality (check if 2 strings are the same)
//      - reverse a string
//      - string concatenation (adding a string to the end of another)
//      - title case conversion (every first letter in a word becomes a capital)
//      - count words (words are a series of characters surrounded by spaces)

#include <stdio.h>
#include <ctype.h>
#include <string.h>

#define MAX_STR_LEN 1024

void count_vowels_consonants(char *string);
int is_vowel(char letter);
void reverse_string(char *string);
void string_concatenation(char *string1, char *string2);
void title_case_conversion(char *string);
void count_words(char *string);

int main(void) {
    // MOST IMPORTANT/USEFUL:

    // Declare & Initialise a String
    char str1[MAX_STR_LEN] = "Hello, World!\n";

    // Print a string
    printf("%s", str1);

    // Scan a string from stdin
    fgets(str1, MAX_STR_LEN, stdin);
    str1[strcspn(str1, "\n")] = '\0';

    // Check if a string is the same as another
    char str2[] = "World";
    if (strcmp(str1, str2) == 0) {
        printf("%s and %s are the same.\n", str1, str2);
    } else if (strcmp(str1, str2) < 0) {
        printf("%s is before %s.\n", str1, str2);
    } else {
        printf("%s is before %s.\n", str2, str1);
    }

    // Copy a string into another
    strcpy(str2, str1);
    printf("str2 is now %s.\n", str2);

    // LESS IMPORTANT/EXTRA PROBLEM SOLVING

    // Count Vowels and Consonants
    count_vowels_consonants(str1);

    // Reverse a String
    reverse_string(str1);

    // String Concatenation
    string_concatenation(str1, "END");
    // Can just use the function strcat
    // strncat(str1, "END");
    printf("%s\n", str1);

    // Title Case Conversion
    title_case_conversion(str1);
    printf("%s\n", str1);

    // Count Words
    count_words(str1);
}

void count_vowels_consonants(char *string) {
    int vowel_count = 0;
    int consonant_count = 0;
    for (int i = 0; string[i] != '\0'; i++) {
        if (is_vowel(string[i])) {
            vowel_count++;
        } else if (isalpha(string[i])) {
            consonant_count++;
        }
    }
    printf("There are %d vowels and %d consonants.\n", vowel_count, consonant_count);
}

int is_vowel(char letter) {
    letter = tolower(letter);
    if (letter == 'a') {
        return 1;
    } else if (letter == 'e') {
        return 1;
    } else if (letter == 'i') {
        return 1;
    } else if (letter == 'o') {
        return 1;
    } else if (letter == 'u') {
        return 1;
    }
    return 0;
}

void reverse_string(char *string) {
    char reversed[MAX_STR_LEN];
    for (int i = 0, j = strlen(string) - 1; j >= 0; i++, j--) {
        reversed[i] = string[j];
    }
    reversed[strlen(string)] = '\0';
    printf("%s\n", reversed);
}

void string_concatenation(char *string1, char *string2) {
    int i = 0;
    while (string1[i] != '\0') {
        i++;
    }
    int j = 0;
    while (j < strlen(string2)) {
        string1[i] = string2[j];
        i++;
        j++;
    }
    string1[i] = '\0';
}

void title_case_conversion(char *string) {
    int prev = 1;
    for (int i = 0; string[i] != '\0'; i++) {
        if (prev) {
            string[i] = toupper(string[i]);
        }
        if (string[i] == ' ') {
            prev = 1;
        } else {
            prev = 0;
        }
    }
}

void count_words(char *string) {
    int prev = 1;
    int word_count = 0;
    for (int i = 0; string[i] != '\0'; i++) {
        if (prev && isalpha(string[i])) {
            word_count++;
        }
        if (string[i] == ' ') {
            prev = 1;
        } else {
            prev = 0;
        }
    }
    printf("There are %d words in this sentence.\n", word_count);
}

Exercise — individual:
Simple Frogger (Revision Session Exercise)

Copy the file(s) for this exercise to your CSE account using the following command:

1511 fetch-revision 06

Complete the program simple_frogger.c, which is a simple version of the classic Frogger arcade game.

The game should start by printing a 9 x 9 map, to be built as follows:

  • The Top Row alternates between house |^| and grass -.
  • Next 3 rows are water ~, where logs -_- and alligators A can be added later.
  • Next row is grass -.
  • Next 3 rows is road =, where cars C can be added later.
  • Bottom row is grass -.

The game then prompts the user to:

  • Enter a column to place Frogger !F! on.
  • Enter the row, column, and length of 3 logs in the water. These will be used to get Frogger across the river as it cannot jump onto the water.
  • Enter the type, row, and column of 3 enemies which can be
    • Alligators (in the water)
    • Cars (on the road)

Once these elements have been added to the map, Frogger can start moving through the map using:

  • u to move up
  • d to move down
  • l to move left
  • r to move right

Frogger wins if it makes it to a house tile |^|.

Frogger loses if it goes into the water ~, or on an alligator A or car C.

No autotests are provided for this question.

Examples

dcc simple_frogger.c -o simple_frogger
./simple_frogger
Welcome to the simple game of Frogger!
|^| - |^| - |^| - |^| - |^|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
===========================
===========================
===========================
 -  -  -  -  -  -  -  -  - 
Please enter frogger's starting column: 4
|^| - |^| - |^| - |^| - |^|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
===========================
===========================
===========================
 -  -  -  - !F! -  -  -  - 
Enter 3 logs:
1 2 4
2 5 3
3 4 2
Enter 3 enemies. Type + row + col:
1 5 3
1 7 4
2 2 4
|^| - |^| - |^| - |^| - |^|
~~~~~~-_--_--_--_-~~~~~~~~~
~~~~~~~~~~~~ A -_--_--_-~~~
~~~~~~~~~~~~-_--_-~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
========= C ===============
===========================
============ C ============
 -  -  -  - !F! -  -  -  - 
Enter movement: u    
Game over!
dcc simple_frogger.c -o simple_frogger
./simple_frogger
Welcome to the simple game of Frogger!
|^| - |^| - |^| - |^| - |^|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
===========================
===========================
===========================
 -  -  -  -  -  -  -  -  - 
Please enter frogger's starting column: 5
|^| - |^| - |^| - |^| - |^|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
===========================
===========================
===========================
 -  -  -  -  - !F! -  -  - 
Enter 3 logs:
1 2 4
2 5 3
3 4 2
Enter 3 enemies. Type + row + col:
1 5 3
1 7 6
2 2 4
|^| - |^| - |^| - |^| - |^|
~~~~~~-_--_--_--_-~~~~~~~~~
~~~~~~~~~~~~ A -_--_--_-~~~
~~~~~~~~~~~~-_--_-~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
========= C ===============
===========================
================== C ======
 -  -  -  -  - !F! -  -  - 
Enter movement: u   
|^| - |^| - |^| - |^| - |^|
~~~~~~-_--_--_--_-~~~~~~~~~
~~~~~~~~~~~~ A -_--_--_-~~~
~~~~~~~~~~~~-_--_-~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
========= C ===============
===========================
===============!F! C ======
 -  -  -  -  -  -  -  -  - 
Enter movement: u  
|^| - |^| - |^| - |^| - |^|
~~~~~~-_--_--_--_-~~~~~~~~~
~~~~~~~~~~~~ A -_--_--_-~~~
~~~~~~~~~~~~-_--_-~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
========= C ===============
===============!F!=========
================== C ======
 -  -  -  -  -  -  -  -  - 
Enter movement: u  
|^| - |^| - |^| - |^| - |^|
~~~~~~-_--_--_--_-~~~~~~~~~
~~~~~~~~~~~~ A -_--_--_-~~~
~~~~~~~~~~~~-_--_-~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
========= C ===!F!=========
===========================
================== C ======
 -  -  -  -  -  -  -  -  - 
Enter movement: u  
|^| - |^| - |^| - |^| - |^|
~~~~~~-_--_--_--_-~~~~~~~~~
~~~~~~~~~~~~ A -_--_--_-~~~
~~~~~~~~~~~~-_--_-~~~~~~~~~
 -  -  -  -  - !F! -  -  - 
========= C ===============
===========================
================== C ======
 -  -  -  -  -  -  -  -  - 
Enter movement: u  
|^| - |^| - |^| - |^| - |^|
~~~~~~-_--_--_--_-~~~~~~~~~
~~~~~~~~~~~~ A -_--_--_-~~~
~~~~~~~~~~~~-_-!F!~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
========= C ===============
===========================
================== C ======
 -  -  -  -  -  -  -  -  - 
Enter movement: u  
|^| - |^| - |^| - |^| - |^|
~~~~~~-_--_--_--_-~~~~~~~~~
~~~~~~~~~~~~ A !F!-_--_-~~~
~~~~~~~~~~~~-_--_-~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
========= C ===============
===========================
================== C ======
 -  -  -  -  -  -  -  -  - 
Enter movement: u   
|^| - |^| - |^| - |^| - |^|
~~~~~~-_--_--_-!F!~~~~~~~~~
~~~~~~~~~~~~ A -_--_--_-~~~
~~~~~~~~~~~~-_--_-~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
========= C ===============
===========================
================== C ======
 -  -  -  -  -  -  -  -  - 
Enter movement: l  
|^| - |^| - |^| - |^| - |^|
~~~~~~-_--_-!F!-_-~~~~~~~~~
~~~~~~~~~~~~ A -_--_--_-~~~
~~~~~~~~~~~~-_--_-~~~~~~~~~
 -  -  -  -  -  -  -  -  - 
========= C ===============
===========================
================== C ======
 -  -  -  -  -  -  -  -  - 
Enter movement: u  
Game won!

Assumptions/Restrictions/Clarifications

  • Error checking is not needed. You can assume only valid inputs will be given.
  • Apart from Frogger, the map elements will not move during the game.
Sample solution for simple_frogger.c
// Simple Frogger
//
// A simple version of the classic Frogger arcade game where frogger
// is placed on a 9 x 9 map which is built as follows:
// Top row: House Grass House Grass House
// Next 3 rows: Water with logs & alligators
// Next 1 row: Grass
// Next 3 rows: Road with cars
// Bottom row: Grass
// Frogger moves through the map using 'u', 'l', 'd', 'r'
// Frogger wins if it makes it to a house tile
// Frogger loses if it goes into the water, or on an alligator or car
// The map is generated and is not changed again (i.e. cars, alligators and logs
// stay where originally placed)
// Error checking not needed, it can be assumed only valid inputs will be given


#include <stdio.h>

#define MAX_SIZE 9

enum tile_type {
    GRASS,
    ROAD,
    WATER,
    LOG,
    HOUSE,
};

enum enemy {
    NO_ENEMY,
    CAR,
    ALLIGATOR,
};

struct tile {
    enum tile_type type;
    enum enemy enemy;
    int frogger;
};

void initialise_map(struct tile map[][MAX_SIZE]);
void print_map(struct tile map[][MAX_SIZE]);
int move_frogger(struct tile map[][MAX_SIZE], int move_row, int move_col);
void prepare_map(struct tile map[][MAX_SIZE]);
int play_turn(struct tile map[][MAX_SIZE]);

int main(void) {
    printf("Welcome to the simple game of Frogger!\n");

    // declare & initialise map
    struct tile map[MAX_SIZE][MAX_SIZE];
    initialise_map(map);
    print_map(map);

    // add frogger, logs and enemies
    prepare_map(map);

    // play turns until frogger wins or loses
    int game_over = 0;
    while (game_over == 0) {
        game_over = play_turn(map);
    }

    if (game_over == 1) {
        printf("Game won!\n");
    } else {
        printf("Game over!\n");
    }

    return 0;
}

void initialise_map(struct tile map[][MAX_SIZE]) {
    // set 0 row to be grass & house
    int row = 0;
    int col = 0;
    while (col < MAX_SIZE) {
        if (col % 2 == 0) {
            map[row][col].type = HOUSE;
        } else {
            map[row][col].type = GRASS;
        }
        col++;
    }

    // set 1, 2 & 3 rows to be water
    row++;
    while (row < 4) {
        col = 0;
        while (col < MAX_SIZE) {
            map[row][col].type = WATER;
            col++;
        }
        row++;
    }

    // set 4 row to be grass
    col = 0;
    while (col < MAX_SIZE) {
        map[row][col].type = GRASS;
        col++;
    }

    // set 5, 6 & 7 rows to be road
    row++;
    while (row < 8) {
        col = 0;
        while (col < MAX_SIZE) {
            map[row][col].type = ROAD;
            col++;
        }
        row++;
    }

    // set row 8 to be grass
    col = 0;
    while (col < MAX_SIZE) {
        map[row][col].type = GRASS;
        col++;
    }

    // set everything to not be frogger & not be an enemy
    for (row = 0; row < MAX_SIZE; row++) {
        for (col = 0; col < MAX_SIZE; col++) {
            map[row][col].frogger = 0;
            map[row][col].enemy = NO_ENEMY;
        }
    }
}

void print_map(struct tile map[][MAX_SIZE]) {
    for (int row = 0; row < MAX_SIZE; row++) {
        for (int col = 0; col < MAX_SIZE; col++) {
            if (map[row][col].frogger) {
                printf("!F!");
            } else if (map[row][col].enemy == CAR) {
                printf(" C ");
            } else if (map[row][col].enemy == ALLIGATOR) {
                printf(" A ");
            } else if (map[row][col].type == GRASS) {
                printf(" - ");
            } else if (map[row][col].type == ROAD) {
                printf("===");
            } else if (map[row][col].type == WATER) {
                printf("~~~");
            } else if (map[row][col].type == LOG) {
                printf("-_-");
            } else if (map[row][col].type == HOUSE) {
                printf("|^|");
            }
        }
        printf("\n");
    }
}

int move_frogger(struct tile map[][MAX_SIZE], int move_row, int move_col) {
    // find frogger
    for (int i = 0; i < MAX_SIZE; i++) {
        for (int j = 0; j < MAX_SIZE; j++) {
            if (map[i][j].frogger) {
                // update old spot to no longer hold frogger
                map[i][j].frogger = 0;
                int new_row = i + move_row;
                int new_col = j + move_col;
                // update new spot to hold frogger
                map[new_row][new_col].frogger = 1;
                // if new spot is house, frogger wins
                if (map[new_row][new_col].type == HOUSE) {
                    return 1;
                }
                // if new spot is water or enemy, frogger loses
                if (map[new_row][new_col].enemy != NO_ENEMY || map[new_row][new_col].type == WATER) {
                    return -1;
                }
                return 0;
            }
        }
    }
    return 0;
}

void prepare_map(struct tile map[][MAX_SIZE]) {
    printf("Please enter frogger's starting column: ");
    int frogger_row = MAX_SIZE - 1;
    int frogger_col;
    scanf("%d", &frogger_col);
    map[frogger_row][frogger_col].frogger = 1;
    print_map(map);

    printf("Enter 3 logs:\n");
    int row;
    int col;
    int length;
    for (int i = 0; i < 3; i++) {
        scanf("%d %d %d", &row, &col, &length);
        for (int j = 0; j < length; j++) {
            map[row][col].type = LOG;
            col++;
        }
    }

    printf("Enter 3 enemies. Type + row + col:\n");
    for (int i = 0; i < 3; i++) {
        int type;
        scanf("%d %d %d", &type, &row, &col);
        map[row][col].enemy = type;
    }
}

int play_turn(struct tile map[][MAX_SIZE]) {
    print_map(map);
    printf("Enter movement: ");
    char move;
    scanf(" %c", &move);
    if (move == 'u') {
        return move_frogger(map, -1, 0);
    } else if (move == 'd') {
        return move_frogger(map, 1, 0);
    } else if (move == 'l') {
        return move_frogger(map, 0, -1);
    } else if (move == 'r') {
        return move_frogger(map, 0, 1);
    } else {
        return 0;
    }
}

Exercise — individual:
CS Calculator Style (Revision Session Exercise)

Copy the file(s) for this exercise to your CSE account using the following command:

1511 fetch-revision 06

Although this cs_calculator.style.c program runs properly, the style is horrendous! Please help us fix up the style.

No autotests are provided for this question.

Sample solution for cs_calculator_style.c
// Author: Dean Wunder
// d.wunder@unsw.edu.au
// 2020-05-04
// A arbitrary calculator app designed to help students
// understand variable length input scanning before assignment 1.

#include <stdio.h>

#define SQUARE_COMMAND 's'
#define POWER_COMMAND  'p'

int main (void) {

    char command;
    printf("Enter instruction: ");
    while (scanf(" %c", &command) == 1) {
        if (command == SQUARE_COMMAND) {
            int num;
            scanf("%d", &num);
            printf("%d\n", num * num);
        } else if (command == POWER_COMMAND) {
            int base, power;
            scanf("%d %d", &base, &power);
            int i = 0;
            int result = 1;
            while (i < power) {
                result *= base;
                i++;
            }
            printf("%d\n", result);
        }
        printf("Enter instruction: ");
    }

    return 0;
}