unit U_Concentration;
 {Copyright  © 2004, Gary Darby,  www.DelphiForFun.org
 This program may be used or modified for any non-commercial purpose
 so long as this original notice remains in place.
 All other rights are reserved
 }

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, U_CardComponent, ExtCtrls, Spin, shellAPI;

type

  TForm1 = class(TForm)
    Label1: TLabel;
    NewGameBtn: TButton;
    PlayerGrp: TRadioGroup;
    PairsEdt: TSpinEdit;
    Label2: TLabel;
    StaticText1: TStaticText;
    TurnLbl: TLabel;
    Label4: TLabel;
    Score1Lbl: TLabel;
    Score2Lbl: TLabel;
    procedure NewGameBtnClick(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure StaticText1Click(Sender: TObject);
  public
    nbrcards:integer;
    nbrplayers:integer;
    guesses, matches: array[1..2] of integer;
    cardup:TCard;   {pointer to the card already turned face up (if any)}
    playernbr:integer;
    procedure CardMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  end;

var Form1: TForm1;

implementation

{$R *.DFM}

{************** FormActivate **********}
procedure TForm1.FormActivate(Sender: TObject);
begin
  newgamebtnclick(sender);  {Set up initial game}
end;

{***************** NewGameBtnClick ***********}
procedure TForm1.NewGameBtnClick(Sender: TObject);
var i, col, row, offsetx, offsety:integer;
    tempdeck:TDeck;
begin
  {initialize game paramters and labels}
  nbrcards:=2*pairsedt.value;  {must be multiple of 2}
  nbrplayers:=playergrp.itemindex+1;
  playernbr:=1;
  score2lbl.visible:=nbrplayers=2;
  score1lbl.caption:='0';
  score2lbl.caption:='0';
  for i:=1 to 2 do
  begin
    guesses[i]:=0;
    matches[i]:=0;
  end;
  CardUp:=nil;
  offsetx:=10; offsety:=10;

  {create and shuffle a deck}

  if assigned(deck) then deck.free;
  deck:=TDeck.create(Application.mainform,point(10,10),nbrcards);

  {create a temporary full deck to pick from}
  tempdeck:=TDeck.create(Application.mainform,point(10,10),52);
  tempdeck.shuffle;

  {duplicate 1st half of cards in 2nd half positions to ensure pairs}
  with deck do
  begin
    for i:=0 to nbrcards div 2-1 do
    begin
      with deckobj[i] do
      begin
        onmouseup:=CardMouseup;   {set mouseup exit for each card}
        value:=tempdeck.deckobj[i].value;
        suit:=tempdeck.deckobj[i].suit;
      end;
      {Duplicate the card in the 2nd half of the deck}
      deckobj[i+nbrcards div 2].value:=deckobj[i].value;
      deckobj[i+nbrcards div 2].suit:=deckobj[i].suit;
      deckobj[i+nbrcards div 2].onmouseup:=CardMouseup;
    end;
    tempdeck.free;
    shuffle;
    for i:=0 to nbrcards-1 do
    begin
      row:=i div 10;  {draw 10 cards per row}
      col:= i mod 10;
      with deckobj[i] do  {position the card}
      begin
        top:=offsety+row*(height+5);
        left:=offsetx+col*(width+5);
      end;
    end;
  end;
end;

{*************** CardMouseUp **************}
procedure TForm1.CardMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
{called when player clicks a card}
var
  winner:string;
  {"match" = boolean flag set when a pair is found, used to kee same player for next turn}
  match:boolean;
  msg:string;
begin
  If (sender is TCard)
  then with tcard(Sender) do
  if showdeck then   {it's face down, so click is valid}
  begin
    if button=mbleft then showdeck:=not showdeck; {show the card}
    if cardup<> nil  then  {we have two cards face up}
    begin
      inc(guesses[playernbr]);
      if (value=cardup.Value) and (suit=cardup.suit) then
      begin  {match!}
        match:=true;
        inc(matches[playernbr]);
        if matches[1]+matches[2]=nbrcards div 2 then {game over}
        begin
           {update displayed score first}
           if playernbr=1 then score1lbl.caption:=inttostr(matches[1])+' of ' + inttostr(guesses[1])
           else  score2lbl.caption:=inttostr(matches[2])+' of ' + inttostr(guesses[2]);
           If nbrplayers = 1
           then showmessage('Game over'
                            +#13+'You found all pairs in '+inttostr(guesses[1])
                            +' Guesses!')
           else
           begin
             if matches[1]<matches[2] then winner:='Winner is Player 2'
             else if matches[2]<matches[1] then winner:='Winner is Player 1'
             else winner:='Tie score - no winner!';
             showmessage('Game over'+#13+winner);
           end;
           newgamebtnclick(sender);
        end;
        if cardup<>nil then
        begin
          sleep(nbrcards*100);
          cardup.visible:=false;
          TCard(sender).visible:=false;
        end;
      end
      else
      begin  {two face up - no match}
        match:=false;
        sleep(nbrcards*100);
        cardup.showdeck:=true;
        TCard(sender).showdeck:=true;
      end;
      cardup:=nil;  {set no cards face up}
      if playernbr=1 then score1lbl.caption:=inttostr(matches[1])+' of ' + inttostr(guesses[1])
      else  score2lbl.caption:=inttostr(matches[2])+' of ' + inttostr(guesses[2]);
      msg:='';
      if nbrplayers=2 then {if 2 players, adjust playernbr, unless a matrch was found}
      if not match then playernbr:=(playernbr) mod 2 +1
      else msg:=' plays again';
      turnlbl.caption:='Player '+inttostr(playernbr)+msg;
    end
    else cardup:=TCard(sender);
  end;
end;



procedure TForm1.StaticText1Click(Sender: TObject);
begin  {Browser link to DFF home page}
   ShellExecute(Handle, 'open', 'http://www.delphiforfun.org/',
  nil, nil, SW_SHOWNORMAL) ;
end;

end.