📄 cards.pas
字号:
var
suit, num, i, suit1, num1: Integer;
b: Boolean;
begin
suit := GetSuit(FPlayerCards[APlayerIndex].Card[ACardIndex]);
num := GetNum(FPlayerCards[APlayerIndex].Card[ACardIndex]);
//判断这张牌前面的牌是否被自已盖了,若是需盖
for i := 0 to FPlayerCoverCards[APlayerIndex].Count - 1 do
begin
suit1 := GetSuit(FPlayerCoverCards[APlayerIndex].Card[i]);
num1 := GetNum(FPlayerCoverCards[APlayerIndex].Card[i]);
if suit = suit1 then
begin
if ((num > 6) and (num1 > 6) and (num > num1))
or ((num < 6) and (num1 < 6) and (num < num1)) then
begin
Result := True;
Exit;
end;
end;
end;
//判断这张牌前面已出的最大或最小牌在出来后,其他玩家是否都盖过牌了
//如果都盖过牌了且这张牌是当前牌前面的牌,则需盖
if FOutCards[suit].Min = scNone then //未出过牌的花色排除
begin
Result := False;
Exit;
end;
b := True;
for i := 0 to PLAYER_COUNT - 1 do
begin
if i = APlayerIndex then Continue;
if num > 6 then
b := b and FOutCards[suit].MaxCover[i]
else
b := b and FOutCards[suit].MinCover[i];
if not b then break;
end;
Result := b;
end;
function TCards.IsLate(APlayerIndex, ACardIndex: Integer): Boolean;
var
i, j, n, m, suit, num, suit1, num1: Integer;
begin
suit := GetSuit(FPlayerCards[APlayerIndex].Card[ACardIndex]);
num := GetNum(FPlayerCards[APlayerIndex].Card[ACardIndex]);
j := 0;
for i := 0 to PLAYER_CARD_COUNT - 1 do
begin
if i = ACardIndex then Continue;
if FPlayerCards[APlayerIndex].Card[i] = scNone then Continue;
suit1 := GetSuit(FPlayerCards[APlayerIndex].Card[i]);
num1 := GetNum(FPlayerCards[APlayerIndex].Card[i]);
if (suit = suit1) then
if ((num > 6) and (num > num1)) or ((num < 6) and (num < num1)) then
Inc(j);
end;
if num > 6 then
n := num - FOutCards[suit].Max - 1
else
n := FOutCards[suit].Min - num - 1;
m := (FPlayerCards[APlayerIndex].Count - j - 1) * 3;
Result := n > m //n = 当前牌和已出的牌的距离 m = 最大出牌机会
end;
function TCards.HaveCont(APlayerIndex, ACardIndex: Integer): Boolean;
var
suit, num, i, l_min, l_max: Integer;
begin
suit := GetSuit(FPlayerCards[APlayerIndex].Card[ACardIndex]);
num := GetNum(FPlayerCards[APlayerIndex].Card[ACardIndex]);
//定义需要查找是否在自已手上的牌区间
if num > 6 then
begin
if FOutCards[suit].Min <> scNone then //如果此花色未出牌
l_min := FOutCards[suit].Max + 1
else
l_min := 7;
l_max := num - 1;
end
else begin
l_min := num + 1;
if FOutCards[suit].Min <> scNone then //如果此花色未出牌
l_max := FOutCards[suit].Min - 1
else
l_max := 5;
end;
//查找区间的所有牌是否在自已手上
for i := l_min to l_max do
begin
if FindCard(APlayerIndex, suit, i) = -1 then //不在自已手上,则返回false
begin
Result := False;
Exit;
end;
end;
Result := True;
end;
function TCards.HaveNext(APlayerIndex, ACardIndex: Integer; ANextN: Integer = 1): Boolean;
var
suit, num: Integer;
bmin, bmax: Boolean;
begin
suit := GetSuit(FPlayerCards[APlayerIndex].Card[ACardIndex]);
num := GetNum(FPlayerCards[APlayerIndex].Card[ACardIndex]);
bmax := FindCard(APlayerIndex, suit, num + ANextN) >=0 ;
bmin := FindCard(APlayerIndex, suit, num - ANextN) >= 0;
if num = 6 then
Result := bmax and bmin
else if num > 6 then
Result := bmax
else
Result := bmin;
end;
function TCards.IsTop(APlayerIndex, ACardIndex: Integer): Boolean;
var
suit, num: Integer;
begin
suit := GetSuit(FPlayerCards[APlayerIndex].Card[ACardIndex]);
num := GetNum(FPlayerCards[APlayerIndex].Card[ACardIndex]);
//若当前牌为1或K则就是最头上的牌
if (num = 0) or (num = 12) then
Result := True
//若当前牌后面一张牌被盖了,则就是最头上的牌
else if (num > 6) and (FindCoverCard(APlayerIndex, suit, num + 1) >= 0) or
(num < 6) and (FindCoverCard(APlayerIndex, suit, num - 1) >= 0) then
Result := True
else
Result := False;
end;
function TCards.AfterScore(APlayerIndex, ACardIndex: Integer): Integer;
var
i, suit, num, suit1, num1: Integer;
begin
Result := 0;
suit := GetSuit(FPlayerCards[APlayerIndex].Card[ACardIndex]);
num := GetNum(FPlayerCards[APlayerIndex].Card[ACardIndex]);
for i := 0 to PLAYER_CARD_COUNT - 1 do
begin
if i = ACardIndex then Continue;
if FPlayerCards[APlayerIndex].Card[i] = scNone then Continue;
suit1 := GetSuit(FPlayerCards[APlayerIndex].Card[i]);
num1 := GetNum(FPlayerCards[APlayerIndex].Card[i]);
if (suit = suit1) and
((num = 6) or ((num > 6) and (num1 > num)) or ((num1 < 6) and (num1 < num))) then
Result := Result + GetNum(FPlayerCards[APlayerIndex].Card[i]) + 1;
end;
end;
function TCards.AfterScoreAll(APlayerIndex, ACardIndex: Integer): Integer;
var
i, suit, num: Integer;
begin
Result := 0;
suit := GetSuit(FPlayerCards[APlayerIndex].Card[ACardIndex]);
num := GetNum(FPlayerCards[APlayerIndex].Card[ACardIndex]);
if num > 6 then
for i := num + 1 to 12 do
Result := Result + GetScore(suit, i)
else
for i := 0 to num - 1 do
Result := Result + GetScore(suit, i);
end;
function TCards.AfterQuantity(APlayerIndex, ACardIndex: Integer): Integer;
var
i, suit, num, suit1, num1: Integer;
begin
Result := 0;
suit := GetSuit(FPlayerCards[APlayerIndex].Card[ACardIndex]);
num := GetNum(FPlayerCards[APlayerIndex].Card[ACardIndex]);
for i := 0 to PLAYER_CARD_COUNT - 1 do
begin
if i = ACardIndex then Continue;
if FPlayerCards[APlayerIndex].Card[i] = scNone then Continue;
suit1 := GetSuit(FPlayerCards[APlayerIndex].Card[i]);
num1 := GetNum(FPlayerCards[APlayerIndex].Card[i]);
if (suit = suit1) and
((num = 6) or (num > 6) and (num1 > num) or (num < 6) and (num1 < num)) then
Inc(Result);
end;
end;
function TCards.BeforeQuantity(APlayerIndex, ACardIndex: Integer): Integer;
var
i, suit, num, suit1, num1: Integer;
begin
Result := 0;
suit := GetSuit(FPlayerCards[APlayerIndex].Card[ACardIndex]);
num := GetNum(FPlayerCards[APlayerIndex].Card[ACardIndex]);
for i := 0 to PLAYER_CARD_COUNT - 1 do
begin
if i = ACardIndex then Continue;
if FPlayerCards[APlayerIndex].Card[i] = scNone then Continue;
suit1 := GetSuit(FPlayerCards[APlayerIndex].Card[i]);
num1 := GetNum(FPlayerCards[APlayerIndex].Card[i]);
if (suit = suit1) and
((num > 6) and (num1 < num)) or ((num1 < 6) and (num1 > num)) then
Inc(Result);
end;
end;
function TCards.DistanceOut(ACardID: Integer): Integer;
var
suit, num: Integer;
begin
suit := GetSuit(ACardID);
num := GetNum(ACardID);
if FOutCards[suit].Min = scNone then //如果花色未出过牌,则返回-1
begin
Result := -1;
exit;
end;
if num > 6 then
Result := num - FOutCards[suit].Max - 1
else
Result := FOutCards[suit].Min - num - 1;
end;
function TCards.PriorOutIsMe(ASuit, APlayerIndex, ANum: Integer): Boolean;
begin
if ANum > 6 then
Result := FOutCards[ASuit].MaxOwner = APlayerIndex
else
Result := FOutCards[ASuit].MinOwner = APlayerIndex;
end;
function TCards.SureOut(APlayerIndex, ACardIndex: Integer): Boolean;
var
i, suit, num, n: Integer;
b: boolean;
begin
suit := GetSuit(FPlayerCards[APlayerIndex].Card[ACardIndex]);
num := GetNum(FPlayerCards[APlayerIndex].Card[ACardIndex]);
//判断已出的最大或最小牌在出来后,其他玩家是否都没盖过牌
//如果都没盖过牌了且这张牌和已出牌相距1,则肯定可出
//如果相距大于1, 而前一张牌在自已手里的话,则看前一张是否和已出牌相距1。
b := False;
for i := 0 to PLAYER_COUNT - 1 do
begin
if i = APlayerIndex then Continue;
if num > 6 then
b := b or FOutCards[suit].MaxCover[i]
else
b := b or FOutCards[suit].MinCover[i];
if b then //如果有人盖过牌,则返回假
begin
Result := False;
Exit;
end;
end;
n := ACardIndex;
repeat
if DistanceOut(FPlayerCards[APlayerIndex].Card[n]) < 1 then //返回真
begin
Result := True;
Exit;
end;
if num > 6 then
Dec(num)
else
Inc(num);
n := FindCard(APlayerIndex, suit, num);
until (num = 6) or (n < 0);
Result := False;
end;
function TCards.NextIsCover(APlayerIndex, ACardIndex: Integer): Boolean;
var
i, suit, num, l_min, l_max: Integer;
begin
suit := GetSuit(FPlayerCards[APlayerIndex].Card[ACardIndex]);
num := GetNum(FPlayerCards[APlayerIndex].Card[ACardIndex]);
if num > 6 then
begin
l_min := num + 1;
l_max := 12;
end
else begin
l_min := 0;
l_max := num - 1;
end;
for i := l_min to l_max do
if FindCoverCard(APlayerIndex, suit, i) >= 0 then
begin
Result := True;
Exit;
end;
Result := False;
end;
function TCards.CalcOutCard(APlayerIndex: Integer): Integer;
var
cs, qz: TPlayerCard;
i, j, suit, num: Integer;
begin
cs.Count := 0;
//若玩家牌数为1,则这张牌就是要发的牌
if FPlayerCards[APlayerIndex].Count = 1 then
for i := 0 to PLAYER_CARD_COUNT - 1 do
if FPlayerCards[APlayerIndex].Card[i] <> scNone then
begin
Result := i;
Exit;
end;
//得到所有可出的牌
for i := 0 to PLAYER_CARD_COUNT - 1 do
if CanOut(APlayerIndex, i) then
begin
if FPlayerCards[APlayerIndex].Card[i] = FIRST_OUT_CARD then
begin
Result := i;
Exit;
end;
Inc(cs.Count);
cs.Card[cs.Count - 1] := i;
end;
//若可出的牌只有一张,则返回这张牌
if cs.Count = 1 then
begin
Result := cs.Card[0];
Exit;
end;
//根据权值计算优先出的牌,权值大的先出。
for i := 0 to cs.Count - 1 do
begin
suit := GetSuit(FPlayerCards[APlayerIndex].Card[cs.Card[i]]);
num := GetNum(FPlayerCards[APlayerIndex].Card[cs.Card[i]]);
//置初始权值,置初始权值,离7远的权值大,小于7的又比大于7的大
qz.Card[i] := (1 - num div 7) * 6 + Abs(num - 6);
if num <> 6 then
qz.Card[i] := qz.Card[i] + AfterQuantity(APlayerIndex, cs.Card[i]) //后面牌多的先出
//若牌为7,且自已的总分大于110的,优先出
else if (FPlayerCards[APlayerIndex].Score > 100) then
begin
qz.Card[i] := qz.Card[i] + 50;
qz.Card[i] := qz.Card[i] + AfterQuantity(APlayerIndex, cs.Card[i]);
end;
//若牌大于7且后面的分数占了所有分数的一半的,优先出
if (num > 6) and (AfterScore(APlayerIndex, cs.Card[i]) * 2 > AfterScoreAll(APlayerIndex, i)) then
qz.Card[i] := qz.Card[i] + 10;
//若牌小于7且后面的张数占了所有张数的一半的,优先出
if (num < 6) and (AfterQuantity(APlayerIndex, cs.Card[i]) * 2 > 6) then
qz.Card[i] := qz.Card[i] + 10;
//最头上的牌,则优先出
if IsTop(APlayerIndex, cs.Card[i]) then
qz.Card[i] := qz.Card[i] + 10
//后面自已没有牌的且不是最头上的牌,则考虑先不出
else if AfterQuantity(APlayerIndex, cs.Card[i]) = 0 then
begin
if num > 6 then
qz.Card[i] := qz.Card[i] - 20;
if num < 6 then
qz.Card[i] := qz.Card[i] - 10;
end
//后面紧接的牌在自已手上, 则优先出
else if HaveNext(APlayerIndex, cs.Card[i]) then
qz.Card[i] := qz.Card[i] + 10
//如果后面隔一张在自已这里的,则优先出
else if HaveNext(APlayerIndex, cs.Card[i], 2) then
qz.Card[i] := qz.Card[i] + 20;
//================= 在以上权值相同的情况下 ================
//花色先出的牌先出
qz.Card[i] := qz.Card[i] * 4 + 4 - FOutCards[suit].Order;
end;
//将权值最大的返回
j := 0;
for i := 1 to cs.Count - 1 do
if qz.Card[j] <= qz.Card[i] then j := i;
Result := cs.Card[j];
end;
function TCards.CalcCoverCard(APlayerIndex: Integer): Integer;
var
qz: TPlayerCard;
suit, num, i, j: Integer;
begin
//若玩家牌数为1,则这张牌就是要盖的牌
if FPlayerCards[APlayerIndex].Count = 1 then
for i := 0 to PLAYER_CARD_COUNT - 1 do
if FPlayerCards[APlayerIndex].Card[i] <> scNone then
begin
Result := i;
Exit;
end;
//根据权值计算优先盖的牌,权值大的先盖。
for i := 0 to PLAYER_CARD_COUNT - 1 do
begin
if FPlayerCards[APlayerIndex].Card[i] = scNone then
begin qz.Card[i] := 0; Continue; end;
//如果前面牌被盖或没有出牌机会了,则先盖.
if IsCover(APlayerIndex, i) or IsLate(APlayerIndex, i) then
begin
Result := i;
Exit;
end;
suit := GetSuit(FPlayerCards[APlayerIndex].Card[i]);
num := GetNum(FPlayerCards[APlayerIndex].Card[i]);
//置初始权值,离7远的权值大,小于7的比大于7的大
qz.Card[i] := (1 - num div 7) * 6 + Abs(num - 6);
//离已出的牌远的先盖
qz.Card[i] := qz.Card[i] + 5 * DistanceOut(FPlayerCards[APlayerIndex].Card[i]);
//如果确定可出的牌,先不盖
if SureOut(APlayerIndex, i) then
qz.Card[i] := qz.Card[i] - 10;
//如果后面有牌被自已盖的,先不盖
if NextIsCover(APlayerIndex, i) then
qz.Card[i] := qz.Card[i] - 10
//如果后面没有牌的(包括后面没盖过牌的)
else begin
if AfterQuantity(APlayerIndex, i) = 0 then
begin
//如果牌前面的牌是不连续的,则优先盖
if not HaveCont(APlayerIndex, i) then qz.Card[i] := qz.Card[i] + 1;
//若大于7且小于J或 小于7且大于4的则优先盖
if (num > 6) and (num < 10) then qz.Card[i] := qz.Card[i] + 30 - num;
if (num < 6) and (num > 3) then qz.Card[i] := qz.Card[i] + 10 + num;
end;
//如果没有后面紧接的牌且这张牌大于7小于10且后面的牌分数小于15的,优先盖
if not HaveNext(APlayerIndex, i) and (num > 6) and (num < 9) and (AfterScore(APlayerIndex, i) < 15) then
qz.Card[i] := qz.Card[i] + 10 + AfterScoreAll(APlayerIndex, i) - AfterScore(APlayerIndex, i);
end;
//如果距离已出牌为1,则已出的那张牌是自已出的,则先不盖
if (DistanceOut(FPlayerCards[APlayerIndex].Card[i]) = 1) and PriorOutIsMe(suit, APlayerIndex, num) then
qz.Card[i] := qz.Card[i] - 10;
//================= 在以上权值相同的情况下 ================
//前面的牌多的先盖
qz.Card[i] := qz.Card[i] * 5 + BeforeQuantity(APlayerIndex, i);
//花色后出的牌先盖
qz.Card[i] := qz.Card[i] * 4 + FOutCards[suit].Order;
end;
//将权值最大的返回
j := -1;
for i := 0 to PLAYER_CARD_COUNT - 1 do
begin
if FPlayerCards[APlayerIndex].Card[i] = scNone then Continue;
if (j < 0) or (qz.Card[j] <= qz.Card[i]) then j := i;
end;
Result := j;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -