memory_test.gno
3.67 Kb · 134 lines
1package memory
2
3import (
4 "testing"
5
6 "gno.land/p/nt/testutils/v0"
7 "gno.land/p/nt/uassert/v0"
8)
9
10// findPairIndices returns two grid indices holding the same face, plus a third
11// index whose face differs from that pair — using the current board layout.
12func findPairIndices() (int, int, int) {
13 // Map first-seen index per face.
14 first := map[int]int{}
15 var pa, pb int = -1, -1
16 for i := 0; i < gridSize; i++ {
17 f := board.tiles[i].face
18 if j, ok := first[f]; ok {
19 pa, pb = j, i
20 break
21 }
22 first[f] = i
23 }
24 // Find an index outside the matched pair with a different face.
25 other := -1
26 for i := 0; i < gridSize; i++ {
27 if i != pa && i != pb && board.tiles[i].face != board.tiles[pa].face {
28 other = i
29 break
30 }
31 }
32 return pa, pb, other
33}
34
35func TestFlipMatchAndMiss(cur realm, t *testing.T) {
36 addr := testutils.TestAddress("player")
37 testing.SetRealm(testing.NewUserRealm(addr))
38
39 NewGame(cross(cur))
40
41 pa, pb, other := findPairIndices()
42 uassert.True(t, pa >= 0 && pb >= 0 && other >= 0, "expected valid indices")
43
44 // Flip a matching pair -> both matched, pairs increments.
45 Flip(cross(cur), pa)
46 Flip(cross(cur), pb)
47 uassert.True(t, board.tiles[pa].matched, "first tile should be matched")
48 uassert.True(t, board.tiles[pb].matched, "second tile should be matched")
49 uassert.Equal(t, 1, board.pairs)
50 uassert.Equal(t, 1, board.moves)
51
52 // Flip a mismatched pair (pa is matched; pick two unmatched non-equal).
53 // Reuse `other` and find a partner with a different face, both unmatched.
54 partner := -1
55 for i := 0; i < gridSize; i++ {
56 if i != other && !board.tiles[i].matched && board.tiles[i].face != board.tiles[other].face {
57 partner = i
58 break
59 }
60 }
61 uassert.True(t, partner >= 0, "expected a mismatched partner")
62
63 Flip(cross(cur), other)
64 Flip(cross(cur), partner)
65 uassert.Equal(t, 2, board.moves)
66 uassert.Equal(t, 1, board.pairs) // no new match
67 // Both still showing (not matched) until next flip clears them.
68 uassert.False(t, board.tiles[other].matched, "mismatched tile not matched")
69 uassert.Equal(t, 2, len(board.flipped))
70
71 // Next flip clears the two mismatched tiles first.
72 // Find any still-unmatched, not-currently-flipped index.
73 next := -1
74 for i := 0; i < gridSize; i++ {
75 if i == other || i == partner {
76 continue
77 }
78 if !board.tiles[i].matched {
79 next = i
80 break
81 }
82 }
83 uassert.True(t, next >= 0, "expected an unflipped unmatched tile")
84 Flip(cross(cur), next)
85 uassert.Equal(t, 1, len(board.flipped), "previous mismatch cleared, one showing")
86}
87
88func TestDeterministicShuffleAndRender(cur realm, t *testing.T) {
89 // Same seed -> identical layout.
90 a := shuffle(42)
91 b := shuffle(42)
92 for i := 0; i < gridSize; i++ {
93 uassert.Equal(t, a[i].face, b[i].face)
94 }
95
96 // Different seed -> at least one differing cell (extremely likely).
97 c := shuffle(43)
98 diff := false
99 for i := 0; i < gridSize; i++ {
100 if a[i].face != c[i].face {
101 diff = true
102 break
103 }
104 }
105 uassert.True(t, diff, "different seeds should differ")
106
107 // Each face appears exactly twice.
108 counts := map[int]int{}
109 for i := 0; i < gridSize; i++ {
110 counts[a[i].face]++
111 }
112 for f := 0; f < numPairs; f++ {
113 uassert.Equal(t, 2, counts[f])
114 }
115
116 // Render on a fresh game shows hidden tiles and zero progress.
117 addr := testutils.TestAddress("viewer")
118 testing.SetRealm(testing.NewUserRealm(addr))
119 NewGame(cross(cur))
120 out := Render("")
121 uassert.True(t, len(out) > 0, "render non-empty")
122 uassert.True(t, containsSub(out, "Memory Match"), "has title")
123 uassert.True(t, containsSub(out, "❓"), "shows hidden tiles")
124 uassert.True(t, containsSub(out, "0 / 8"), "zero pairs matched")
125}
126
127func containsSub(s, sub string) bool {
128 for i := 0; i+len(sub) <= len(s); i++ {
129 if s[i:i+len(sub)] == sub {
130 return true
131 }
132 }
133 return false
134}