Пасьянс "Косынка" 
Колода из 36 карт раскладывается в 8 рядов. Количество карт 
в каждом ряду убывает с увеличением номера ряда. Получается "косынка".
Справа есть 4 места (банка), куда можно складывать карты однинаковой масти
в следующей последовательности: Туз, шетерка, семерка, ..., десятка, Валет, 
Дама, Король. Можно перемещать карты в колонках, кладя меньшую на большую 
для одинаковой масти. Последовательности подряд лежащих карт (одной масти) 
перемещаются вместе (например, можно перенести восьмерку-семерку-шестерку 
на девятку). В программе использованы объекты и ссылочные переменные.
Перенос из ряда в ряд осуществляется последовательным выбором двух чисел: 
"откуда" и "куда". "Куда" может принимать значение 0, что подразумевает "банк".
 
 
uses crt; 
const  
  cardVal :array[2..14] of  
    string[2] =('2','3','4','5','6','7','8','9','10','J','Q','K','A'); 
 
  cardSuit :array[1..4] of char = (#6,#5,#4,#3);  
  suitColor :array[1..4] of byte = (32,32,36,36);  
  topY = 2;  
  bgcolor = 2*16+14;                               
  gameTypeHidden = false;  
  gameTypeVisible = true;  
 
type 
  pCard = ^card;  
  card = object 
    val:byte;     
    suit:byte;    
    x,y:byte;     
    visible:boolean;   
    next:pCard;   
    procedure Init(_val,_suit,_x,_y:byte;_visible:boolean);  
    procedure Draw;  
  end; 
 
  cColumn = object  
    n:byte;         
    x:byte;         
    list:pCard;     
    procedure Draw;  
    procedure Init(_n,_x:byte;_list:pCard);  
    procedure addCard(aCard:pCard);   
    procedure addNewCard(val,suit:byte;vis:boolean);  
    function  getLastCard:pCard;  
    function  getCard(i:byte):pCard;  
    function  getAvailableCardNo:byte;  
  end; 
 
var frm:String[12];   
 
 
procedure card.Init(_val,_suit,_x,_y:byte;_visible:boolean); 
  begin 
  val     := _val; 
  suit    := _suit; 
  x       := _x; 
  y       := _y; 
  visible := _visible; 
  next    := nil; 
  end; 
 
procedure card.Draw; 
var topL,cFace :String; 
  begin 
  cFace := '**';  
  if (visible) then cFace := cardVal[val]+cardSuit[suit];  
  topL := frm[1]+frm[1]+frm[5]; 
  if (visible and (val=10)) then 
    topL := frm[1]+frm[5]; 
  gotoXY(x,y); 
  write(frm[3]); 
  if (visible) then TextAttr:=suitColor[suit];  
  write(cFace); 
  TextAttr:=bgcolor;  
  write(topL); 
  gotoXY(x,y+1);write(frm[2],'    ',frm[2]); 
  gotoXY(x,y+2);write(frm[2],'    ',frm[2]); 
  gotoXY(x,y+3);write(frm[9],frm[1],frm[1],frm[1],frm[1],frm[11]); 
  end; 
 
procedure cColumn.Init(_n,_x:byte;_list:pCard); 
  begin 
  n:=_n; 
  x:=_x; 
  list:=_list; 
  end; 
 
procedure cColumn.Draw; 
var cCard:pCard; 
  begin 
  cCard := list; 
  while cCard <> nil do 
    begin 
    cCard^.Draw; 
    cCard := cCard^.next; 
    end; 
  end; 
 
procedure cColumn.addCard(aCard:pCard);  
var cCard:pCard; 
    yK:byte; 
  begin 
  if (list=nil) then  
    begin 
    list := aCard;  
    yK:=topY; 
    while (aCard<>nil) do 
      begin 
      aCard^.x:=x; 
      aCard^.y:=yK; 
      inc(yK); 
      aCard:=aCard^.next; 
      end; 
    end 
  else  
    begin 
    cCard :=list;  
    while cCard^.next <> nil do 
      cCard := cCard^.next; 
     
    cCard^.next := aCard; 
    yK:=1+cCard^.y; 
    while aCard<> nil do  
      begin 
      aCard^.x:=x; 
      aCard^.y:=yK; 
      aCard:=aCard^.next; 
      inc(yK); 
      end; 
    end; 
  end; 
 
procedure cColumn.addNewCard(val,suit:byte;vis:boolean);  
var pC :pCard; 
  begin 
  new(pC);  
  pC^.Init(val,suit,1,1,vis); 
  addCard(pC);  
  end; 
 
function cColumn.getLastCard:pCard;  
var cCard:pCard; 
  begin 
  cCard := nil; 
  if (list<>nil) then  
    begin 
    cCard := list; 
    while cCard^.next <> nil do 
      cCard := cCard^.next; 
    end; 
  getLastCard:=cCard; 
  end; 
 
function cColumn.getCard(i:byte):pCard;  
var cCard:pCard; 
    k:byte; 
  begin 
  cCard := nil; 
  if ((list<>nil) and (i>0)) then 
    begin 
    cCard := list; 
    k:=1; 
    while (cCard^.next <> nil) and (k<i) do 
      begin 
      cCard := cCard^.next; 
      inc(k); 
      end; 
    end; 
  getCard:=cCard; 
  end; 
 
function cColumn.getAvailableCardNo:byte;  
 
var cCard:pCard; 
    cN,k:byte; 
    vals,suits,visib:String; 
    suitPatt,valPatt:char; 
    lineOk:boolean; 
  begin 
  cN:=0; 
  if (list<>nil) then  
    begin 
     
    vals:=''; 
    suits:=''; 
    visib:=''; 
    cCard := list; 
    while cCard <> nil do 
      begin 
      vals:=vals+chr(cCard^.val); 
      suits:=suits+chr(cCard^.suit); 
      if cCard^.visible 
        then visib:=visib+'T' 
        else visib:=visib+'F'; 
      cCard := cCard^.next; 
      end; 
    lineOk:=true; 
    suitPatt := suits[length(suits)]; 
    valPatt := vals[length(vals)]; 
    k:=length(vals); 
    while (lineOk and (k>0)) do 
      begin 
      inc(valPatt); 
      dec(k); 
      lineOk := (suitPatt=suits[k]) and (valPatt=vals[k]) and (visib[k]='T'); 
      end; 
    cN := k+1; 
    end; 
  getAvailableCardNo := cN; 
  end; 
 
var  
  columns:array[1..8] of cColumn;  
  i,k,n,j,kFrom,kTo,cardsLeft:shortint; 
  pC :pCard; 
  pack : String; 
  ch:char; 
  cardDone:array[1..4] of card;    
  gameType,moveAvailable,checkComplete:boolean; 
  checkColNum,checkTo:byte; 
 
function getNextCardFromDeck:byte; 
 
var i,j:byte; 
  begin 
  i:=0; 
  if (length(pack)>0) then 
    begin 
    j := 1+random(length(pack)); 
    i := ord(pack[j]); 
    Delete(pack,j,1); 
    end; 
  getNextCardFromDeck := i; 
  end; 
 
function move2done(kFrom:byte;justCheck:boolean):boolean; 
 
 
var pC:pCard; 
    result:boolean; 
  begin 
  pC:=columns[kFrom].getLastCard; 
  result:=false; 
  if (pC^.val = cardDone[pC^.suit].val+1) 
    or ((cardDone[pC^.suit].val=14) and (pC^.val=6)) 
  then  
    begin 
    if (not justCheck) then 
      begin  
      cardDone[pC^.suit].val:=pC^.val; 
      cardDone[pC^.suit].visible:=true; 
       
      if (pC=columns[kFrom].list) then  
        begin 
        Dispose(pC); 
        columns[kFrom].list:=nil 
        end 
      else 
        begin  
        pC:=columns[kFrom].list; 
        while pC^.next^.next<>nil do 
          pC:=pC^.next; 
        Dispose(pC^.next); 
        pC^.next:=nil; 
        pC^.visible:=true;  
        end; 
      Dec(cardsLeft);  
      end; 
    result:=true; 
    end; 
  move2done := result;	 
  end; 
 
function Move(kFrom,kTo:byte;justCheck:boolean):boolean; 
 
var lCard,fCard:pCard; 
    k:byte; 
    result:boolean; 
  procedure moveCard; 
    begin 
    if (not justCheck) then 
      begin  
      columns[kTo].addCard(fCard); 
      fCard:=columns[kFrom].getCard(k-1); 
      if (fCard=nil) 
        then columns[kFrom].list:=nil 
        else 
          begin 
          fCard^.next:=nil; 
          fCard^.visible:=true; 
          end; 
      end; 
    result := true; 
    end; 
  begin  
  if (kTo=0) then  
    result := (move2done(kFrom,justCheck)) 
  else  
    begin 
    lCard := columns[kTo].getLastCard;  
    k := columns[kFrom].getAvailableCardNo; 
    fCard:=columns[kFrom].getCard(k);  
    if (lCard=nil) then  
      moveCard 
    else if (fCard^.suit=lCard^.suit) then  
      begin 
      while ((fCard<>nil) and (fCard^.val<>lCard^.val-1)) do 
       
        begin 
        fCard:=fCard^.next; 
        Inc(k); 
        end; 
      if (fCard<>nil) then  
        moveCard 
      else  
        result := false; 
      end 
    else  
      result := false; 
    end; 
  Move:=result; 
  end; 
 
 
procedure displayAll;  
  begin 
  clrscr; 
  for i:=1 to 8 do  
    begin 
    gotoXY(i*6-2,1);write(i); 
    columns[i].Draw; 
    end; 
  for i:=1 to 4 do 
    begin 
    gotoXY(51+i*6,1);write('0'); 
     
    cardDone[i].Draw; 
    end; 
  GotoXY(55,8);write('Cards Left: ',cardsLeft); 
  GotoXY(55,10);write('Chose two column numbers:'); 
  GotoXY(57,11);write('From and To'); 
  end; 
 
 
procedure restartCheck;  
  begin 
  moveAvailable:=false; 
  checkComplete:=false; 
  checkColNum:=1; checkTo:=0; 
  end; 
 
procedure chekMoveAvailable; 
 
  begin 
  if (not checkComplete) then 
    if (move(checkColNum,checkTo,true)) then 
      begin  
      moveAvailable:=true; 
      checkComplete:=true; 
      gotoXY(50,16);write('T'); 
      end 
    else 
      begin  
      inc(checkTo); 
      if (checkTo>8) then 
        begin 
        checkTo:=0; 
        inc(checkColNum); 
        if (checkColNum>8) then 
          checkComplete:=true;  
        end 
      end 
  end; 
 
begin  
gameType := gameTypeHidden;  
gameType := gameTypeVisible;  
        
frm := '-¦-T¬+++L+-';  
frm := '-!+++++++++';  
frm := #196#179#218#194#191#195#197#180#192#193#217;  
TextAttr:=bgcolor; 
clrscr; 
 
for i:=1 to 8 do columns[i].Init(i,1+(i-1)*6,nil); 
for i:=1 to 4 do 
  cardDone[i].init(13,i,48+6*i,topY,false); 
 
 
 
randomize; 
pack := '';  
for i:=1 to 36 do pack := pack + chr(i); 
for k:=1 to 8 do 
  begin 
  for j:=1 to 8-k do 
    begin 
    i:=getNextCardFromDeck; 
    columns[k].addNewCard(6+(i mod 9),1+((i-1) div 9),gameType);  
    end; 
   
  i:=getNextCardFromDeck; 
  columns[k].addNewCard(6+(i mod 9),1+((i-1) div 9),true); 
  end; 
 
cardsLeft:=36; 
displayAll; 
 
kFrom:=-1;kTo:=-1;ch:=' '; 
restartCheck; 
repeat 
  if keyPressed then 
    begin 
    ch:=readkey; 
    if (ch in ['0'..'8']) then 
      begin 
      if (kFrom<0) 
        then 
          begin 
          kFrom:=ord(ch)-ord('0'); 
          gotoXY(19,23);write(ch,'->         ');gotoXY(1,1); 
          end 
        else 
          begin 
          kTo:=ord(ch)-ord('0'); 
          if (move(kFrom,kTo,false)) then 
            begin 
            displayAll; 
            gotoXY(19,23); 
            writeln('move done'); 
            restartCheck; 
            end 
          else 
            begin 
            gotoXY(19,23); 
            writeln('not possible to move'); 
            end; 
          kFrom:=-1;kTo:=-1; 
          end; 
      end; 
    end 
  else chekMoveAvailable; 
until (ch=#27) or (cardsLeft<1) or (checkComplete and (not moveAvailable)); 
if (cardsLeft<1) then  
  begin 
  gotoXY(19,23); 
  write('Well done!            '); 
  end else 
if (not moveAvailable) then  
  begin 
  gotoXY(19,23); 
  write('No more moves available.'); 
  end; 
end. 
 
 
 
 |