Mini Master Mind - programy


W tym rozdziale: Podrozdziały:

 

Prezentowane poniżej programy utworzono w następujących środowiskach programowania:

Jeśli stosujesz inne środowiska, to prawdopodobnie będziesz musiał przetworzyć odpowiednio kod programów.

 

Programy

Na podstawie opisanego algorytmu tworzymy program w języku Pascal. Poniżej przedstawiamy przykładowe zrzuty zawartości okienka konsoli oraz kod źródłowy programu.

 

obrazek
Plansza tytułowa gry
obrazek
Przykładowa rozgrywka

 

Program w języku Pascal

//          M A S T E R   M I N D
//           WERSJA PROCEDURALNA
//--------------------------------------------
// (C)2004 mgr Jerzy Wałaszek  I LO w Tarnowie

program mastermind;

uses Crt;

//----------------------------------------------------
// PROCEDURY I FUNKCJE POMOCNICZE
//----------------------------------------------------

// Funkcja PL konwertuje tekst ze standardu Windows 1250
// na standard konsoli znakowej Latin II
//------------------------------------------------------
function PL(s : string) : string;
var
  i : integer;
  c : char;
begin
  for i := 1 to length(s) do
  begin
   case s[i] of
      'ą' : c := #165;
      'ć' : c := #134;
      'ę' : c := #169;
      'ł' : c := #136;
      'ń' : c := #228;
      'ó' : c := #162;
      'ś' : c := #152;
      'ż' : c := #190;
      'ź' : c := #171;
      'Ą' : c := #164;
      'Ć' : c := #143;
      'Ę' : c := #168;
      'Ł' : c := #157;
      'Ń' : c := #227;
      'Ó' : c := #224;
      'Ś' : c := #151;
      'Ż' : c := #189;
      'Ź' : c := #141;
      else
        c := s[i]; 
    end;
    s[i] := c;
  end;
  Result := s;
end;

// Procedura centruje w bieżącym wierszu
// tekst podany jako parametr
//----------------------------------------------------
procedure Centruj(t : string);
begin
  GotoXY(1 + (80-length(t)) div 2, WhereY);
  writeln(t);
end;

// Procedura rysuje pojedynczą ramkę ze znaków
// tabelek. Parametry określają współrzędne
// lewego górnego i prawego dolnego narożnika
//----------------------------------------------------
procedure Ramka(xp,yp,xk,yk : integer);
var
  i : integer;
