Obiekt string - gra Master Mind

Zapoznaj się z materiałami przedstawionymi na poprzednich zajęciach koła:

 

Utwórz nowy katalog projektowy. Skopiuj do niego pliki biblioteki:

newconio.cpp  -  plik źródłowy biblioteki
newconio.h  - plik nagłówkowy dla biblioteki

Utwórz nowy projekt konsoli w Dev-C++. Do projektu dodaj plik źródłowy newconio.cpp z twojego katalogu projektowego.

 

String

Mocnym atutem języka C++ jest biblioteka standardowych szablonów STL (ang. Standard Template Library), która udostępnia programiście wiele pożytecznych obiektów danych oraz algorytmów operujących na tych obiektach. Dzięki STL programowanie w C++ jest o wiele prostsze.

Obiekt string przechowuje dynamiczny łańcuch znaków. Na dzisiejszych zajęciach poznamy podstawowe funkcje tego obiektu.

 

Plik nagłówkowy string

W programie wykorzystującym obiekt string należy dołączyć plik nagłówkowy:

 

#include <string>

 

Typ danych string

Po dołączeniu pliku nagłówkowego string dostajemy typ danych o nazwie string, na podstawie którego możemy budować zmienne klasy string:

 

string zmienna_string;

 

Zmienna typu string przechowuje łańcuch znaków, czyli ciąg literek. Literki można wprowadzić do zmiennej za pomocą instrukcji przypisania:

 

zmienna_string = "ABCDEF";

 

lub odczytać je ze strumienia konsoli:

 

cin >> zmienna_string;

 

Dostęp do poszczególnych znaków przechowywanych w zmiennej łańcuchowej otrzymujemy za pomocą operatora [] oraz numeru znaku:

 

string a = "ABCDEF";
cout << a[0] << a[5] << endl;

...

 

Powyższy przykład umieszcza w zmiennej łańcuchowej a tekst ABCDEF i wyświetla pierwszą i ostatnią literkę. Otrzymamy zatem wydruk liter AF.

 

string a = "ABCDEF";
cout << a << endl;

a[0] = 'X';
a[5] = 'Z';

cout << a << endl;

...

 

Na wydruku otrzymamy:

ABCDEF
XBCDEZ

 

Operacje na łańcuchach

Porównanie:

    a == b

Jeśli a i b są zmiennymi łańcuchowymi, to porównanie daje wynik true, gdy zmienna a zawiera dokładnie ten sam tekst co zmienna b. W przeciwnym razie wynikiem jest false.

    a != b

Wynik true, gdy tekst w zmiennej a różni się od tekstu w zmiennej b (nawet jedną literką!). W przeciwnym razie wynikiem jest true.

    a < b

Jest to tzw. porównanie leksykograficzne. Porównywane są kolejne literki obu tekstów aż do napotkania niezgodności. Jako mniejszy uważa się ten z tekstów, w którym niezgodny znak posiada mniejszy kod. Na przykład:

    a = "Jan";  b = "Jar";

Teksty różnią się ostatnią literą. Zatem:

    a < b  - true, gdyż kod 'n' = 110, kod 'r' = 114  i 110 < 114.

Jeśli jeden z tekstów jest prefiksem drugiego tekstu i jest krótszy, to uważa się go za mniejszy:

    a = "Jan"; b = "Janek";
    a < b
- true, ponieważ Jan jest prefiksem Janek i jest krótszy.

 

Dołączanie znaków:

Operator + w znaczeniu do tekstów oznacza dołączanie, czyli tzw. konkatencję. Niech a, b  i c będą zmiennymi łańcuchowymi:

    a = 'A' + 'B';  // w a znajdzie się tekst "AB"
    b = "CDEF";
    c = a + b;      // w c znajdzie się połączenie tekstów a i b, czyli "ABCDEF"

Operator += dołącza do zawartości zmiennej nowy tekst:

    a = "" ;  // łańcuch pusty, czyli nie zawierający żadnego znaku
    for(int i = 0; i < 10; i++) a += "AB";

Po zakończeniu pętli zmienna a będzie zwierała 10 razy powtórzony tekst AB, czyli ABABABABABABABABABAB

Znaki są traktowane w języku C++ jak liczby całkowite będące kodami ASCII tych znaków. Dzięki temu w prosty sposób możemy używać znaków w wyrażeniach arytmetycznych:

    a = "";
    for(int i = 65; i <= 90; i++) a += i;
    cout << a << endl;

