Pole minowe - 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
Strona tytułowa gry
obrazek
Przykładowa rozgrywka
obrazek
Przykładowa rozgrywka

Program w języku Pascal

//          P O L E   M I N O W E
//           WERSJA PROCEDURALNA
//--------------------------------------------
// (C)2004 mgr Jerzy Wałaszek  I LO w Tarnowie

program PoleMinowe;

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
//------------------------------------------------------

const
  PM_MAX_Y = 19; // określa wysokość pola minowego
  PM_MAX_X = 77; // określa szerokość pola minowego

var
  pm : array[0..PM_MAX_Y,0..PM_MAX_X] of char;

// Procedura wyświetla stronę tytułową, czeka na dowolny
// klawisz i czyści ekran
//------------------------------------------------------
procedure StronaTytulowa;
begin
  TextAttr := $07; ClrScr;
  GotoXY(1,4);
  TextAttr := $4e;
  Centruj(PL('                                  '));
  Centruj(PL('  GRA DLA SAPERÓW---------------  '));
  Centruj(PL('  -------------------POLE MINOWE  '));
  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('   Czy pokonasz pole pełne min?   '));
  Centruj(PL('                                  '));
  TextAttr := $f4;
  Centruj(PL('        Gdy będziesz gotowy,      '));
  Centruj(PL('     naciśnij dowolny klawisz     '));
  Centruj(PL('                                  '));
  TextAttr := $0e; Ramka(23,3,58,22);
  while ReadKey = #0 do; // Oczekiwanie na dowolny klawisz
  TextAttr := $07; ClrScr;
end;

// Procedura inicjuje tablice tm[]
//------------------------------------------------------
procedure UstawPoleMinowe;
var
  i,j,x,y : integer;
begin
  for i := 0 to PM_MAX_Y do
    for j := 0 to PM_MAX_X do
      pm[i,j] := ' ';
  for i := 1 to 100 do
  begin
    x := random(PM_MAX_X + 1);
    y := random(PM_MAX_Y + 1);
    pm[y,x] := '*';
  end;
  pm[PM_MAX_Y,0] := '-';
  pm[0,PM_MAX_X] := '+';
end;

// Procedura wyświetla planszę gry z polem minowym.
// Widocznością min steruje parametr miny
//------------------------------------------------------
procedure Plansza(miny : boolean);
var
  i,j : integer;
begin
  for i := 0 to PM_MAX_Y do
  begin
    GotoXY(2,i+2);
    for j := 0 to PM_MAX_X do
      case pm[i,j] of
      '*' : begin // mina
              TextAttr := $20;
              if miny then write('*') else write(' ');
            end;
      ' ' : begin // puste
              TextAttr := $20; write(' ');
            end;
      '.' : begin // ślad przejścia
              TextAttr := $a0; write(' ');
            end;
      '-' : begin // punkt startu
              TextAttr := $70; write(' ');
            end;
      '+' : begin // punkt docelowy
              TextAttr := $e0; write(' ');
            end;
      end;
  end;
end;

// Funkcja zwraca true, jeśli gracz nie ma ochoty na
// kolejną rozgrywkę.
//------------------------------------------------------
function KoniecGry : boolean;
begin
  GotoXY(1,23); TextAttr := $0f;
  Centruj('Jeszcze raz ? [T] = Tak, [Inny] = Nie');
  Result := UpCase(ReadKey) <> 'T';
end;

// Funkcja steruje ruchami gracza. Obsługuje naciśnięcia
// klawiszy kursora i przemieszcza pozycję gracza na nowe
// pole. Sprawdza rodzaj pola na którym znalazł się po
// ruchu gracz. Jeśli jest to mina lub pole docelowe,
// kończy grę z odpowiednim komunikatem. Pole gry jest
// wtedy ponownie wyświetlane, ale z widocznymi minami.
//------------------------------------------------------
function KoncowyRuch(var x,y : integer) : boolean;
var
  c : char;
