Пасьянс "Косынка"
Колода из 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.
|