Wynikiem tego fragmentu kodu jest wyświetlenie kolejnych literek alfabetu od A do Z, które zostały umieszczone w zmiennej a przez pętlę iteracyjną. Literki te posiadają kody ASCII od 65 do 90.

 

Długość łańcucha:

Liczba znaków zawartych w tekście przechowywanym przez zmienną łańcuchową nosi nazwę długości łańcucha (ang. string length). Obiekt string posiada wiele użytecznych funkcji. Jedną z nich jest length(), która zwraca nam liczbę znaków aktualnie przechowywanych w zmiennej. Funkcję wywołujemy następująco:

    zmienna_string.length();

Na przykład:

    string a = "ABCD";
    cout << a.length() << endl;  // otrzymamy wynik 4

 

Gra Master Mind

Jest to prosta gra logiczna o następujących zasadach:

Komputer losuje 4-ro literowy kod zbudowany z literek A, B, C, D, E i F. Kod ten nie jest ujawniany. Zadaniem gracza-człowieka jest odgadnięcie wylosowanego kodu w maksymalnie 6 próbach. W tym celu gracz wprowadza swoje kody zbudowane z tych samych literek. Komputer ocenia wprowadzony kod następująco:

Jeśli literka w kodzie gracza i komputera jest taka sama i na tej samej pozycji, to komputer wypisuje znak x - trafiona literka kodu.
Jeśli litera kodu gracza znajduje się w kodzie komputera na innej pozycji, to komputer wypisuje znak o.

Oczywiście nie wiadomo o które znaki chodzi.

Na przykład:

 

Kod komputera ABCD  
Kod gracza EFBF  o - jedna literka trafiona (B), ale na innej pozycji
Kod gracza AFFD  xx - dwie literki trafione na dobrych pozycjach (A i D)
Kod gracza ACFD  xxo  - dwie trafione na dobrych pozycjach (A i D) oraz jedna na innej pozycji (C)

 

Wykorzystując logikę gracz-człowiek na podstawie odpowiedzi komputera odtwarza kod komputera. Gra wymaga zatem inteligencji oraz umiejętności logicznego wnioskowania.

 

Program

// Master Mind
// (C)2008 Koło informatyczne w I LO w Tarnowie
// Kurs programowania w C++ dla początkujących
//--------------------------------------------

#include <iostream>
#include <string>
#include "newconio.h"

using namespace std;

// Wyświetla prosty ekran tytułowy i oczekuje
// na wciśnięcie dowolnego klawisza
//-------------------------------------------

void ekran_tytulowy()
{
  textattr(0x1f); clrscr();
  center(24,"M A S T E R   M I N D");
  textcolor(YELLOW);
  center(26,_pl("(C)2008 Koło informatyczne w I-LO"));
  textcolor(LIGHTGRAY);
  center(49,_pl("Aby rozpocząć, naciśnij dowolny klawisz"));
  while(!getch());
}

// Funkcja wywoływana po zakończeniu rozgrywki.
// Sprawdza, czy gracz ma ochotę zagrać jeszcze
// raz. Jeśli tak, zwraca true, inaczej false
//---------------------------------------------

bool jeszcze_raz()
{
  char c;
  textcolor(LIGHTRED);
  center(49,_pl("Chcesz zagrać jeszcze raz? (t = TAK) "));
  
  while(!(c = getch()));
  return c == 't';
}

// Ocenia kod wprowadzony przez gracza
// Wyświetla literkę x dla każdego znaku
// w kodzie gracza zgodnego ze znakiem
// kodu komputera co do wartości i miejsca
// lub literkę o dla znaku zgodnego co do
// wartości, lecz znajdującego się na innej
// pozycji w kodzie komputera.
// k - kod komputera
// g - kod gracza
//-----------------------------------------