begin
  Result := false;
  GotoXY(x+2,y+2); TextAttr := $8f; write(#207);
  repeat
    c := ReadKey;
  until c <> #0;
  GotoXY(x+2,y+2); TextAttr := $8f; write(' ');
  case c of
    #75 : if x > 0 then dec(x);        //strzałka w lewo
    #77 : if x < PM_MAX_X then inc(x); //strzałka w prawo
    #72 : if y > 0 then dec(y);        //strzałka w górę
    #80 : if y < PM_MAX_Y then inc(y); //strzałka w dół
  end;
  GotoXY(1,22);
  case pm[y,x] of
    '*' : begin
            TextAttr := $0c;
            Centruj(PL('P O L E G Ł E Ś  N A  P O L U  M I N O W Y M'));
            Plansza(true);
            GotoXY(x+2,y+2); TextAttr := $4e; write('+');
            Result := true;
          end;
    '+' : begin
            TextAttr := $0e;
            Centruj(PL('GRATULACJE - POKONAŁEŚ POLE MINOWE'));
            Plansza(true);
            GotoXY(x+2,y+2); TextAttr := $e1; write(#207);
            Result := true;
          end;
    '-' : ;
    else
      pm[y,x] := '.'; // Pozostawiamy ślad przejścia
  end;
end;

// Procedura sprawdza, czy wokół pozycji gracza są miny.
// Wyświetla odpowiedni komunikat.
//------------------------------------------------------
procedure SprawdzMiny(x,y : integer);
var
  i,j  : integer;
  mina : boolean;
begin
  GotoXY(1,23);
  mina := false;
  for i := y - 1 to y + 1 do
    for j := x - 1 to x + 1 do
    if (i >= 0) and (i <= PM_MAX_Y) and
       (j >= 0) and (j <= PM_MAX_X) and
       (pm[i,j] = '*') then mina := true;
  if mina then
  begin
    TextAttr := $ce; Centruj('  UWAGA - MINY!  ');
  end
  else
  begin
    TextAttr := $1f; Centruj('  NIE  MA  MIN   ');
  end;
end;

// Główny blok programu.
//------------------------------------------------------
var
  a,px,py : integer;
begin
  Randomize;
  a := TextAttr; CursorOff;
  repeat
    StronaTytulowa;
    UstawPoleMinowe;
    Plansza(false);
    px := 0; py := PM_MAX_Y;
    repeat
      SprawdzMiny(px,py);
    until KoncowyRuch(px,py);
  until KoniecGry;
  TextAttr := a; CursorOn; ClrScr;
end.

 

Program obiektowy w języku Pascal

//          P O L E   M I N O W E
//            WERSJA  OBIEKTOWA
//--------------------------------------------
// (C)2004 mgr Jerzy Wałaszek  I LO w Tarnowie

program PoleMinowe;

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
//------------------------------------------------------

const
  PM_MAX_Y = 19; // określa wysokość pola minowego
  PM_MAX_X = 77; // określa szerokość pola minowego

type

  TPoleMinowe = class
                  private
                    pm    : array[0..PM_MAX_Y,0..PM_MAX_X] of char;
                    px,py : integer;
                    procedure   InicjujGre;
                    procedure   Plansza(miny : boolean);
                    procedure   SprawdzMiny;
                    procedure   StronaTytulowa;
                    procedure   UstawPoleMinowe;
                    function    KoncowyRuch : boolean;
                    function    KoniecGry   : boolean;
                  public
                    constructor Create;
                    procedure   Graj;
                end;

// Definicje metod obiektowych
//------------------------------------------------------

constructor TPoleMinowe.Create;
begin
  // tylko standardowe działanie
end;

// Metoda obsługuje całą rozgrywkę
//------------------------------------------------------
procedure TPoleMinowe.Graj;
var
  a : integer;
begin
  Randomize;
  a := TextAttr; CursorOff;
  repeat
    StronaTytulowa;
    InicjujGre;
    repeat
      SprawdzMiny;
    until KoncowyRuch;
  until KoniecGry;
  TextAttr := a; CursorOn; ClrScr;
end;

// Procedura inicjuje grę ustawiając pole minowe,
// współrzędne gracza oraz wyświetlając planszę gry.
//------------------------------------------------------
procedure TPoleMinowe.InicjujGre;
begin
  UstawPoleMinowe;
  px := 0; py := PM_MAX_Y;
  Plansza(false);
end;

// Procedura wyświetla planszę gry
//------------------------------------------------------
procedure TPoleMinowe.Plansza(miny : boolean);
var
  i,j : integer;
begin
  for i := 0 to PM_MAX_Y do
  begin
    GotoXY(2,i+2);
    for j := 0 to PM_MAX_X do
      case pm[i,j] of
      '*' : begin // mina
              TextAttr := $20;
              if miny then write('*') else write(' ');
            end;
      ' ' : begin // puste
              TextAttr := $20; write(' ');
            end;
      '.' : begin // ślad przejścia
              TextAttr := $a0; write(' ');
            end;
      '-' : begin // punkt startu
              TextAttr := $70; write(' ');
            end;
      '+' : begin // punkt docelowy
              TextAttr := $e0; write(' ');
            end;
      end;
  end;
end;

// Procedura sprawdza, czy wokół pola gracza znajdują
// się jakieś miny. O obu wypadkach wyświetlany jest
// odpowiedni komunikat
//------------------------------------------------------
procedure TPoleMinowe.SprawdzMiny;
var
  i,j  : integer;
  mina : boolean;
begin
  GotoXY(1,23);
  mina := false;
  for i := py - 1 to py + 1 do
    for j := px - 1 to px + 1 do
    if (i >= 0) and (i <= PM_MAX_Y) and
       (j >= 0) and (j <= PM_MAX_X) and
       (pm[i,j] = '*') then mina := true;
  if mina then
  begin
    TextAttr := $ce; Centruj('  UWAGA - MINY!  ');
  end
  else
  begin
    TextAttr := $1f; Centruj('  NIE  MA  MIN   ');
  end;
end;

// Procedura wyświetla stronę tytułową, czeka na dowolny
// klawisz i czyści ekran
//------------------------------------------------------
procedure TPoleMinowe.StronaTytulowa;
begin
  TextAttr := $07; ClrScr;
  GotoXY(1,4);
  TextAttr := $4e;
  Centruj(PL('                                  '));
  Centruj(PL('  GRA DLA SAPERÓW---------------  '));
  Centruj(PL('  -------------------POLE MINOWE  '));
  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('   Czy pokonasz pole pełne min?   '));
  Centruj(PL('                                  '));
  TextAttr := $f4;
  Centruj(PL('        Gdy będziesz gotowy,      '));
  Centruj(PL('     naciśnij dowolny klawisz     '));
  Centruj(PL('                                  '));
  TextAttr := $0e; Ramka(23,3,58,22);
  while ReadKey = #0 do; // Oczekiwanie na dowolny klawisz
  TextAttr := $07; ClrScr;
end;

// Procedura inicjuje pole gry.
//------------------------------------------------------
procedure TPoleMinowe.UstawPoleMinowe;
var
  i,j,x,y : integer;
begin
  for i := 0 to PM_MAX_Y do
    for j := 0 to PM_MAX_X do
      pm[i,j] := ' ';
  for i := 1 to 100 do
  begin
    x := random(PM_MAX_X + 1);
    y := random(PM_MAX_Y + 1);
    pm[y,x] := '*';
  end;
  pm[PM_MAX_Y,0] := '-';
  pm[0,PM_MAX_X] := '+';
end;

// Funkcja steruje ruchami gracza. Obsługuje naciśnięcia
// klawiszy kursora i przemieszcza pozycję gracza na nowe
// pole. Sprawdza rodzaj pola na którym znalazł się po
// ruchu gracz. Jeśli jest to mina lub pole docelowe,
// kończy grę z odpowiednim komunikatem. Pole gry jest
// wtedy ponownie wyświetlane, ale z widocznymi minami.
//------------------------------------------------------
function TPoleMinowe.KoncowyRuch : boolean;
var
  c : char;
begin
  Result := false;
  GotoXY(px+2,py+2); TextAttr := $8f; write(#207);
  repeat
    c := ReadKey;
  until c <> #0;
  GotoXY(px+2,py+2); TextAttr := $8f; write(' ');
  case c of
    #75 : if px > 0 then dec(px);        //strzałka w lewo
    #77 : if px < PM_MAX_X then inc(px); //strzałka w prawo
    #72 : if py > 0 then dec(py);        //strzałka w górę
    #80 : if py < PM_MAX_Y then inc(py); //strzałka w dół
  end;
  GotoXY(1,22);
  case pm[py,px] of
    '*' : begin
            TextAttr := $0c;
            Centruj(PL('P O L E G Ł E Ś  N A  P O L U  M I N O W Y M'));
            Plansza(true);
            GotoXY(px+2,py+2); TextAttr := $4e; write('+');
            Result := true;
          end;
    '+' : begin
            TextAttr := $0e;
            Centruj(PL('GRATULACJE - POKONAŁEŚ POLE MINOWE'));
            Plansza(true);
            GotoXY(px+2,py+2); TextAttr := $e1; write(#207);
            Result := true;
          end;
    '-' : ;
    else
      pm[py,px] := '.'; // Pozostawiamy ślad przejścia
  end;
end;

// Funkcja zwraca true, jeśli gracz nie ma ochoty na
// kolejną rozgrywkę.
//------------------------------------------------------
function TPoleMinowe.KoniecGry   : boolean;
begin
  GotoXY(1,23); TextAttr := $0f;
  Centruj('Jeszcze raz ? [T] = Tak, [Inny] = Nie');
  Result := UpCase(ReadKey) <> 'T';
end;

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

var
  gra : TPoleMinowe;

begin
  gra := TPoleMinowe.Create;
  gra.Graj;
end.

Program w języku C++

Program uruchomiono w środowisku Dev-C++.

//          P O L E   M I N O W E
//--------------------------------------------
// (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
//----------------------------------------------------

const int PM_MAX_X = 77;
const int PM_MAX_Y = 19;

class TPoleMinowe
{
    char pm[PM_MAX_Y+1][PM_MAX_X+1];
    int  px,py;
    void InicjujGre();
    void Plansza(int miny);
    void SprawdzMiny();
    void StronaTytulowa();
    void UstawPoleMinowe();
    int  KoncowyRuch();
    int  KoniecGry();
  public:
    void Graj();
};

//----------------------------------------------------
// 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
//----------------------------------------------------

// Metoda obsługuje całą rozgrywkę
//------------------------------------------------------
void TPoleMinowe::Graj()
{
  srand((unsigned)time(NULL));
  CursorOff();
  do
  {
    StronaTytulowa();
    InicjujGre();
    do
    {
      SprawdzMiny();
    } while(!KoncowyRuch());
  } while(!KoniecGry());
  textattr(7); CursorOn(); clrscr();
}

// Procedura inicjuje grę ustawiając pole minowe,
// współrzędne gracza oraz wyświetlając planszę gry.
//------------------------------------------------------
void TPoleMinowe::InicjujGre()
{
  UstawPoleMinowe();
  px = 0; py = PM_MAX_Y;
  Plansza(false);
}

// Procedura wyświetla planszę gry
//------------------------------------------------------
void TPoleMinowe::Plansza(int miny)
{
  int i,j;

  for(i = 0; i <= PM_MAX_Y; i++)
  {
    gotoxy(2,i+2);
    for(j = 0; j <= PM_MAX_X; j++)
    {
      switch(pm[i][j])
      {
        case '*' :  // mina
          textattr(0x20);
          if(miny) cout << "*"; else cout << " ";
          break;
        case ' ' :  // puste
          textattr(0x20); cout << " "; break;
        case '.' :  // ślad przejścia
          textattr(0xa0); cout << " "; break;
        case '-' :  // punkt startu
          textattr(0x70); cout << " "; break;
        case '+' :  // punkt docelowy
          textattr(0xe0); cout << " "; break;
      };
      cout.flush();
    };
  };
}

// Procedura sprawdza, czy wokół pola gracza znajdują
// się jakieś miny. O obu wypadkach wyświetlany jest
// odpowiedni komunikat
//------------------------------------------------------
void TPoleMinowe::SprawdzMiny()
{
  int i,j,mina;

  gotoxy(1,23);
  mina = false;
  for(i = py - 1; i <= py + 1; i++)
    for(j = px - 1; j <= px + 1; j++)
      if((i >= 0) && (i <= PM_MAX_Y) &&
         (j >= 0) && (j <= PM_MAX_X) && (pm[i][j] == '*')) mina = true;
  if(mina)
  {
    textattr(0xce); Centruj("  UWAGA - MINY!  ");
  }
  else
  {
    textattr(0x1f); Centruj("  NIE  MA  MIN   ");
  };
}

// Procedura wyświetla stronę tytułową, czeka na dowolny
// klawisz i czyści ekran
//------------------------------------------------------
void TPoleMinowe::StronaTytulowa()
{
  textbackground(0); clrscr();
  gotoxy(1,4); textattr(0x4e);
  Centruj(PL("                                  "));
  Centruj(PL("  GRA DLA SAPERÓW---------------  "));
  Centruj(PL("  -------------------POLE MINOWE  "));
  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("   Czy pokonasz pole pełne min?   "));
  Centruj(PL("                                  "));
  textattr(0xf4);
  Centruj(PL("        Gdy będziesz gotowy,      "));
  Centruj(PL("     naciśnij dowolny klawisz     "));
  Centruj(PL("                                  "));
  textattr(0x0e); Ramka(23,3,58,22);
  while(getch() == '\0') ; // Oczekiwanie na dowolny klawisz
  textattr(0x07); clrscr();
}

// Procedura inicjuje pole gry.
//------------------------------------------------------
void TPoleMinowe::UstawPoleMinowe()
{
  int i,j,x,y;

  for(i = 0; i <= PM_MAX_Y; i++)
    for(j = 0; j <= PM_MAX_X; j++) pm[i][j] = ' ';
  for(i = 1; i <= 100; i++)
  {
    x = rand() % (PM_MAX_X + 1);
    y = rand() % (PM_MAX_Y + 1);
    pm[y][x] = '*';
  };
  pm[PM_MAX_Y][0] = '-';
  pm[0][PM_MAX_X] = '+';
}

// Funkcja steruje ruchami gracza. Obsługuje naciśnięcia
// klawiszy kursora i przemieszcza pozycję gracza na nowe
// pole. Sprawdza rodzaj pola na którym znalazł się po
// ruchu gracz. Jeśli jest to mina lub pole docelowe,
// kończy grę z odpowiednim komunikatem. Pole gry jest
// wtedy ponownie wyświetlane, ale z widocznymi minami.
//------------------------------------------------------
int TPoleMinowe::KoncowyRuch()
{
  char c;

  gotoxy(px+2,py+2); textattr(0x8f); cout << char(207);
  while((c = getch()) == '\0') ;
  gotoxy(px+2,py+2); textattr(0x8f); cout << ' ';
  switch(c)
  {
    case char(75) : if(px > 0) px--; break;        //strzałka w lewo
    case char(77) : if(px < PM_MAX_X) px++; break; //strzałka w prawo
    case char(72) : if(py > 0) py--; break;        //strzałka w górę
    case char(80) : if(py < PM_MAX_Y) py++; break; //strzałka w dół
  };
  gotoxy(1,22);
  switch(pm[py][px])
  {
    case '*' : textattr(0x0c);
               Centruj(PL("P O L E G Ł E Ś  N A  P O L U  M I N O W Y M"));
               Plansza(true);
               gotoxy(px+2,py+2); textattr(0x4e); cout << "+";
               return(true);
    case '+' : textattr(0x0e);
               Centruj(PL("GRATULACJE - POKONAŁEŚ POLE MINOWE"));
               Plansza(true);
               gotoxy(px+2,py+2); textattr(0xe1); cout << char(207);
               return(true);
    case '-' : break;
    default  : pm[py][px] = '.'; // Pozostawiamy ślad przejścia
               break;
  };
  return(false);
}

// Funkcja zwraca true, jeśli gracz nie ma ochoty na
// kolejną rozgrywkę.
//------------------------------------------------------
int TPoleMinowe::KoniecGry()
{
  gotoxy(1,23); textattr(0x0f);
  Centruj("Jeszcze raz ? [T] = Tak, [Inny] = Nie");
  return(toupper(getch()) != 'T');
}

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

int main()
{
  TPoleMinowe gra;

  gra.Graj();
}

 

Dla ambitnych

  1. Dodaj do naszego programu dodatkowe utrudnienie w postaci limitu czasu. Jeśli czas upłynie, to gracz przegrywa rozgrywkę.
  2. Zmodyfikuj nasz program tak, aby był wyposażony w listę graczy, którzy przebyli pole minowe w najmniejszej liczbie ruchów.
  3. Opracuj algorytm przejścia dowolnego pola minowego od zadanego punktu początkowego do wyznaczonego punktu docelowego na podstawie sygnałów z wykrywacza min.

 


   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