544 lines
15 KiB
Go
544 lines
15 KiB
Go
package cribbage
|
|
|
|
import (
|
|
"testing"
|
|
|
|
. "code.rocketnine.space/tslocum/joker"
|
|
)
|
|
|
|
var (
|
|
testHandA = Cards{
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{Face4, SuitSpades},
|
|
Card{Face5, SuitSpades}}
|
|
testHandB = Cards{
|
|
Card{FaceJack, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}
|
|
testHandC = Cards{
|
|
Card{Face3, SuitHearts},
|
|
Card{Face3, SuitDiamonds},
|
|
Card{Face3, SuitClubs},
|
|
Card{Face3, SuitSpades}}
|
|
testHandD = Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}
|
|
testHandE = Cards{
|
|
Card{Face7, SuitHearts},
|
|
Card{Face8, SuitHearts},
|
|
Card{Face9, SuitHearts},
|
|
Card{Face10, SuitHearts}}
|
|
testHandF = Cards{
|
|
Card{Face3, SuitHearts},
|
|
Card{Face6, SuitHearts},
|
|
Card{Face5, SuitHearts},
|
|
Card{Face4, SuitHearts}}
|
|
testHandG = Cards{
|
|
Card{Face6, SuitHearts},
|
|
Card{Face5, SuitHearts},
|
|
Card{Face4, SuitHearts}}
|
|
testHandH = Cards{
|
|
Card{FaceAce, SuitHearts},
|
|
Card{Face3, SuitHearts},
|
|
Card{Face2, SuitHearts},
|
|
Card{Face4, SuitHearts}}
|
|
testHandI = Cards{
|
|
Card{FaceAce, SuitHearts},
|
|
Card{Face3, SuitHearts},
|
|
Card{FaceAce, SuitClubs},
|
|
Card{Face2, SuitHearts},
|
|
Card{Face4, SuitHearts},
|
|
Card{Face7, SuitHearts}}
|
|
testHandJ = Cards{
|
|
Card{Face7, SuitHearts},
|
|
Card{Face3, SuitHearts},
|
|
Card{Face2, SuitHearts},
|
|
Card{Face4, SuitHearts}}
|
|
testHandK = Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{FaceJack, SuitSpades}}
|
|
testHandL = Cards{
|
|
Card{Face2, SuitHearts},
|
|
Card{Face2, SuitDiamonds},
|
|
Card{Face7, SuitClubs},
|
|
Card{Face7, SuitSpades}}
|
|
testHandM = Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{FaceKing, SuitSpades}}
|
|
)
|
|
|
|
type expectedPegScore struct {
|
|
Hand Cards
|
|
|
|
Result []ScoreResult
|
|
}
|
|
|
|
var expectedPegScores = []expectedPegScore{
|
|
{testHandA, []ScoreResult{
|
|
{Type: ScoreRun, Points: 4, Cards: Cards{
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{Face4, SuitSpades},
|
|
Card{Face5, SuitSpades}}}}},
|
|
{testHandB, []ScoreResult{
|
|
{Type: ScorePair, Points: 6, Cards: Cards{
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}}}},
|
|
{testHandC, []ScoreResult{
|
|
{Type: ScorePair, Points: 12, Cards: Cards{
|
|
Card{Face3, SuitHearts},
|
|
Card{Face3, SuitDiamonds},
|
|
Card{Face3, SuitClubs},
|
|
Card{Face3, SuitSpades}}}}},
|
|
{testHandF, []ScoreResult{
|
|
{Type: ScoreRun, Points: 4, Cards: Cards{
|
|
Card{Face3, SuitHearts},
|
|
Card{Face4, SuitHearts},
|
|
Card{Face5, SuitHearts},
|
|
Card{Face6, SuitHearts}}}}},
|
|
{testHandG, []ScoreResult{
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face4, SuitHearts},
|
|
Card{Face5, SuitHearts},
|
|
Card{Face6, SuitHearts}}},
|
|
{Type: ScoreRun, Points: 3, Cards: Cards{
|
|
Card{Face4, SuitHearts},
|
|
Card{Face5, SuitHearts},
|
|
Card{Face6, SuitHearts}}}}},
|
|
{testHandH, []ScoreResult{
|
|
{Type: ScoreRun, Points: 4, Cards: Cards{
|
|
Card{FaceAce, SuitHearts},
|
|
Card{Face2, SuitHearts},
|
|
Card{Face3, SuitHearts},
|
|
Card{Face4, SuitHearts}}}}},
|
|
{testHandI, []ScoreResult{}},
|
|
{testHandJ, []ScoreResult{
|
|
{Type: ScoreRun, Points: 3}}},
|
|
{testHandK, []ScoreResult{}},
|
|
{testHandL, []ScoreResult{
|
|
{Type: ScorePair, Points: 2, Cards: Cards{
|
|
Card{Face7, SuitClubs},
|
|
Card{Face7, SuitSpades}}}}},
|
|
{testHandM, []ScoreResult{}},
|
|
}
|
|
|
|
type expectedShowScore struct {
|
|
Starter Card
|
|
Hand Cards
|
|
|
|
HandResult []ScoreResult
|
|
CribResult []ScoreResult
|
|
}
|
|
|
|
var expectedShowScores = []expectedShowScore{
|
|
{Card{FaceAce, SuitSpades},
|
|
testHandA, []ScoreResult{
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{FaceAce, SuitSpades},
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{Face4, SuitSpades},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: ScoreRun, Points: 5, Cards: Cards{
|
|
Card{FaceAce, SuitSpades},
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{Face4, SuitSpades},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: ScoreFlush, Points: 5, Cards: Cards{
|
|
Card{FaceAce, SuitSpades},
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{Face4, SuitSpades},
|
|
Card{Face5, SuitSpades}}},
|
|
}, []ScoreResult{
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{FaceAce, SuitSpades},
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{Face4, SuitSpades},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: ScoreRun, Points: 5, Cards: Cards{
|
|
Card{FaceAce, SuitSpades},
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{Face4, SuitSpades},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: ScoreFlush, Points: 5, Cards: Cards{
|
|
Card{FaceAce, SuitSpades},
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{Face4, SuitSpades},
|
|
Card{Face5, SuitSpades}}},
|
|
}},
|
|
|
|
{Card{FaceKing, SuitClubs},
|
|
testHandA, []ScoreResult{
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitSpades},
|
|
Card{FaceKing, SuitClubs}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{FaceKing, SuitClubs}}},
|
|
{Type: ScoreRun, Points: 4, Cards: Cards{
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{Face4, SuitSpades},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: ScoreFlush, Points: 4, Cards: Cards{
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{Face4, SuitSpades},
|
|
Card{Face5, SuitSpades}}},
|
|
}, []ScoreResult{
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitSpades},
|
|
Card{FaceKing, SuitClubs}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{FaceKing, SuitClubs}}},
|
|
{Type: ScoreRun, Points: 4, Cards: Cards{
|
|
Card{Face2, SuitSpades},
|
|
Card{Face3, SuitSpades},
|
|
Card{Face4, SuitSpades},
|
|
Card{Face5, SuitSpades}}},
|
|
}},
|
|
|
|
{Card{Face8, SuitClubs},
|
|
testHandE, []ScoreResult{
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face7, SuitHearts},
|
|
Card{Face8, SuitHearts}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face7, SuitHearts},
|
|
Card{Face8, SuitClubs}}},
|
|
{Type: ScorePair, Points: 2, Cards: Cards{
|
|
Card{Face8, SuitHearts},
|
|
Card{Face8, SuitClubs}}},
|
|
{Type: ScoreRun, Points: 4, Cards: Cards{
|
|
Card{Face7, SuitHearts},
|
|
Card{Face8, SuitHearts},
|
|
Card{Face9, SuitHearts},
|
|
Card{Face10, SuitHearts}}},
|
|
{Type: ScoreRun, Points: 4, Cards: Cards{
|
|
Card{Face7, SuitHearts},
|
|
Card{Face8, SuitClubs},
|
|
Card{Face9, SuitHearts},
|
|
Card{Face10, SuitHearts}}},
|
|
{Type: ScoreFlush, Points: 4, Cards: Cards{
|
|
Card{Face7, SuitHearts},
|
|
Card{Face8, SuitHearts},
|
|
Card{Face9, SuitHearts},
|
|
Card{Face10, SuitHearts}}},
|
|
}, []ScoreResult{
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face7, SuitHearts},
|
|
Card{Face8, SuitHearts}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face7, SuitHearts},
|
|
Card{Face8, SuitClubs}}},
|
|
{Type: ScorePair, Points: 2, Cards: Cards{
|
|
Card{Face8, SuitHearts},
|
|
Card{Face8, SuitClubs}}},
|
|
{Type: ScoreRun, Points: 4, Cards: Cards{
|
|
Card{Face7, SuitHearts},
|
|
Card{Face8, SuitHearts},
|
|
Card{Face9, SuitHearts},
|
|
Card{Face10, SuitHearts}}},
|
|
{Type: ScoreRun, Points: 4, Cards: Cards{
|
|
Card{Face7, SuitHearts},
|
|
Card{Face8, SuitClubs},
|
|
Card{Face9, SuitHearts},
|
|
Card{Face10, SuitHearts}}},
|
|
}},
|
|
|
|
{Card{Face5, SuitSpades},
|
|
testHandK, []ScoreResult{
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{FaceJack, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitDiamonds},
|
|
Card{FaceJack, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitClubs},
|
|
Card{FaceJack, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitSpades},
|
|
Card{FaceJack, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: ScorePair, Points: 12, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: ScoreNobs, Points: 1, Cards: Cards{
|
|
Card{FaceJack, SuitSpades}}},
|
|
}, []ScoreResult{
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{FaceJack, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitDiamonds},
|
|
Card{FaceJack, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitClubs},
|
|
Card{FaceJack, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitSpades},
|
|
Card{FaceJack, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: ScorePair, Points: 12, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: ScoreNobs, Points: 1, Cards: Cards{
|
|
Card{FaceJack, SuitSpades}}},
|
|
}},
|
|
|
|
{Card{Face5, SuitSpades},
|
|
testHandM, []ScoreResult{
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{FaceKing, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitDiamonds},
|
|
Card{FaceKing, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitClubs},
|
|
Card{FaceKing, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitSpades},
|
|
Card{FaceKing, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: ScorePair, Points: 12, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
}, []ScoreResult{
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{FaceKing, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitDiamonds},
|
|
Card{FaceKing, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitClubs},
|
|
Card{FaceKing, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitSpades},
|
|
Card{FaceKing, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: Score15, Points: 2, Cards: Cards{
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
{Type: ScorePair, Points: 12, Cards: Cards{
|
|
Card{Face5, SuitHearts},
|
|
Card{Face5, SuitDiamonds},
|
|
Card{Face5, SuitClubs},
|
|
Card{Face5, SuitSpades}}},
|
|
}},
|
|
}
|
|
|
|
func TestScorePeg(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for i, expected := range expectedPegScores {
|
|
if Sum(expected.Hand) > 31 {
|
|
t.Errorf("case %d: invalid peg hand sum: got %d, want <=31: %s", i, Sum(expected.Hand), expected.Hand)
|
|
}
|
|
|
|
pegPoints, pegResult := Score(Peg, expected.Hand, Card{})
|
|
|
|
if !resultsEqual(pegResult, expected.Result) {
|
|
t.Fatalf("case %d: incorrect peg result: got %s, want %s: %s", i, pegResult, expected.Result, expected.Hand)
|
|
}
|
|
|
|
var expectedPoints int
|
|
for _, r := range expected.Result {
|
|
expectedPoints += r.Points
|
|
}
|
|
if pegPoints != expectedPoints {
|
|
t.Fatalf("case %d: incorrect peg score: got %d, want %d: %s", i, pegPoints, expectedPoints, expected.Hand)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestScoreShowHand(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var expectedPoints int
|
|
for i, expected := range expectedShowScores {
|
|
handPoints, handResult := Score(ShowHand, expected.Hand, expected.Starter)
|
|
|
|
if !resultsEqual(handResult, expected.HandResult) {
|
|
t.Fatalf("case %d: incorrect hand result: got %s, want %s: %s - %s", i, handResult, expected.HandResult, expected.Starter, expected.Hand)
|
|
}
|
|
|
|
expectedPoints = 0
|
|
for _, r := range expected.HandResult {
|
|
expectedPoints += r.Points
|
|
}
|
|
if handPoints != expectedPoints {
|
|
t.Fatalf("case %d: incorrect hand score: got %d, want %d: %s - %s", i, handPoints, expectedPoints, expected.Starter, expected.Hand)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestScoreShowCrib(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var expectedPoints int
|
|
for i, expected := range expectedShowScores {
|
|
cribPoints, cribResult := Score(ShowCrib, expected.Hand, expected.Starter)
|
|
|
|
if !resultsEqual(cribResult, expected.CribResult) {
|
|
t.Fatalf("case %d: incorrect crib result: got %s, want %s: %s - %s", i, cribResult, expected.CribResult, expected.Starter, expected.Hand)
|
|
}
|
|
|
|
expectedPoints = 0
|
|
for _, r := range expected.CribResult {
|
|
expectedPoints += r.Points
|
|
}
|
|
if cribPoints != expectedPoints {
|
|
t.Fatalf("case %d: incorrect crib score: got %d, want %d: %s - %s", i, cribPoints, expectedPoints, expected.Starter, expected.Hand)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkScorePeg(b *testing.B) {
|
|
var (
|
|
score int
|
|
results ScoreResults
|
|
)
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
for _, expected := range expectedPegScores {
|
|
score, results = Score(Peg, expected.Hand, Card{})
|
|
}
|
|
}
|
|
_, _ = score, results
|
|
}
|
|
|
|
func BenchmarkScoreShowHand(b *testing.B) {
|
|
var (
|
|
score int
|
|
results ScoreResults
|
|
)
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
for _, expected := range expectedShowScores {
|
|
score, results = Score(ShowHand, expected.Hand, expected.Starter)
|
|
}
|
|
}
|
|
_, _ = score, results
|
|
}
|
|
|
|
func BenchmarkScoreShowCrib(b *testing.B) {
|
|
var (
|
|
score int
|
|
results ScoreResults
|
|
)
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
for _, expected := range expectedShowScores {
|
|
score, results = Score(ShowCrib, expected.Hand, expected.Starter)
|
|
}
|
|
}
|
|
_, _ = score, results
|
|
}
|
|
|
|
func resultsEqual(a []ScoreResult, b []ScoreResult) bool {
|
|
if len(a) != len(b) {
|
|
return false
|
|
}
|
|
|
|
for i := range a {
|
|
if a[i].Type != b[i].Type {
|
|
return false
|
|
} else if a[i].Points != b[i].Points {
|
|
return false
|
|
} else if len(a[i].Cards) != len(b[i].Cards) {
|
|
return false
|
|
}
|
|
|
|
for j := range a[i].Cards {
|
|
if !a[i].Cards[j].Equal(b[i].Cards[j]) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|