Index over opgaver i denne lektion   Alfabetisk indeks   Kursets hjemmeside   

Opgaver og løsninger
Datatyper


8.1   En tilfældig menu  

Definer tre forskellige enumeration typer for hhv. forret, hovedret og dessert.

Enumeration typen forret skal indholde værdier for guacamole, tarteletter, lakserulle og græskarsuppe.

Enumeration typen hovedret skal indholde værdier for gyldenkål, hakkebøf, gullash og forloren hare.

Enumeration typen dessert skal indholde værdier for pandekager med is, gulerodskage, choklademousse, og citronfromage.

Undgå dog danske bogstaver i dit C program. Det giver kun besvær!

Skriv en funktion maaltid, som vælger og udskriver én tilfældig ret i hver af de tre kategorier. Læs om "tilfældige tal" i C her.

Kald funktionen maaltid 25 gange i main, med det formål at få genereret et menukort af 25 kombinationer af forret, hovedret og dessert.

Overvej om der skal defineres flere små funktioner, som nedbryder det samlede problem i delproblemer.

Denne opgave er inspireret af en tilsvarende opgave i bogen 'C by Dissection'. Benyttet med tilladelse fra forlaget.

Løsning

Du kan se denne video, hvor jeg udvikler programmet - stort set svarende til de programmer jeg viser herunder.

Her er et bud en løsning, der udskriver 25 måltider:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ANTAL_FORRETTER 4
#define ANTAL_HOVEDRETTER 4
#define ANTAL_DESSERTER 4

typedef enum forret   {guacamole, tarteletter, lakserulle, graeskarsuppe} forret;   
typedef enum hovedret {gyldenkaal, hakkeboef, gullash, forloren_hare} hovedret;              
typedef enum dessert  {pandekager_med_is, gulerodskage, chokolademousse, citronfromage} dessert;  

void maaltid(void);
void prnt_forret(forret fr);
void prnt_hovedret(hovedret hr);
void prnt_dessert(dessert d);
forret make_random_forret(void);
hovedret make_random_hovedret(void);
dessert make_random_dessert(void);
        
int main(void){
 int i;

 srand(time(NULL));
 for (i=0; i < 20; i++) maaltid();

 return 0;
}

void maaltid(void){
  forret f = make_random_forret();
  hovedret h = make_random_hovedret();
  dessert d = make_random_dessert();

  prnt_forret(f);     printf("  ");
  prnt_hovedret(h); printf("  ");
  prnt_dessert(d);   printf("\n");
}

forret make_random_forret(void){
  int ret = rand() % ANTAL_FORRETTER;
  return (forret)ret;
}

hovedret make_random_hovedret(void){
  int ret = rand() % ANTAL_HOVEDRETTER;
  return (hovedret)ret;
}

dessert make_random_dessert(void){
  int ret = rand() % ANTAL_DESSERTER;
  return (dessert)ret;
}

void prnt_forret(forret fr){
 switch (fr){
  case guacamole:     printf("%20s", "Guacamode"); break;
  case tarteletter:   printf("%20s", "Tarteletter"); break;
  case lakserulle:    printf("%20s", "Lakserulle"); break;
  case graeskarsuppe: printf("%20s", "Graeskarsuppe"); break;
  default: printf("Forkert forret"); exit(-1);
 }
}

void prnt_hovedret(hovedret hr){
 switch (hr){
  case gyldenkaal:    printf("%20s", "Gyldenkaal"); break;
  case hakkeboef:     printf("%20s", "Hakkeboef"); break;
  case gullash:       printf("%20s", "Gullash"); break;
  case forloren_hare: printf("%20s", "Forloren_hare"); break;
  default: printf("Forkert hovedret"); exit(-1);
 }
}

void prnt_dessert(dessert d){
 switch (d){
  case pandekager_med_is: printf("%20s", "Pandekager med is"); break;
  case gulerodskage:      printf("%20s", "Gulerodskage"); break;
  case chokolademousse:   printf("%20s", "Chokolademousse"); break;
  case citronfromage:     printf("%20s", "Citronfromage"); break;
  default: printf("Forkert dessert"); exit(-1);
 }
}

