Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych. Autor artykułu: mgr Jerzy Wałaszek, wersja1.0 |
©2010 mgr
Jerzy Wałaszek |
Pomoce:
Biblioteka procedur obsługi konsoli znakowej - newconio
Łańcuchy znakowe są wygodnym typem danych do przetwarzania tekstów. W bibliotece STL mamy zdefiniowana klasę string, która umożliwia wykonywanie różnych operacji na łańcuchach znakowych. Klasa jest strukturą danych, z którą powiązane są tzw. funkcje składowe, czyli funkcje operujące bezpośrednio na tej strukturze, Dostęp do klasy string uzyskujemy po dołączeniu do naszego programu źródłowego pliku nagłówkowego:
#include <string>
Zmienną typu string definiujemy jak każdą inną zmienną w C++:
string nazwa_zmiennej;
Tak zdefiniowana zmienna nie zawiera w sobie żadnego znaku. Mówimy, że jest pustym łańcuchem znakowym. Tekst możemy wprowadzić do łańcucha np. za pomocą instrukcji przypisania:
// Klasa string // (C)2010 ILO w Tarnowie // KOŁO INFORMATYCZNE //----------------------- #include <iostream> #include <string> using namespace std; int main() { string s; s = "ALA MA KOTA"; cout << s << endl; return 0; } |
Na łańcuchach zdefiniowany jest operator dodawania +. W tym przypadku oznacza on łączenie ze sobą łańcuchów:
// Klasa string // (C)2010 ILO w Tarnowie // KOŁO INFORMATYCZNE //----------------------- #include <iostream> #include <string> using namespace std; int main() { string s1,s2,s3; s1 = "MISIEK"; s2 = "BUBU"; s3 = s1 + " " + s2; cout << s3 << endl; return 0; } |
Zawartość łańcucha można odczytać ze strumienia cin:
// Klasa string // (C)2010 ILO w Tarnowie // KOŁO INFORMATYCZNE //----------------------- #include <iostream> #include <string> using namespace std; int main() { string s; cin >> s; cout << s << endl; return 0; } |
Jednakże ten sposób wprowadzania danych nie zawsze jest dogodny, ponieważ spacja jest traktowana przez strumień jako separator. Zatem tekst zostanie wprowadzony tylko do pierwszej spacji, po czym wprowadzanie zakończy się. Dalszą część tekstu można odczytać kolejną operacją cin >>. Uruchom ponownie poprzedni program i wpisz dwa wyrazy rozdzielone spacją. Zwróć uwagę na wynik. Spróbuj jeszcze wprowadzić tekst pusty, naciskając sam klawisz Enter, lub same spacje - nie da się, prawda? Teraz wprowadź poniższy program i spróbuj ponownie wprowadzić dwa wyrazy rozdzielone spacją
// Klasa string // (C)2010 ILO w Tarnowie // KOŁO INFORMATYCZNE //----------------------- #include <iostream> #include <string> using namespace std; int main() { string s; cin >> s; cout << s << endl; cin >> s; cout << s << endl; return 0; } |
Rozwiązaniem tego problemu jest zastosowanie funkcji getline(). Przyjmuje ona dwa parametry:
getline(strumień,łańcuch);
strumień - z którego odczytujemy znaki
łańcuch - zmienna łańcuchowa, do której trafią odczytane znaki.
// Klasa string // (C)2010 ILO w Tarnowie // KOŁO INFORMATYCZNE //----------------------- #include <iostream> #include <string> using namespace std; int main() { string s; getline(cin,s); cout << s << endl; return 0; } |
Funkcja getline() odczytuje ze strumienia jeden wiersz tekstu. Problemy mogą się jednak pojawić, jeśli w programie mieszamy metodę odczytu cin >> z getline(). Pierwsza metoda nie usuwa ze strumienia znaku końca wiersza. Jeśli bezpośrednio po niej zastosujemy getline(), to zamiast odczytu wiersza znaków, zostanie odczytany pozostawiony w strumieniu znak końca wiersza z poprzedniego cin >>. W efekcie odczytany wiersz znaków będzie pusty!!!
// Klasa string // (C)2010 ILO w Tarnowie // KOŁO INFORMATYCZNE //----------------------- #include <iostream> #include <string> using namespace std; int main() { string s; int a; cin >> a; getline(cin,s); cout << s << endl; return 0; } |
W powyższym programie wprowadź dowolną liczbę. Po jej wprowadzeniu program powinien odczytać ciąg znaków. Jednakże kończy się z pustym łańcuchem s, ponieważ odczyt cin >> a; pozostawił w strumieniu znak końca wiersza \n. Teraz getline() odczytuje ten znak i w efekcie do s trafia pusta linia tekstu - użytkownik nie ma nawet okazji nic wpisać. Problem ten można rozwiązać za pomocą funkcji składowej cin.ignore(liczba_znaków_do_usunięcia,znak), która usuwa zadaną ilość znaków, aż do napotkania wskazanego znaku. Funkcję tę stosujemy po operacji cin >> następująco:
// Klasa string // (C)2010 ILO w Tarnowie // KOŁO INFORMATYCZNE //----------------------- #include <iostream> #include <string> using namespace std; int main() { string s; int a; cin >> a; cin.ignore(256,'\n'); getline(cin,s); cout << s << endl; return 0; } |
Dostęp do poszczególnych znaków łańcucha uzyskujemy za pomocą indeksów, jak w zwykłej tablicy. Ilość znaków przechowywanych w łańcuchu udostępnia nam funkcja składowa:
łańcuch.length()
Poniższy program odczytuje dowolny tekst, a następnie zastępuje w nim literki "a" literkami "i", a literki "i" literakami "a".
// Klasa string // (C)2010 ILO w Tarnowie // KOŁO INFORMATYCZNE //----------------------- #include <iostream> #include <string> using namespace std; int main() { string s; int i,n; getline(cin,s); n = s.length(); for(i = 0; i < n; i++) if(s[i] == 'a') s[i] = 'i'; else if(s[i] == 'i') s[i] = 'a'; cout << s << endl; return 0; } |
Mini Master Mind jest grą logiczną rozwijającą
inteligencję. Nie jest to gra prymitywna. Kiedyś zdobyła olbrzymią popularność
na całym świecie. Do dzisiaj w sklepach z zabawkami można jeszcze kupić zestaw
do gry w Master Mind. W oryginalnej grze celem było odgadnięcie kodu
przeciwnika, który składał się z kolorowych pionów - cztery piony wybrane
spośród 6 kolorów. Kolory mogły się powtarzać. U nas, zamiast kolorowych pionów,
będą literki A, B, C, D, E i F.
|
W naszej rozgrywce będzie uczestniczył człowiek i komputer. Każdy z nich może być jednym z dwóch graczy - szyfrantem i łamaczem kodu. Schemat gry będzie następujący:
Na początku gracz decyduje kim chce być: szyfrantem czy łamaczem kodu. Jeśli wybiera rolę szyfranta, to wymyśla swój czteroliterowy kod z literek A...F. Jeśli wybierze rolę łamacza kodu, to komputer generuje tajny kod, który gracz będzie musiał odgadnąć.
Rozpoczyna się seria 6 rund. Jeśli gracz jest łamaczem kodu, to w każdej rundzie wprowadza swój kod, na który komputer generuje odpowiedź z literek x i o. Jeśli gracz odgadnie kod komputera, gra się kończy zwycięstwem człowieka. Jeśli w ciągu 6 rund kod nie zostanie złamany, człowiek przegrywa - komputer wyświetla wtedy odpowiedni komunikat oraz podaje swój kod, którego gracz nie odgadnął.
Jeśli człowiek jest szyfrantem, to komputer generuje swój kod, który następnie człowiek ocenia wpisując literki x i o. Dalsze zasady są takie same jak dla człowieka.
W grze tej pojawiają się dwa problemy:
Generowanie kodu odpowiedzi z x i o na podstawie kodu tajnego oraz kodu wprowadzonego przez gracza. Zadanie to rozwiązujemy w dwóch krokach. Pracujemy zawsze na kopiach tych kodów, a nie na ich oryginałach. W pierwszym kroku porównujemy kolejne znaki obu kodów. Jeśli natrafimy na zgodność, dopisujemy do odpowiedzi x. Następnie usuwamy te znaki w obu kodach, aby nie zostały ponownie zaliczone. W drugim kroku sprawdzamy każdy znak jednego kodu z każdym znakiem kodu drugiego. Jeśli znajdziemy zgodność, to do odpowiedzi dopisujemy o, a znaki w obu kodach usuwamy, aby nie zostały zaliczone ponownie.
Wybór kodu przez komputer. Zadanie to rozwiązujemy tworząc tablicę wszystkich możliwych kodów czteroliterowych, zbudowanych z 6 dozwolonych liter A...F. W tablicy tej wybieramy losowo jeden z kodów. Następnie odczytujemy jego ewaluację przez człowieka. Teraz dokonujemy pewnej sztuczki. Przyjmujemy, że wybrany przez nas kod, jest kodem tajnym. Porównujemy go ze wszystkimi kodami w tablicy, generując odpowiedzi z x i o. Jeśli różnią się one od odpowiedzi otrzymanej od człowieka, to dany kod w tablicy nie może być poszukiwanym kodem (dlaczego?). Usuwamy go z tablicy. Gdy zrobimy to ze wszystkimi kodami, w tablicy pozostaną jedynie takie, które dają zgodne odpowiedzi z odpowiedzią człowieka. Wśród nich musi znajdować się kod człowieka. W następnej turze całą operacje powtarzamy z kodami pozostawionymi w tablicy. Ilość ich za każdym razem maleje, aż w końcu pozostanie tylko jeden kod - tajny kod człowieka..
// Gra MASTER MIND // (C)2010 ILO w Tarnowie // KOŁO INFORMATYCZNE //----------------------- #include <iostream> #include <string> #include <cstdlib> #include <time.h> using namespace std; // funkcja dokonuje ocent dwóch kodów, dając w odpowiedzi // ciąg x i o zgodnie z regułami gry //------------------------------------------------------- string ocena_kodow(string kod1,string kod2) { string wynik = ""; // najpierw sprawdzamy zgodność znaków na tych samych pozycjach for(int i = 0; i < 4; i++) if(kod1[i] == kod2[i]) { wynik += "x"; kod1[i] = '#'; kod2[i] = '$'; } // teraz sprawdzamy zgodność znaków na różnych pozycjach for(int i = 0; i < 4; i++) for(int j = 0; j < 4; j++) if(kod1[i] == kod2[j]) { wynik += "o"; kod2[j] = '$'; break; } return wynik; } int main() { bool koder; // false - koduje człowiek, true - koduje komputer string tajny_kod; // kod do odgadywania string kod_gracza; // kod wprowadzany przez gracza string odpowiedz; // ewaluacja kodu z literek x i o string tablica_kodow[1296]; // tablica wszystkich kodów int liczba_kodow; // określa ile jest kodów w tablicy // inicjujemy generator pseudolosowy srand((unsigned)time(NULL)); // tworzymy tablicę wszystkich kodów for(int i = 0; i < 1296; i++) { string kod = " "; int v = i; kod[0] = 65 + v / 216; v = v % 216; kod[1] = 65 + v / 36; v = v % 36; kod[2] = 65 + v / 6; v = v % 6; kod[3] = 65 + v; tablica_kodow[i] = kod; } liczba_kodow = 1296; // powitanie w grze, określamy, kto jest koderem, a kto łamaczem kodu cout << "MASTER MIND\n" "-----------\n\n" "(C)2010 KOLO INFORMATYCZNE w I-LO w Tarnowie\n\n" "Czy chcesz byc koderem? : "; getline(cin,odpowiedz); cout << endl << endl; koder = (odpowiedz[0] != 't') && (odpowiedz[0] != 'T'); // Jeśli komputer jest koderem, to generuje tajny kod if(koder) { tajny_kod = ""; for(int i = 0; i < 4; i++) tajny_kod += 65 + rand() % 6; } // rozpoczynamy rozgrywkę z 6 rund for(int runda = 1; runda <= 6; runda++) { cout << "RUNDA NR " << runda << " : "; // jeśli koderem jest komputer, to gracz wprowadza swój kod, // inaczej komputer wybiera losowy kod z tablicy kodów if(koder) { getline(cin,kod_gracza); while(kod_gracza.length() < 4) kod_gracza += " "; } else { kod_gracza = tablica_kodow[rand() % liczba_kodow]; cout << kod_gracza << endl; } // jeśli koderem jest komputer, to on ocenia kod gracza // inaczej gracz wprowadza swoja ocenę, a komputer eliminuje // nie pasujące do niej kody z tablicy cout << " : "; if(koder) { odpowiedz = ocena_kodow(tajny_kod,kod_gracza); cout << odpowiedz << endl; } else { getline(cin,odpowiedz); int i,j; for(j = i = 0; i < liczba_kodow; i++) if(odpowiedz == ocena_kodow(kod_gracza,tablica_kodow[i])) tablica_kodow[j++] = tablica_kodow[i]; liczba_kodow = j; } if(odpowiedz == "xxxx") break; } // koniec gry. if(odpowiedz == "xxxx") cout << endl << "### GRATULACJE ###" << endl; else if(koder) cout << endl << "NIE ODGADLES " << tajny_kod << endl; return 0; } |
Uwaga: w tej uproszczonej wersji program nie jest odporny na błędne wprowadzenie danych przez użytkownika.
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe