program L1;
   uses crt, graph,dos;
   const n=10;
   type field= array[1..n] of array [1..n] of boolean;
   matrix= object
           CellWidth:integer;
           x,y,QuitX,QuitY:integer;
           game_flag:byte;
           xInit,yInit:integer;
           NumofMines:integer;
           colour,pattern,CellColour:word;
           mines,marked: field;
           constructor Init;
           procedure DrawCounter(counter:string);
           procedure DrawQuitButton;
           procedure DrawMatrix;
           procedure FillMines;
           function MarkMines: boolean;
           procedure GameOver;
           procedure OpenCells(i,j:integer);
           procedure DrawOpenedCells(i,j:integer);
           function IsMine(a,b:integer):boolean;
           function DetectMines(a,b:integer):integer;
           end;
procedure show_mouse;
var reg:registers;
begin
     reg.ax:=$01;
     intr($33,reg);
end;

Procedure hide_mouse;
Inline( $B8/$02/$00/
        $CD/$33);

procedure get_mouse_coordinates(var b:byte;var x,y:word);
var reg:registers;
begin
     reg.ax:=$03;
     intr($33,reg);
     with reg do begin
     b:=bl;
     x:=cx;
     y:=dx;
     end;
end;


procedure mouse_goto(x,y:word);
var reg:registers;
begin
     with reg do begin
     ax:=$04;
     cx:=x;
     dx:=y;
     end;
     intr($33,reg);