Her er en variant som bruger en array datastruktur til håndtering af retternes navne, så vi kan undgå at bruge en selektiv kontrolstruktur til printning:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ANTAL_FORRETTER 4
#define ANTAL_HOVEDRETTER 4
#define ANTAL_DESSERTER 4

typedef enum forret   {guacamole, tarteletter, lakserulle, graeskarsuppe} forret;   
typedef enum hovedret {gyldenkaal, hakkeboef, gullash, forloren_hare} hovedret;              
typedef enum dessert  {pandekager_med_is, gulerodskage, chokolademousse, citronfromage} dessert;  

void maaltid(void);
void prnt_forret(forret fr);
void prnt_hovedret(hovedret hr);
void prnt_dessert(dessert d);
forret make_random_forret(void);
hovedret make_random_hovedret(void);
dessert make_random_dessert(void);

char *forret_navne[] = {"guacamole", "tarteletter", "lakserulle", "graeskarsuppe"};
char *hovedret_navne[] = {"gyldenkaal", "hakkeboef", "gullash", "forloren_hare"};
char *dessert_navne[] = {"pandekager_med_is", "gulerodskage", "chokolademousse", "citronfromage"};
        
int main(void){
 int i;

 srand(time(NULL));
 for (i=0; i < 20; i++) maaltid();

 return 0;
}

void maaltid(void){
  forret f = make_random_forret();
  hovedret h = make_random_hovedret();
  dessert d = make_random_dessert();

  prnt_forret(f);     printf("  ");
  prnt_hovedret(h); printf("  ");
  prnt_dessert(d);   printf("\n");
}

forret make_random_forret(void){
  int ret = rand() % ANTAL_FORRETTER;
  return (forret)ret;
}

hovedret make_random_hovedret(void){
  int ret = rand() % ANTAL_HOVEDRETTER;
  return (hovedret)ret;
}

dessert make_random_dessert(void){
  int ret = rand() % ANTAL_DESSERTER;
  return (dessert)ret;
}

void prnt_forret(forret fr){
  printf("%20s", forret_navne[(int)fr]);
}

void prnt_hovedret(hovedret hr){
  printf("%20s", hovedret_navne[(int)hr]);
}

void prnt_dessert(dessert d){
  printf("%20s", dessert_navne[(int)d]);
}




8.2   Tegning af geometriske primitiver - PPM grafik  

I denne opgave vil vi - trin for trin - tilføje nye nyttige funktioner, som arbejder på PPM billeder. De første er forholdsvis simple. De senere er lidt mere udfordrende. I denne opgave er billedet tilgængelig i en passende datastruktur, som vi dog ikke har behov for at gå i dybden med på nuværende tidspunkt.

Der findes en video som giver et oplæg til denne opgave. Der findes også en video der introducerer det billedformat som vi arbejder med. Det er kun de første 9 minutter af denne video der er relevant for dette kursus.

Arbejdet vil basere sig på nogle allerede programmerede funktioner, som kan aflæse og sætte én pixel i et PPM billede. Du kan også tænke på en pixel som en farve.

Der findes en zip-fil, som indeholder alt det nødvendige for at komme igang. README filen giver anvisninger på hvordan du kan compilere programmerne.

Nogle af jer har måske allerede lavet lidt forarbejde, nemlig funktioner som arbejder med RGB pixels. Hvis dette ikke er filfældet indholder zip filen min version af pixel funktionerne.

Det anbefales først at læse ppm.h og det simple eksempel på anvendelse af nogle af funktionerne fra ppm.h. Denne anvendelse genererer dette billede.

Programmer nu følgende:

Arbejdet kan fortsættes med endnu flere primitiver, i forskellige retninger. Tegning af stiplede linier er en mulighed. Eller indnu mere ambitiøst (for de særligt inkarnerede) indsættelse af tegn (fra en bestemt font) i et ppm billede.

Det er naturligvis vigtigt, at du kan se den grafik som genereres af dit program. Her er et antal muligheder, som jeg ved virker:


Genereret: Torsdag 28. oktober 2021, 08:28:02