Programming Fundamentals

Check in week

Reminder: This week is a check-in week, so please make sure to stay around in the lab time for your one-on-one with one of your Tutors.

Tutorial Overview:

Part 1: 2D Arrays Practice (20 mins)

In this section we will write a short program that deals with 2D arrays.

The objective of this program is to simulate the exploration of a galaxy by placing celestial bodies such as stars, planets, and nebulae within a grid.

Functionality

  1. Your program will need to scan in the player's starting position. This will be given as a pair of integers which denotes the row and column (in that order). If the starting position does not place the player within the boundary, the program should print out Invalid starting position!. Then the program should prompt with Re-enter starting position: and re-scan the position of the player, repeating until a valid position is scanned in.

Here is a diagram with the spawn boundary highlighted in pink.

visual representation of player spawn
  1. After spawning the player, the program should prompt for how many celestial bodies will be added to the galaxy with How many planets and nebulae are there? [count] and take input for count number of planets and nebula.

    • Planets are added with p [row] [col] [points]
    • Neulae are added with n [row] [col]
  2. After spawning planets and nebulae the program should prompt for stars with Enter the position and points of the star(s): and take input in the form [row] [col] [points] until ctrl + d is pressed.

  3. Finally, after spawning all celestial bodies, the program should print the galaxy with the print_galaxy function provided.

This program is the starting point we'll be using today:

// part1_galaxy.c
//
// This program was written by YOUR-NAME (ZID)
// on DATE
//
// This program is a simple game that allows the user to build a galaxy. 
// The user can place stars, planets, and nebulae in the galaxy.

#include <stdio.h>

#define SIZE 5
#define NEBULA_POINTS -10

enum entity {
    STAR,
    PLANET,
    NEBULA,
    SPACESHIP,
    EMPTY,
};

struct celestial_body {
    enum entity entity;
    int points;
};

void print_map(struct celestial_body galaxy[SIZE][SIZE]);

int main(void) {
    struct celestial_body galaxy[SIZE][SIZE];

    // TODO: Initialize the galaxy

    // TODO: Place the player in the galaxy
    printf("Enter the starting position of the player: ");

    // TODO: Place the planets and nebulae in the galaxy
    printf("How many planets and nebulae are there? ");

    // TODO: Place the planets and nebulae in the galaxy
    printf("Enter the position and points of the planet(s) and nebula(e): ");
    
    // TODO: Place the stars in the galaxy
    printf("Enter the position and points of the star(s): \n");

    // TODO: Print the map
}

// Function prints the map of the galaxy
// 
// Parameters:
// - galaxy: the 2D array representing the galaxy
//
// returns: nothing
void print_map(struct celestial_body galaxy[SIZE][SIZE]) {
    printf("\n---------------------\n");
    for (int i = 0; i < SIZE; i++) {
        for (int j = 0; j < SIZE; j++) {
            printf("|");
            if (galaxy[i][j].entity == SPACESHIP) {
                printf(" X ");
            } else if (galaxy[i][j].entity == EMPTY) {
                printf("   ");
            } else if (galaxy[i][j].entity == STAR) {
                printf(" * ");
            } else if (galaxy[i][j].entity == PLANET) {
                printf(" o ");
            } else if (galaxy[i][j].entity == NEBULA) {
                printf(" # ");
            }
        }
        printf("|\n");
        printf("---------------------\n");
    }
}

Part 2: Arrays and Functions (15 min max)

In this section, we'll practice writing and using functions, focusing in particular on how they interact with arrays.

To do this we will be working with the program we created in part1 and in groups refactoring the program to use functions.

Part 3: Strings (20 min max)

Warmup:

Your tutor may briefly run through the following code and diagram with you:

Diagram of strings in c
// part3_simple_string.c
//
// This program was written by Sofia De Bellis (z5418801)
// on March 2024
//
// This program demonstrates how to work with strings in C.

#include <stdio.h>

#define MAX_SIZE 1024

int main(void) {
    // Declare and initialise a string
    char my_string[] = "Hello world!";
    
    // Traverse the string and print each character
    int i = 0;
    while (my_string[i] != '\0') {
        printf("%c", my_string[i]);
        i++;
    }
    printf("\n");

    // Another way to traverse the string and print each character 
    for (int i = 0; my_string[i] != '\0'; i++) {
        printf("%c", my_string[i]);
    }

    // How to print a string in its entirety
    printf("My string: %s\n", my_string);

    // Declare a string
    char another_string[MAX_SIZE];
    
    // Read a string from the user, note we DO NOT use scanf for strings
    printf("Enter a string: ");
    fgets(another_string, MAX_SIZE, stdin);
    
    // Print the string using fputs
    fputs(another_string, stdout);

    return 0;
}

Practice

In this section you'll be completing some string activities in your groups.

Have a quick look at the following char functions that have been implemented for you:

// Provided char functions

// Returns : 1 if `c` is a lowercase letter
//         : 0 otherwise.
int is_lowercase(char c) {

    return 'a' <= c && c <= 'z';
}

// Returns : 1 if `c` is an uppercase letter
//         : 0 otherwise.
int is_uppercase(char c) {

    return 'A' <= c && c <= 'Z';
}

// Returns : 1 if `c` is a letter
//         : 0 otherwise.
int is_letter(char c) {

    return is_lowercase(c) || is_uppercase(c);
}

// Returns : `c` converted to lowercase, if it was an uppercase letter
//         : `c` unmodified, otherwise
char to_lowercase(char c) {
    if (is_uppercase(c)) {
        return c - 'A' + 'a';
    }

    return c;
}

// Returns : `c` converted to uppercase, if it was a lowercase letter
//         : `c` unmodified, otherwise
char to_uppercase(char c) {
    if (is_lowercase(c)) {
        return c - 'a' + 'A';
    }

    return c;
}

// Returns : 1 if `c` is an uppercase or lowercase vowel
//         : 0 otherwise.
int is_vowel(char c) {
    char lower_c = to_lowercase(c);

    return lower_c == 'a' 
        || lower_c == 'e'
        || lower_c == 'i' 
        || lower_c == 'o' 
        || lower_c == 'u';
}

You may want to use some of these in your solutions.

You will be completing one of these functions!

// Functions to implement:

// 1.
// returns the number of lowercase letters in `char *string`
int count_lowercase(char string[MAX_CHARS]) {
    return 42;
}

// 2.
// modifies `char *string` by converting all its vowels to uppercase
void make_vowels_uppercase(char string[MAX_CHARS]) {
    return;
}

// 3..
// shortens a string so that it ends after the first word
// e.g. "This is a sentence" should turn into:
//      "This"
// 
// (hint. what defines when a string ends?)
void delete_following_words(char string[MAX_CHARS]) {
    return;
}