end;
   constructor matrix.Init;
   var i,j:byte;
   begin
        CellWidth:=25;
        CellColour:=11;
        x:=GetMaxX div 3;
        y:=GetMaxY div 3;
        NumofMines:=15;
        game_flag:=0;
        xInit:=x; yInit:=y;
        QuitX:=xInit;
        QuitY:=yInit-CellWidth;
        colour:=0;
        pattern:=1;
        for i:=1 to n do
            for j:=1 to n do
            marked[i][j]:=FALSE;
   end;

   procedure matrix.DrawCounter(counter:string);
   var xF,yF:integer;
   begin
       xF:=xInit-2;
       yF:=GetMaxY div 10;
       SetColor(4);
       SetFillStyle(8,12);
       Bar3D(xF,yF,xF+CellWidth*n+7,yF+50,0,FALSE);
       SetFillStyle(1,10);
       Bar3D(xF+CellWidth*n div 3+10, yF+10, xF+CellWidth*n div 3+40,yF+40,0,FALSE);
       SetTextStyle(4,0,3);
       OutTextXY(xF+CellWidth*n div 3+12, yF+10,counter);
   end;

   procedure matrix.DrawQuitButton;
   begin
        SetColor(8);
        SetFillStyle(1,7);
        SetColor(0);
        Bar3D(QuitX,QuitY,QuitX+CellWidth*n,QuitY+20,0,FALSE);
        OutTextXY(QuitX+CellWidth*3,QuitY+2,'Quit');
   end;

   procedure matrix.DrawMatrix;
   var i,j: integer;
   begin
    mouse_goto(colour,pattern);
    show_mouse;
        SetColor(colour);
        SetFillStyle(pattern,CellColour);
        for i:=1 to 10 do
        begin
            for j:=1 to 10 do
            begin
                 Bar3D(x,y,x+CellWidth,y+CellWidth,0,FALSE);
                 x:=x+CellWidth;
            end;
            x:=x-CellWidth*10;
            y:=y+CellWidth;
        end;
   end;

   procedure matrix.FillMines;
   var i,j,k:integer;
   begin
    for i:=1 to n do
           for j:=1 to n do
               mines[i][j]:=FALSE;
        Randomize;
        k:=0;
        repeat
             i:=Random(n-1)+1; j:=Random(n-1)+1;
             if mines[i][j]<> TRUE then begin
                                   mines[i][j]:=TRUE;
                                   inc(k);
                                   end;
        until k=NumofMines;
   end;

   function matrix.IsMine(a,b:integer):boolean;
   var i,j:integer;
   begin
        i:=(a-xInit)div CellWidth+1;
        j:=(b-yInit)div CellWidth+1;
        if mines[i][j]=TRUE then IsMine:=TRUE;
   end;

   function matrix.DetectMines(a,b:integer):integer;
   var i,j,m:integer;
   begin
        m:=0;
        i:=(a-xInit)div CellWidth+1;
        j:=(b-yInit)div CellWidth+1;
        if i+1<=n then
        begin
           if mines[i+1][j]=TRUE then inc(m);
           if (j-1>0)and(mines[i+1][j-1]=TRUE) then inc(m);
           if (j+1<=n)and(mines[i+1][j+1]=TRUE) then inc(m);
        end;
        if i-1>0 then
        begin
           if mines[i-1][j]=TRUE then inc(m);
           if(j+1<=n)and(mines[i-1][j+1]=TRUE) then inc(m);
           if (j-1>0) and(mines[i-1][j-1]=TRUE) then inc(m);
        end;
        if j+1<=n then
           if mines[i][j+1]=TRUE then inc(m);
        if j-1>0 then
           if mines[i][j-1]=TRUE then inc(m);
        DetectMines:=m;
   end;

   procedure matrix.DrawOpenedCells(i,j: integer);
   var NM:string; NumofNearMines,a,b: integer;
   begin
        a:=xInit+CellWidth*(i-1);
        b:=yInit+CellWidth*(j-1);
        SetFillStyle(1,14);
        Bar3D(a,b,a+CellWidth,b+CellWidth,0,FALSE);
        NumofNearMines:=DetectMines(a,b);
        if NumofNearMines>0 then
        begin
            Str(NumofNearMines,NM);
            OutTextXY(a+CellWidth div 3,b+CellWidth div 3,NM);
        end;
        if mines[i][j]=TRUE then
        begin
            SetFillStyle(1,0);
            FillEllipse(a+CellWidth div 2,b+CellWidth div 2,3,3);
        end;
   end;

   procedure matrix.OpenCells(i,j:integer);
   var a,b,t:integer;
   begin
        a:=xInit+CellWidth*(i-1);
        b:=yInit+CellWidth*(j-1);
        t := 0;
        if (i < 1) or (j < 1) then t := 1;
        if (i = n+1) or (j = n+1) then t := 1;
        if t = 0 then
        begin
             if (marked[i][j] = FALSE) then
             begin
                  if mines[i][j]=TRUE then exit;
                  marked[i][j] := TRUE;
                  DrawOpenedCells(i,j);
                  if mines[i][j] = FALSE  then
                  begin
                       OpenCells(i+1,j);
                       OpenCells(i-1,j);
                       OpenCells(i,j-1);
                       OpenCells(i,j+1);
                       OpenCells(i-1,j-1);
                       OpenCells(i+1,j-1);
                       OpenCells(i-1,j+1);
                       OpenCells(i+1,j+1);
                  end;
             end;
        end;
   end;

   function matrix.MarkMines:boolean;
   var mouseX,mouseY,TextX,TextY,H,M,S,S100:word;
   i,j,x1,y1:integer; counter:string;
   OpenOK,PressButton: boolean; Button:byte;
   SFirst:longint;
   begin
       OpenOK:=FALSE; PressButton:=FALSE;
       Str(NumofMines,counter);
       DrawCounter(counter);
       Init;
       while TRUE do
       begin
            if game_flag=1 then
            begin
                 MarkMines:=FALSE;
                 Exit;
            end;
            get_mouse_coordinates(Button,MouseX,MouseY);
            if(Button>0)and(MouseX in [QuitX..QuitX+Cellwidth*n])and(MouseY in [QuitY..QuitY-CellWidth]) then Exit;
            if (MouseX > xInit) and(MouseY >yInit) then
            begin
            i:= (MouseX-xInit)div CellWidth+1;
            j:=(MouseY-yInit)div CellWidth+1;
            case  Button of
            2: begin
               if marked[i][j]<>TRUE then
               begin
                    marked[i][j]:=TRUE;
                    dec(NumofMines);
                    Str(NumofMines,counter);
                    DrawCounter(counter);
                    TextX:=xInit+(CellWidth)*(i-1)+CellWidth div 3;
                    TextY:=yInit+(CellWidth)*(j-2)+CellWidth div 2;
                    OutTextXY(TextX,TextY,'*');
               end;
               end;


             1: begin
                     if mines[i][j]=TRUE then begin
                                             DrawOpenedCells(i,j);
                                             MarkMines :=FALSE;
                                             exit;
                                             end;
                          SetTextStyle(0,0,1);
                          x:=xInit+CellWidth*(i-1);
                          y:=yInit+CellWidth*(j-1);
                          mouse_goto(x-CellWidth,y-CellWidth);
                          OpenCells(i,j);
                 end;
            end;
            end;
       end;
   end;

   procedure matrix.GameOver;
   begin
        SetColor(4);
        TextColor(128);
        SetTextStyle(7,0,5);
        OutTextXY(xInit,10,'GAME OVER');
   end;



   var mines,marked: ^field;
   i,j,Err:integer; matrix1:^matrix;
   begin
        i:=detect;
        InitGraph(i,j,'');
        Err:=GraphResult;
        if Err<>grOK then
           WriteLn(GraphErrorMsg(Err))
        else
        begin
             New(Matrix1,Init);
             Matrix1^.DrawMatrix;
             Matrix1^.DrawQuitButton;
             Matrix1^.FillMines;
             if Matrix1^.MarkMines=FALSE then Matrix1^.GameOver;
             ReadLn;
             Dispose(Matrix1);
             CloseGraph;
        end;
   end.

   end.