begin
  GotoXY(xp,yp); write(#218);
  GotoXY(xp,yk); write(#192);
  GotoXY(xk,yp); write(#191);
  GotoXY(xk,yk); write(#217);
  for i := xp + 1 to xk - 1 do
  begin
    GotoXY(i,yp); write(#196);
    GotoXY(i,yk); write(#196);
  end;
  for i := yp + 1 to yk - 1 do
  begin
    GotoXY(xp,i); write(#179);
    GotoXY(xk,i); write(#179);
  end;
end;

//----------------------------------------------------
// PROGRAM GRY
//----------------------------------------------------

// Zmienne globalne dla procedur programu
//----------------------------------------------------
var
  z,t   : array[0..3] of integer;
  runda : integer;

// Procedura wyświetla planszę tytułową gry
//----------------------------------------------------
procedure Tytul;
begin
  TextAttr := $07; ClrScr;
  GotoXY(1,3);
  TextAttr := $3b;
  Centruj(PL('                                  '));
  Centruj(PL('  GRA INTELEKTU ----------------  '));
  Centruj(PL('  -------------------MASTER MIND  '));
  Centruj(PL('                                  '));
  TextAttr := $1f;
  Centruj(PL('                                  '));
  Centruj(PL('    (C)2004 mgr Jerzy Wałaszek    '));
  Centruj(PL('                                  '));
  TextAttr := $2e;
  Centruj(PL('                                  '));
  Centruj(PL('     I Liceum Ogólnokształcące    '));
  Centruj(PL('   im. Kazimierza  Brodzińskiego  '));
  Centruj(PL('             w Tarnowie           '));
  Centruj(PL('                                  '));
  TextAttr := $f0;
  Centruj(PL('                                  '));
  Centruj(PL('   Odgadnij w sześciu kolejkach   '));
  Centruj(PL('   kod koloru  wylosowany przez   '));
  Centruj(PL('    komputer z 6 różnych barw.    '));
  Centruj(PL('                                  '));
  TextAttr := $f4;
  Centruj(PL('        Gdy będziesz gotowy,      '));
  Centruj(PL('     naciśnij dowolny klawisz     '));
  Centruj(PL('                                  '));
  TextAttr := $0e; Ramka(23,2,58,23);
  while ReadKey = #0 do; // Oczekiwanie na dowolny klawisz
  TextAttr := $07; ClrScr;
end;

// Procedura losuje kod kolorów z
//----------------------------------------------------
procedure Losuj_z;
var
  i : integer;
begin
  for i := 0 to 3 do z[i] := random(6);
end;

// Procedura drukuje nagłówek gry - nazwę oraz
// pierwszy wiersz z zakrytym kodem komputera
//----------------------------------------------------
procedure Naglowek;
begin
  TextAttr := $4e;
  Centruj('    MASTER  MIND    ');
  TextAttr := $87;
  Centruj('                    ');
  Centruj('    ? ? ? ?         ');
  Centruj('                    ');
end;

// Procedura wyświetla w podanym wierszu y zawartość
// tablicy t lub z. Jeśli parametr kursor jest równy
// true, to wokół pozycji kodu nr x rysowana jest ramka
//----------------------------------------------------
procedure Wyswietl(var tz : array of integer;
                   x,y : integer; kursor : boolean);
const
  kolory : array[0..5] of integer =
  (Black,LightBlue,LightGreen,LightRed,LightMagenta,Yellow);
var
  i : integer;
begin
  TextAttr := $87; GotoXY(1,y);
  Centruj('                    ');
  GotoXY(31,WhereY);
  write(runda : 2, ': ');
  for i := 0 to 3 do
  begin
    TextAttr := $80 + kolory[tz[i]]; write(#219' ');
  end;
  writeln('        ');
  TextAttr := $80; Centruj('____________________');
  if kursor then
  begin
    TextAttr := $84; Ramka(34 + 2 * x, y, 36 + 2 * x, y + 2);
  end;
end;

// Procedura odczytuje kod kolorów gracza i umieszcza
// go w tablicy t
//----------------------------------------------------
procedure Czytaj_t;
var
  x,y,i : integer;
  c     : char;
begin
  y := WhereY; // zapamiętujemy pozycję w pionie
  for i := 0 to 3 do t[i] := 0;
  x := 0;
  repeat
    Wyswietl(t,x,y,true);
    repeat
      c := ReadKey;
    until c <> #0;
    Wyswietl(t,x,y,false);
    case c of
      #75 : x := (x + 3) mod 4;       //strzałka w lewo
      #77 : x := (x + 1) mod 4;       //strzałka w prawo
      #72 : t[x] := (t[x] + 1) mod 6; //strzałka w górę
      #80 : t[x] := (t[x] + 5) mod 6; //strzałka w dół
    end;
  until c = #13; // klawisz Enter
  GotoXY(1,y);
end;

// Procedura ocenia kod wprowadzony przez gracza
//----------------------------------------------------
procedure Ocen_t;
var
  kz,kt : array[0..3] of integer;
  czarne,biale,i,j : integer;
begin
  kz := z; kt := t;
  czarne := 0;
  for i := 0 to 3 do
    if kt[i] = kz[i] then
    begin
      inc(czarne); kz[i] := -1; kt[i] := -2;
    end;
  biale := 0;
  for i := 0 to 3 do
    for j := 0 to 3 do
      if kt[i] = kz[j] then
      begin
        inc(biale); kz[j] := -1; kt[i] := -2; break;
      end;
  GotoXY(43,WhereY + 1);
  TextAttr := $80; for i := 1 to czarne do write('* ');
  TextAttr := $8f; for i := 1 to biale  do write('* ');
  writeln; writeln;
end;

// Funkcja sprawdza, czy t jest równe z
//----------------------------------------------------
function t_rowne_z : boolean;
var
  test : boolean;
  i    : integer;
begin
  test := true;
  for i := 0 to 3 do test := test and (t[i] = z[i]);
  Result := test;
end;

// Blok główny programu
//----------------------------------------------------

var
  a : integer;
begin
  Randomize; CursorOff;
  a := TextAttr;
  repeat
    Tytul;
    Losuj_z;
    runda := 1;
    Naglowek;
    repeat
      Czytaj_t;
      Ocen_t;
      if t_rowne_z then
      begin
        TextAttr := $0e;
        Centruj(PL('GRATULACJE - odgadłeś kod komputera!'));
        break;
      end;
      inc(runda);
      if runda > 6 then
      begin
        TextAttr := $0c;
        Centruj(PL('GRA SKOŃCZONA - nie odgadłeś kodu komputera!'));
      end;
    until runda > 6;
    TextColor(White);
    Centruj('Zagrasz jeszcze raz ? [T] = Tak, [inny] = Nie');
    Wyswietl(z,0,2,false);
    GotoXY(32,3); write(' '); // usuwamy numer rundy
  until UpCase(ReadKey) <> 'T';
  TextAttr := a; CursorOn; ClrScr;
end.

 

Program obiektowy w języku Pascal

Gra Master Mind ma strukturę idealną dla projektu obiektowego. Stworzymy prostą hierarchię obiektów. Najpierw zaprojektujemy obiekt kodu komputera o następującej strukturze:

 

type

  TKod_z = class
    tz : array[0..3] of integer;
    constructor Create;
    procedure   Inicjuj;
    procedure   Wyswietl;
    procedure   Oceniaj(var t : array of integer);
  end;

 

Obiekt posiada metody:

Na podstawie obiektu TKod_z tworzymy obiekt pochodny TKod_t obsługujący kod gracza.

  TKod_t = class(TKod_z)
    public
      procedure Inicjuj(runda : integer);
      procedure Wyswietl(runda,kursor : integer);
  end;

 

W nowym obiekcie pokrywamy metodę Inicjuj, która ma odczytać z klawiatury kod gracza i odpowiednio ustawić dziedziczoną tablicę tz oraz Wyswietl, która przyjmuje dodatkowy parametr sterujący widocznością i pozycją ramki kursora.

W dalszej kolejności tworzymy obiekt gry zawierający w sobie utworzone wcześniej dwa obiekty:

  TMasterMind = class
    private
      z     : TKod_z;
      t     : TKod_t;
      runda : integer;
      procedure Ocen_t;
      function  t_rowne_z : boolean;
      function  KoniecGry : boolean;
    public
      constructor Create;
      procedure   StronaTytulowa;
      procedure   Graj;
      function    JeszczeRaz : boolean;
  end;

 

Obiekt ten zawiera kolejno następujące składniki:

//          M A S T E R   M I N D
//            WERSJA  OBIEKTOWA
//--------------------------------------------
// (C)2004 mgr Jerzy Wałaszek  I LO w Tarnowie

program mastermind;

uses Crt;

//----------------------------------------------------
// PROCEDURY I FUNKCJE POMOCNICZE
//----------------------------------------------------

// Funkcja PL konwertuje tekst ze standardu Windows 1250
// na standard konsoli znakowej Latin II
//------------------------------------------------------
function PL(s : string) : string;
var
  i : integer;
  c : char;
begin
  for i := 1 to length(s) do
  begin
   case s[i] of
      'ą' : c := #165;
      'ć' : c := #134;
      'ę' : c := #169;
      'ł' : c := #136;
      'ń' : c := #228;
      'ó' : c := #162;
      'ś' : c := #152;
      'ż' : c := #190;
      'ź' : c := #171;
      'Ą' : c := #164;
      'Ć' : c := #143;
      'Ę' : c := #168;
      'Ł' : c := #157;
      'Ń' : c := #227;
      'Ó' : c := #224;
      'Ś' : c := #151;
      'Ż' : c := #189;
      'Ź' : c := #141;
      else
        c := s[i]; 
    end;
    s[i] := c;
  end;
  Result := s;
end;

// Procedura centruje w bieżącym wierszu
// tekst podany jako parametr
//----------------------------------------------------
procedure Centruj(t : string);
begin
  GotoXY(1 + (80-length(t)) div 2, WhereY);
  writeln(t);
end;

// Procedura rysuje pojedynczą ramkę ze znaków
// tabelek. Parametry określają współrzędne
// lewego górnego i prawego dolnego narożnika
//----------------------------------------------------
procedure Ramka(xp,yp,xk,yk : integer);
var
  i : integer;
begin
  GotoXY(xp,yp); write(#218);
  GotoXY(xp,yk); write(#192);
  GotoXY(xk,yp); write(#191);
  GotoXY(xk,yk); write(#217);
  for i := xp + 1 to xk - 1 do
  begin
    GotoXY(i,yp); write(#196);
    GotoXY(i,yk); write(#196);
  end;
  for i := yp + 1 to yk - 1 do
  begin
    GotoXY(xp,i); write(#179);
    GotoXY(xk,i); write(#179);
  end;
end;

//------------------------------------------------------
// PROGRAM GRY
//------------------------------------------------------

// Deklaracje klas
//******************************************************

type

  TKod_z = class
      tz : array[0..3] of integer;
      constructor Create;
      procedure   Inicjuj;
      procedure   Wyswietl;
      procedure   Oceniaj(var t : array of integer);
  end;

  TKod_t = class(TKod_z)
      procedure Inicjuj(runda : integer);
      procedure Wyswietl(runda,kursor : integer);
  end;      

  TMasterMind = class
    private
      z     : TKod_z;
      t     : TKod_t;
      runda : integer;
      procedure Ocen_t;
      function  t_rowne_z : boolean;
      function  KoniecGry : boolean;
    public
      constructor Create;
      procedure   StronaTytulowa;
      procedure   Graj;
      function    JeszczeRaz : boolean;
    end;

// Definicje metod klas
//----------------------------------------------------

// Obiekt TKod_z
//****************************************************

constructor TKod_z.Create;
begin
  // standardowe działanie
end;

// Metoda losuje kod kolorów dla komputera i umieszcza
// go w tablicy tz obiektu
//------------------------------------------------------
procedure   TKod_z.Inicjuj;
var
  i : integer;
begin
  for i := 0 to 3 do tz[i] := random(6);
end;

// Metoda wyświetla na bieżącej pozycji kolejne
// kolory zawarte w kodzie tz. Kolory są wyświetlane
// w postaci kolorowych prostokątów oddzielonych spacją.
//------------------------------------------------------
procedure TKod_z.Wyswietl;
const
  kolory : array[0..5] of integer =
  (Black,LightBlue,LightGreen,LightRed,LightMagenta,Yellow);
var
  i : integer;
begin
  for i := 0 to 3 do
  begin
    TextAttr := $80 + kolory[tz[i]]; write(#219' ');
  end;
end;

// Procedura porównuje podany jej w formie tablicy kod
// z kodem w polu tz. Wynik jest wyświetlany na bieżącej
// pozycji ekranu w postaci gwiazdek czarnych - zgodność
// kolorów i pozycji oraz białych - zgodność kolorów
//------------------------------------------------------
procedure TKod_z.Oceniaj(var t : array of integer);
var
  kz,kt : array[0..3] of integer;
  czarne,biale,i,j : integer;
begin
  kz := tz; kt := t;
  czarne := 0;
  for i := 0 to 3 do
    if kt[i] = kz[i] then
    begin
      inc(czarne); kz[i] := -1; kt[i] := -2;
    end;
  biale := 0;
  for i := 0 to 3 do
    for j := 0 to 3 do
      if kt[i] = kz[j] then
      begin
        inc(biale); kz[j] := -1; kt[i] := -2; break;
      end;
  TextAttr := $80; for i := 1 to czarne do write('* ');
  TextAttr := $8f; for i := 1 to biale  do write('* ');
end;

// Obiekt TKod_t
//***********************************************************

// Zmodyfikowana procedura wyświetlania kodu tz,
// z której korzysta obiekt kodu gracza. Wyświetla
// ona w bieżącym wierszu ekranu segment gry, który
// oprócz kodu zawierać może dodatkowo kursor, czyli
// prostokątną ramkę otaczającą kwadrat koloru na
// pozycji kursor. Przed kodem koloru wyświetlony
// zostaje numer rundy, który obiekt kodu gracza
// otrzymuje z obiektu gry.
//------------------------------------------------------
procedure TKod_t.Wyswietl(runda,kursor : integer);
var
  y : integer;
begin
  y := WhereY; // zapamiętujemy pozycję wydruku
  TextAttr := $87; GotoXY(1,y);
  Centruj('                    ');
  GotoXY(31,WhereY); write(runda : 2, ': ');

  inherited Wyswietl;  // do wyświetlenia kodu wykorzystujemy
                       // odziedziczoną metodę
  writeln('        ');
  TextAttr := $80; Centruj('____________________');
  if kursor >= 0 then
  begin
    TextAttr := $84; Ramka(34 + 2 * kursor, y, 36 + 2 * kursor, y + 2);
  end;
  GotoXY(1,y);  // odtwarzamy pozycję wydruku
end;

// Procedura odczytuje kod koloru gracza.
//------------------------------------------------------
procedure TKod_t.Inicjuj(runda : integer);
var
  x,i : integer;
  c     : char;
begin
  for i := 0 to 3 do tz[i] := 0;
  x := 0;
  repeat
    Wyswietl(runda,x);
    repeat
      c := ReadKey;
    until c <> #0;
    Wyswietl(runda,-1); // to usunie kursor z ekranu
    case c of
      #75 : x     := (x + 3) mod 4;     //strzałka w lewo
      #77 : x     := (x + 1) mod 4;     //strzałka w prawo
      #72 : tz[x] := (tz[x] + 1) mod 6; //strzałka w górę
      #80 : tz[x] := (tz[x] + 5) mod 6; //strzałka w dół
    end;
  until c = #13; // klawisz Enter
end;

// Obiekt TMasterMind
//*************************************************************

// Metoda ocenia kod wprowadzony przez gracza. Wydruk
// jest przemieszczany do następnego segmentu gry.
//------------------------------------------------------
procedure TMasterMind.Ocen_t;
begin
  GotoXY(43, WhereY + 1); // ustawiamy pozycję oceny
  z.Oceniaj(t.tz);        // oceniamy kod gracza
  writeln; writeln;       // przechodzimy do następnego segmentu
end;

// Metoda porównuje obiekty z i t. Zwraca true, jeśli
// zawierają ten sam kod.
//------------------------------------------------------
function TMasterMind.t_rowne_z : boolean;
var
  test : boolean;
  i    : integer;
begin
  test := true;
  for i := 0 to 3 do test := test and (z.tz[i] = t.tz[i]);
  Result := test;
end;

// Metoda testuje warunek zakończenia gry. Jeśli gra się
// kończy, wypisuje odpowiedni komunikat i zwraca true
//------------------------------------------------------
function TMasterMind.KoniecGry : boolean;
begin
  inc(runda);      // zwiększamy numer rundy
  Result := false; // zakładamy, że gra się nie kończy
  if t_rowne_z then
  begin
    TextAttr := $0e;
    Centruj(PL('GRATULACJE - odgadłeś kod komputera!'));
    GotoXY(35,3); z.Wyswietl;  // wyświetlamy kod komputera
    Result := true;
  end
  else if runda > 6 then
  begin
    TextAttr := $0c;
    Centruj(PL('GRA SKOŃCZONA - nie odgadłeś kodu komputera!'));
    GotoXY(35,3); z.Wyswietl;
    Result := true
  end;
end;

constructor TMasterMind.Create;
begin
  z := TKod_z.Create;
  t := TKod_t.Create;
end;

// Metoda wyświetla stronę tytułową i czeka na
// dowolny klawisz, po czym czyści ekran.
//------------------------------------------------------
procedure TMasterMind.StronaTytulowa;
begin
  TextAttr := $07; ClrScr;
  GotoXY(1,3);
  TextAttr := $3b;
  Centruj(PL('                                  '));
  Centruj(PL('  GRA INTELEKTU ----------------  '));
  Centruj(PL('  -------------------MASTER MIND  '));
  Centruj(PL('                                  '));
  TextAttr := $1f;
  Centruj(PL('                                  '));
  Centruj(PL('    (C)2004 mgr Jerzy Wałaszek    '));
  Centruj(PL('                                  '));
  TextAttr := $2e;
  Centruj(PL('                                  '));
  Centruj(PL('     I Liceum Ogólnokształcące    '));
  Centruj(PL('   im. Kazimierza  Brodzińskiego  '));
  Centruj(PL('             w Tarnowie           '));
  Centruj(PL('                                  '));
  TextAttr := $f0;
  Centruj(PL('                                  '));
  Centruj(PL('   Odgadnij w sześciu kolejkach   '));
  Centruj(PL('   kod koloru  wylosowany przez   '));
  Centruj(PL('    komputer z 6 różnych barw.    '));
  Centruj(PL('                                  '));
  TextAttr := $f4;
  Centruj(PL('        Gdy będziesz gotowy,      '));
  Centruj(PL('     naciśnij dowolny klawisz     '));
  Centruj(PL('                                  '));
  TextAttr := $0e; Ramka(23,2,58,23);
  while ReadKey = #0 do; // Oczekiwanie na dowolny klawisz
  TextAttr := $07; ClrScr;
end;

// Metoda odpowiedzialna za prowadzenie gry.
//------------------------------------------------------
procedure TMasterMind.Graj;
begin
  z.Inicjuj; runda := 1;
  TextAttr := $4e;
  Centruj('    MASTER  MIND    ');
  TextAttr := $87;
  Centruj('                    ');
  Centruj('    ? ? ? ?         ');
  Centruj('                    ');
  repeat
    t.Inicjuj(runda);
    Ocen_t;
  until KoniecGry;
end;

// Metoda upewnia się, że gracz ma ochotę na jeszcze
// jedną grę. Zwraca w atkim wypadku true.
//------------------------------------------------------
function TMasterMind.JeszczeRaz : boolean;
begin
  GotoXY(1,24); TextColor(White);
  Centruj('Zagrasz jeszcze raz ? [T] = Tak, [inny] = Nie');
  Result := (UpCase(ReadKey) = 'T');
end;

// Blok główny programu
//--------------------------------------------------

var
  gra : TMasterMind;
  a   : integer;

begin
  a := TextAttr; CursorOff;
  Randomize;
  gra := TMasterMind.Create;
  with gra do
    repeat
      StronaTytulowa;
      Graj;
    until not JeszczeRaz;
  TextAttr := a; CursorOn; ClrScr;
end.

 

Program w języku C++

//          M A S T E R   M I N D
//--------------------------------------------
// (C)2004 mgr Jerzy Wałaszek  I LO w Tarnowie

#include <conio.h>
#include <windows.h>
#include <strings.h>
#include <iostream>

using namespace std;

//----------------------------------------------------
// Deklaracja klasy gry
//----------------------------------------------------

  class TKod_z
  {
     public:
      int tz[4];
      void Inicjuj();
      void Wyswietl();
      void Oceniaj(int t[]);
  };

  class TKod_t : public TKod_z
  {
     public:
       void Inicjuj(int runda);
       void Wyswietl(int runda, int kursor);
  };      

  class TMasterMind
  {
      TKod_z z;
      TKod_t t;
      int runda;
      void Ocen_t();
      int t_rowne_z();
      int KoniecGry();
    public:
      void StronaTytulowa();
      void Graj();
      int JeszczeRaz();
  };

//----------------------------------------------------
// PROCEDURY I FUNKCJE POMOCNICZE
//----------------------------------------------------

const int BLACK        = 0;
const int BLUE         = 1;
const int GREEN        = 2;
const int CYAN         = 3;
const int RED          = 4;
const int MAGENTA      = 5;
const int BROWN        = 6;
const int LIGHTGRAY    = 7;
const int DARKGRAY     = 8;
const int LIGHTBLUE    = 9;
const int LIGHTGREEN   = 10;
const int LIGHTCYAN    = 11;
const int LIGHTRED     = 12;
const int LIGHTMAGENTA = 13;
const int YELLOW       = 14;
const int WHITE        = 15;

static int __BACKGROUND = BLACK;
static int __FOREGROUND = LIGHTGRAY;

// Procedura ustawia pozycję wydruku w oknie konsoli
//----------------------------------------------------
void gotoxy(int x, int y)
{
  COORD c;

  c.X = x - 1;
  c.Y = y - 1;
  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}

// Procedura ustawia kolor tła wydruku
//----------------------------------------------------
void textbackground(int color)
{
  __BACKGROUND = color;
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
    __FOREGROUND + (color << 4));
}

// Procedura ustawia kolor tekstu
//----------------------------------------------------
void textcolor(int color)
{
  __FOREGROUND = color;
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
    color + (__BACKGROUND << 4));
}

// Procedura ustawia atrybuty koloru tekstu i tła
//----------------------------------------------------
void textattr(int _attr)
{
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _attr);
}

// Funkcja zwraca aktualną pozycję x kursora
//----------------------------------------------------
int wherex()
{
  CONSOLE_SCREEN_BUFFER_INFO info;

  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
  return info.dwCursorPosition.X + 1;
}

// Funkcja zwraca aktualną pozycję y kursora
//----------------------------------------------------
int wherey()
{
  CONSOLE_SCREEN_BUFFER_INFO info;

  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
  return info.dwCursorPosition.Y + 1;
}

// Procedura czyści zawartość okna konsoli
//----------------------------------------------------
void clrscr()
{
  DWORD written;

  FillConsoleOutputAttribute(GetStdHandle (STD_OUTPUT_HANDLE),
    __FOREGROUND + (__BACKGROUND << 4), 2000, (COORD){0, 0}, &written);
  FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), ' ',
    2000, (COORD){0, 0}, &written);
  gotoxy(1, 1);
}

// Procedura ukrywa kursor okienka konsoli
//------------------------------------------------------
void CursorOff()
{
  CONSOLE_CURSOR_INFO Info;

  GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); 
  Info.bVisible = 0;
  SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); 
};

// Procedura przywraca kursor okienka konsoli
//------------------------------------------------------
void CursorOn()
{
  CONSOLE_CURSOR_INFO Info;

  GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); 
  Info.bVisible = -1;
  SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); 
};

// Funkcja PL konwertuje tekst ze standardu Windows 1250
// na standard konsoli znakowej Latin II
//------------------------------------------------------
string PL(string s)
{
  int i;
  char c;

  for(i = 0; i < s.length(); i++)
  {
    switch(s[i])
    {
      case 'ą' : c = char(165); break;
      case 'ć' : c = char(134); break;
      case 'ę' : c = char(169); break;
      case 'ł' : c = char(136); break;
      case 'ń' : c = char(228); break;
      case 'ó' : c = char(162); break;
      case 'ś' : c = char(152); break;
      case 'ż' : c = char(190); break;
      case 'ź' : c = char(171); break;
      case 'Ą' : c = char(164); break;
      case 'Ć' : c = char(143); break;
      case 'Ę' : c = char(168); break;
      case 'Ł' : c = char(157); break;
      case 'Ń' : c = char(227); break;
      case 'Ó' : c = char(224); break;
      case 'Ś' : c = char(151); break;
      case 'Ż' : c = char(189); break;
      case 'Ź' : c = char(141); break;
      default:   c = s[i]; 
    };
    s[i] = c;
  };
  return(s);
}

// Procedura centruje w bieżącym wierszu
// tekst podany jako parametr
//----------------------------------------------------
void Centruj(string t)
{
  gotoxy(1 + (80 - t.length()) / 2, wherey());
  cout << t << endl;
}

// Procedura rysuje pojedynczą ramkę ze znaków
// tabelek. Parametry określają współrzędne
// lewego górnego i prawego dolnego narożnika
//----------------------------------------------------
void Ramka(int xp,int yp,int xk,int yk)
{
  int i;

  gotoxy(xp,yp); putch(char(218));
  gotoxy(xp,yk); putch(char(192));
  gotoxy(xk,yp); putch(char(191));
  gotoxy(xk,yk); putch(char(217));
  for(i = xp + 1; i <= xk - 1; i++)
  {
    gotoxy(i,yp); putch(char(196));
    gotoxy(i,yk); putch(char(196));
  };
  for(i = yp + 1; i <= yk - 1; i++)
  {
    gotoxy(xp,i); putch(char(179));
    gotoxy(xk,i); putch(char(179));
  };
}

//----------------------------------------------------
// Definicje metod klasy gry
//----------------------------------------------------

// Obiekt TKod_z
//****************************************************

// Metoda losuje kod kolorów dla komputera i umieszcza
// go w tablicy tz obiektu
//------------------------------------------------------
void TKod_z::Inicjuj()
{
  for(int i = 0; i <= 3; i++) tz[i] = rand() % 6;
}

// Metoda wyświetla na bieżącej pozycji kolejne
// kolory zawarte w kodzie tz. Kolory są wyświetlane
// w postaci kolorowych prostokątów oddzielonych spacją.
//------------------------------------------------------
void TKod_z::Wyswietl()
{
const int kolory[6] =
  {BLACK,LIGHTBLUE,LIGHTGREEN,LIGHTRED,LIGHTMAGENTA,YELLOW};

  for(int i = 0; i <= 3; i++)
  {
    textattr(0x80 + kolory[tz[i]]);
    cout << char(219) << ' ';
  };
}

// Procedura porównuje podany jej w formie tablicy kod
// z kodem w polu tz. Wynik jest wyświetlany na bieżącej
// pozycji ekranu w postaci gwiazdek czarnych - zgodność
// kolorów i pozycji oraz białych - zgodność kolorów
//------------------------------------------------------
void TKod_z::Oceniaj(int t[])
{
  int kz[4],kt[4],czarne,biale,i,j;

  for(i = 0; i <= 3; i++)
  {
    kz[i] = tz[i]; kt[i] = t[i];
  };
  czarne = 0;
  for(i = 0; i <= 3; i++)
    if(kt[i] == kz[i])
    {
      czarne++; kz[i] = -1; kt[i] = -2;
    };
  biale = 0;
  for(i = 0; i <= 3; i++)
    for(j = 0; j <= 3; j++)
      if(kt[i] == kz[j])
      {
        biale++; kz[j] = -1; kt[i] = -2; break;
      };
  textattr(0x80); for(i = 1; i <= czarne; i++) cout << "* ";
  textattr(0x8f); for(i = 1; i <= biale; i++)  cout << "* ";
}

// Obiekt TKod_t
//***********************************************************

// Zmodyfikowana procedura wyświetlania kodu tz,
// z której korzysta obiekt kodu gracza. Wyświetla
// ona w bieżącym wierszu ekranu segment gry, który
// oprócz kodu zawierać może dodatkowo kursor, czyli
// prostokątną ramkę otaczającą kwadrat koloru na
// pozycji kursor. Przed kodem koloru wyświetlony
// zostaje numer rundy, który obiekt kodu gracza
// otrzymuje z obiektu gry.
//------------------------------------------------------
void TKod_t::Wyswietl(int runda, int kursor)
{
  int y;

  y = wherey(); // zapamiętujemy pozycję wydruku
  textattr(0x87); gotoxy(1,y);
  Centruj("                    ");
  gotoxy(31,wherey()); cout << " " << runda << ": ";
  TKod_z::Wyswietl();  // do wyświetlenia kodu wykorzystujemy
                       // odziedziczoną metodę
  cout << "        \n";
  textattr(0x80); Centruj("____________________");
  if(kursor >= 0)
  {
    textattr(0x84); Ramka(34 + 2 * kursor, y, 36 + 2 * kursor, y + 2);
  };
  gotoxy(1,y);  // odtwarzamy pozycję wydruku
}

// Procedura odczytuje kod koloru gracza.
//------------------------------------------------------
void TKod_t::Inicjuj(int runda)
{
  int x,i;
  char c;

  for(i = 0; i <= 3; i++) tz[i] = 0;
  x = 0;
  do
  {
    Wyswietl(runda,x);
    do
    {
      c = getch();
    } while(c == '\0');
    Wyswietl(runda,-1); // to usunie kursor z ekranu
    switch(c)
    {
      case char(75) : x = (x + 3) % 4; break;         //strzałka w lewo
      case char(77) : x = (x + 1) % 4; break;         //strzałka w prawo
      case char(72) : tz[x] = (tz[x] + 1) % 6; break; //strzałka w górę
      case char(80) : tz[x] = (tz[x] + 5) % 6; break; //strzałka w dół
    };
  } while(int(c) != 13); // klawisz Enter
}

// Obiekt TMasterMind
//*************************************************************

// Metoda ocenia kod wprowadzony przez gracza. Wydruk
// jest przemieszczany do następnego segmentu gry.
//------------------------------------------------------
void TMasterMind::Ocen_t()
{
  gotoxy(43, wherey() + 1); // ustawiamy pozycję oceny
  z.Oceniaj(t.tz);          // oceniamy kod gracza
  cout << endl << endl;     // przechodzimy do następnego segmentu
}

// Metoda porównuje obiekty z i t. Zwraca true, jeśli
// zawierają ten sam kod.
//------------------------------------------------------
int TMasterMind::t_rowne_z()
{
  int test,i;

  test = true;
  for(i = 0; i <= 3; i++) test = test && (z.tz[i] == t.tz[i]);
  return(test);
}

// Metoda testuje warunek zakończenia gry. Jeśli gra się
// kończy, wypisuje odpowiedni komunikat i zwraca true
//------------------------------------------------------
int TMasterMind::KoniecGry()
{
  runda++;      // zwiększamy numer rundy
  if(t_rowne_z())
  {
    textattr(0x0e);
    Centruj(PL("GRATULACJE - odgadłeś kod komputera!"));
    gotoxy(35,3); z.Wyswietl();  // wyświetlamy kod komputera
    return(true);
  }
  else if(runda > 6)
  {
    textattr(0x0c);
    Centruj(PL("GRA SKOŃCZONA - nie odgadłeś kodu komputera!"));
    gotoxy(35,3); z.Wyswietl();
    return(true);
  };
  return(false);
}

// Metoda wyświetla stronę tytułową i czeka na
// dowolny klawisz, po czym czyści ekran.
//------------------------------------------------------
void TMasterMind::StronaTytulowa()
{
  textbackground(0); clrscr();
  gotoxy(1,3); textattr(0x3b);
  Centruj(PL("                                  "));
  Centruj(PL("  GRA INTELEKTU ----------------  "));
  Centruj(PL("  -------------------MASTER MIND  "));
  Centruj(PL("                                  "));
  textattr(0x1f);
  Centruj(PL("                                  "));
  Centruj(PL("    (C)2004 mgr Jerzy Wałaszek    "));
  Centruj(PL("                                  "));
  textattr(0x2e);
  Centruj(PL("                                  "));
  Centruj(PL("     I Liceum Ogólnokształcące    "));
  Centruj(PL("   im. Kazimierza  Brodzińskiego  "));
  Centruj(PL("             w Tarnowie           "));
  Centruj(PL("                                  "));
  textattr(0xf0);
  Centruj(PL("                                  "));
  Centruj(PL("   Odgadnij w sześciu kolejkach   "));
  Centruj(PL("   kod koloru  wylosowany przez   "));
  Centruj(PL("    komputer z 6 różnych barw.    "));
  Centruj(PL("                                  "));
  textattr(0xf4);
  Centruj(PL("        Gdy będziesz gotowy,      "));
  Centruj(PL("     naciśnij dowolny klawisz     "));
  Centruj(PL("                                  "));
  textattr(0x0e); Ramka(23,2,58,23);
  while(getch() == '\0') ; // Oczekiwanie na dowolny klawisz
  textattr(0x07); clrscr();
}

// Metoda odpowiedzialna za prowadzenie gry.
//------------------------------------------------------
void TMasterMind::Graj()
{
  z.Inicjuj(); runda = 1;
  textattr(0x4e);
  Centruj("    MASTER  MIND    ");
  textattr(0x87);
  Centruj("                    ");
  Centruj("    ? ? ? ?         ");
  Centruj("                    ");
  do
  {
    t.Inicjuj(runda);
    Ocen_t();
  } while(!KoniecGry());
}

// Metoda upewnia się, że gracz ma ochotę na jeszcze
// jedną grę. Zwraca w atkim wypadku true.
//------------------------------------------------------
int TMasterMind::JeszczeRaz()
{
  gotoxy(1,24); textcolor(WHITE);
  Centruj("Zagrasz jeszcze raz ? [T] = Tak, [inny] = Nie");
  return(toupper(getch()) == 'T');
}

// Blok główny programu
//--------------------------------------------------

int main()
{
  TMasterMind gra;

  srand((unsigned)time(NULL));
  CursorOff();
  do
  {
     gra.StronaTytulowa();
     gra.Graj();
  } while(gra.JeszczeRaz());
  textattr(0x07); CursorOn(); clrscr(); return(0);
}

 

Dla ambitnych

  1. Ile jest wszystkich możliwych kombinacji czteroelementowych kodów zbudowanych z sześciu kolorów?
  2. Czy potrafisz określić strategię wygrywającą dla Mini Master Minda.
  3. Zaprojektuj algorytm, który w co najwyżej 6 ruchach odgaduje kod na podstawie informacji z pionów czarnych i białych. Napisz odpowiedni program.

 


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

©2021 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