GeoGuessr

Autor zadatka: Rade Radišić <radisic.rade@uns.ac.rs>

Pokušaj korisnika u igri GeoGuessr predstavljen je preko strukture pomoću sledećih polja:

  • korisničko ime (jedna reč, maksimalno 20 karaktera)

  • relativna udaljenost pogotka izražena u metrima (celobrojna vrednost)

Učitati zadate podatke u binarno stablo pretrage (struktura sadrži potrebna polja za formiranje čvora binarnog stabla). Kriterijum za formiranje stabla je korisničko ime igrača u rastućem redosledu (koristiti funkciju strcmp za poređenje korisničkih imena).

U izlaznu datoteku ispisati relativnu udaljenost pogotka i korisničko ime u formatu "%4dm %s". Pronaći igrače čija su korisnička imena zadata kao argumenti komandne linije i ispisati apsolutnu razdaljinu između njih (koristiti funkciju abs), ukoliko postoje igrači sa zadatim korisničkim imenima. U slučaju da barem jedan od igrača ne postoji, ispisati sledeći sadržaj: "\nNe postoji bar jedan igrac od zadatih korisnickih imena!\n"

Primer ulaznog fajla pokusaji.txt:

Raisan     103
Keffer      15
Dianernan   97
Covelsmar 1450
Jeanite    231
Quahassu   489
Thegamy   3482
Alatec     746
Gnomera    431

Primer poziva programa:

./resenje pokusaji.txt rezultati.txt Alatec Jeanite

Primer izlazne datoteke rezultati.txt:

 746m Alatec
1450m Covelsmar
  97m Dianernan
 431m Gnomera
 231m Jeanite
  15m Keffer
 489m Quahassu
 103m Raisan
3482m Thegamy

Razdaljina izmedju pogodataka igraca Alatec i Jeanite je 515m.

Primer poziva programa kada jedan od traženih korisnika ne postoji:

./resenje pokusaji.txt rezultati-nema-igraca.txt Alatec Shiyaut

Primer izlazne datoteke rezultati-nema-igraca.txt:

 746m Alatec
1450m Covelsmar
  97m Dianernan
 431m Gnomera
 231m Jeanite
  15m Keffer
 489m Quahassu
 103m Raisan
3482m Thegamy

Ne postoji bar jedan igrac od zadatih korisnickih imena!