void ewaluacja(string k,  string g)
{
  int i,j;
  
// Ponieważ gracz mógł wprowadzić mniej niż 4 znaki kodu,
// wyrównujemy spacjami jego kod do 4 znaków
 
  while(g.length() < 4) g += " ";

// Najpierw analizujemy zgodność znaków kodu gracza
// ze znakami kodu komputera co do wartości i pozycji

  textcolor(LIGHTGREEN);

// Przeglądamy kolejne znaki obu kodów i jeśli są
// takie same, to wyświetlamy jasnozieloną literkę x
// Znaki w obu kodach musimy zniszczyć, aby nie były
// powtórnie zliczone przez dalszą część algorytmu
// Możemy tak zrobić, ponieważ funkcja otrzymuje kopie
// kodów, z którymi może sobie zrobić to, co chce.

  for(i = 0; i < 4; i++)
    if(k[i] == g[i])
    {
      cout << "x";
      k[i] = '?';  // niszczymy znak i-ty kodu komputera
      g[i] = '@';  // niszczymy znak i-ty kodu gracza
    }

// Teraz badamy zgodność liter kodu gracza z literami
// kodu komputera. Ponieważ litery równe na tych samych
// pozycjach w obu kodach zostały zniszczone, nie zliczymy
// ich. Kolejne litery kodu gracza porównujemy ze wszystkimi
// literami kodu komputera. Jeśli znajdziemy równość, to
// wyświetlamy zółtą literkę o, a literę w kodzie komputera
// niszczymy i przerywamy pętlę wewnętrzną

  textcolor(YELLOW);
  for(i = 0; i < 4; i++)
    for(j = 0; j < 4; j++)
      if(g[i] == k[j])
      {
        cout << "o";
        k[j] = '?'; // niszczymy znak j-ty w kodzie komputera
        break;
      }
}

// Główna funkcja gry
//-------------------

void gra()
{
  string kkod; // zawiera kod komputera
  string gkod; // zawiera kod gracza
  
// Pętla gry

  do
  {
    textattr(0x07); clrscr();
    
// Generujemy 4-ro literowy kod komputera. Najpierw
// zerujemy łańcuch kkod

    kkod = "";
    
// Teraz w pętli losujemy przypadkowe literki od A do F
// i dołączamy je na koniec łańcucha kkod

    for(int i = 0; i < 4; i++) kkod += 65 + rand() % 6;
    
    textcolor(CYAN);
    cout << "*** MASTER MIND ***\n\n";
    
// Rozgrywka składa się z maksymalnie 6 prób odgadnięcia
// kodu komputera. Realizujemy ją za pomocą pętli iteracyjnej

    for(int i = 1; i <= 6; i++)
    {

// Wyświetlamy numer próby i odczytujemy kod gracza

      textcolor(GREEN);
      gotoxy(0,2 + 2 * i);
      cout << "Runda nr " << i << " : ";
      textcolor(YELLOW);
      cursoron(); cin >> gkod; cursoroff();

// Ustawiamy pozycję wydruku za kodem wprowadzonym
// przez gracza. Jest to konieczne, ponieważ ewaluację
// tego kodu chcemy otrzymać w tym samym wierszu

      gotoxy(19,2 + 2 * i);

// oceniamy prowadzony kod

      ewaluacja(kkod,gkod);

// Jeśli gracz odgadł kod komputera, wyświetlamy gratulacje
// i przerywamy pętlę

      if(kkod == gkod)
      {
        textcolor(WHITE);
        gotoxy(24,2 + 2 * i);
        cout << "*** BRAWO ***";
        break;
      }
      
// Jeśli obecny obieg jest ostatnim, to gracz nie odgadł
// kodu komputera w 6 próbach. W takim razie przed
// zakończeniem pętli wyświetlamy kod komputera
      
      if(i == 6)
      {
        textcolor(LIGHTRED);
        gotoxy(13,4 + 2 * i);
        cout << kkod;
      }
    }    

// Sprawdzamy, czy gracz chce zagrać ponownie. Jeśli tak,
// to wykonujemy następny obieg pętli gry

  } while(jeszcze_raz());
}

// Program główny
//---------------

main()
{

// Inicjujemy bibliotekę newconio

  _cinit();
  
// Inicjujemy generator liczb pseudolosowych

  srand((unsigned)time(NULL));
  
// Przechodzimy w tryb pełnoekranowy, wyświetlamy ekran
// tytułowy i rozpoczynamy grę.

  fullscreen(true);
  cursoroff();
  ekran_tytulowy();
  gra();
  cursoron();
  fullscreen(false);  
}
*** MASTER MIND ***



Runda nr 1 : ABCD x

Runda nr 2 : EFCC xooo

Runda nr 3 : FCDE xxx

Runda nr 4 : FEDC xoo

Runda nr 5 : FCCE xxxx *** BRAWO ***

 


   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2024 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.

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