Primer rešenja

  1#include <stdio.h>
  2#include <string.h>
  3#include <stdlib.h>
  4
  5#define MAX_KOR_IME 21
  6
  7typedef struct pokusaj_st {
  8    char korisnicko_ime[MAX_KOR_IME];
  9    int rel_ud_pogotka;
 10    struct pokusaj_st *levi;
 11    struct pokusaj_st *desni;
 12} POKUSAJ;
 13
 14FILE *safe_fopen(char *, char *, int);
 15void ucitaj_pokusaje(FILE *, POKUSAJ **);
 16void ispisi_rezultate(FILE *, POKUSAJ *);
 17
 18void inicijalizacija(POKUSAJ **);
 19POKUSAJ *napravi_cvor(char *, int);
 20void dodaj_u_stablo(POKUSAJ **, POKUSAJ *);
 21POKUSAJ *pronadji_cvor(POKUSAJ *, char *);
 22void obrisi_stablo(POKUSAJ **);
 23
 24int main(int argc, char **argv) {
 25    POKUSAJ *koren;
 26
 27    if(argc != 5) {
 28        printf("Primer poziva: %s pokusaji.txt rezultati.txt Alatec Jeanite\n", argv[0]);
 29        exit(EXIT_FAILURE);
 30    }
 31
 32    inicijalizacija(&koren);
 33
 34    FILE *ulazna = safe_fopen(argv[1], "r", 3);
 35    ucitaj_pokusaje(ulazna, &koren);
 36    fclose(ulazna);
 37
 38    FILE *izlazna = safe_fopen(argv[2], "w", 4);
 39    ispisi_rezultate(izlazna, koren);
 40    POKUSAJ *prvi_igrac = pronadji_cvor(koren, argv[3]);
 41    POKUSAJ *drugi_igrac = pronadji_cvor(koren, argv[4]);
 42    if(prvi_igrac != NULL && drugi_igrac != NULL) {
 43        int raz_izm_pogotka = abs(prvi_igrac->rel_ud_pogotka - drugi_igrac->rel_ud_pogotka);
 44        fprintf(izlazna, "\nRazdaljina izmedju pogodataka igraca %s i %s je %dm.\n",
 45                prvi_igrac->korisnicko_ime, drugi_igrac->korisnicko_ime, raz_izm_pogotka);
 46    } else {
 47        fprintf(izlazna, "\nNe postoji bar jedan igrac od zadatih korisnickih imena!\n");
 48    }
 49    fclose(izlazna);
 50
 51    obrisi_stablo(&koren);
 52
 53    return EXIT_SUCCESS;
 54}
 55
 56FILE *safe_fopen(char *name, char *mode, int error_code) {
 57    FILE *fp = fopen(name, mode);
 58
 59    if(fp == NULL) {
 60        printf("Nije moguce otvoriti fajl %s!\n", name);
 61        exit(error_code);
 62    }
 63
 64    return fp;
 65}
 66
 67void ucitaj_pokusaje(FILE *ulazna, POKUSAJ **pkoren) {
 68    char tmp_korisnicko_ime[MAX_KOR_IME];
 69    int tmp_rel_ud_pogotka;
 70
 71    while(fscanf(ulazna, "%s %d",
 72                 tmp_korisnicko_ime,
 73                 &tmp_rel_ud_pogotka
 74          ) != EOF) {
 75        POKUSAJ *novi = napravi_cvor(tmp_korisnicko_ime, tmp_rel_ud_pogotka);
 76        dodaj_u_stablo(pkoren, novi);
 77    }
 78}
 79
 80void ispisi_rezultate(FILE *izlazna, POKUSAJ *koren) {
 81    if(koren != NULL) {
 82        ispisi_rezultate(izlazna, koren->levi);
 83        fprintf(izlazna, "%4dm %s\n", koren->rel_ud_pogotka, koren->korisnicko_ime);
 84        ispisi_rezultate(izlazna, koren->desni);
 85    }
 86}
 87
 88void inicijalizacija(POKUSAJ **pkoren) {
 89    *pkoren = NULL;
 90}
 91
 92POKUSAJ *napravi_cvor(char *korisnicko_ime, int rel_ud_pogotka) {
 93    POKUSAJ *novi = (POKUSAJ *)malloc(sizeof(POKUSAJ));
 94
 95    if(novi == NULL) {
 96        printf("Greska prilikom zauzimanja memorije!\n");
 97        exit(2);
 98    }
 99
100    strcpy(novi->korisnicko_ime, korisnicko_ime);
101    novi->rel_ud_pogotka = rel_ud_pogotka;
102    novi->levi = NULL;
103    novi->desni = NULL;
104
105    return novi;
106}
107
108void dodaj_u_stablo(POKUSAJ **pkoren, POKUSAJ *novi) {
109    if(*pkoren == NULL) {
110        *pkoren = novi;
111    } else {
112        if(strcmp((*pkoren)->korisnicko_ime, novi->korisnicko_ime) > 0) {
113            dodaj_u_stablo(&(*pkoren)->levi, novi);
114        } else {
115            dodaj_u_stablo(&(*pkoren)->desni, novi);
116        }
117    }
118}
119
120POKUSAJ *pronadji_cvor(POKUSAJ *koren, char *korisnicko_ime) {
121    POKUSAJ *nadjen = NULL;
122
123    if(koren != NULL) {
124        if(strcmp(koren->korisnicko_ime, korisnicko_ime) == 0) {
125            nadjen = koren;
126        } else {
127            if(strcmp(koren->korisnicko_ime, korisnicko_ime) > 0) {
128                nadjen = pronadji_cvor(koren->levi, korisnicko_ime);
129            } else {
130                nadjen = pronadji_cvor(koren->desni, korisnicko_ime);
131            }
132        }
133    }
134
135    return nadjen;
136}
137
138void obrisi_stablo(POKUSAJ **pkoren) {
139    if(*pkoren != NULL) {
140        obrisi_stablo(&(*pkoren)->levi);
141        obrisi_stablo(&(*pkoren)->desni);
142        free(*pkoren);
143        *pkoren = NULL;
144    }
145}
146