每周Succinct都会发$10 credit用于游戏,而其中最快消费掉这些credit的方式是用于Coin Craze的游戏

这游戏每局1分钟,得分的方式是选择靠近的数字加起来等于10。得分超过60就会获得最高的6个星星(消费$0.6),也就是玩个16分钟就可以消费完$10 credit

这里分享一下这个游戏的自动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
// Script to automate Coin Craze game
// To use: Copy and paste into browser console at https://testnet.succinct.xyz/coin

function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

async function solveCoinCraze() {
// Function to simulate mouse events
function simulateMouseEvent(element, x, y, type) {
const rect = element.getBoundingClientRect();
const event = new MouseEvent(type, {
bubbles: true,
cancelable: true,
view: window,
clientX: rect.left + x,
clientY: rect.top + y,
screenX: rect.left + x,
screenY: rect.top + y,
buttons: type === 'mouseup' ? 0 : 1,
button: 0,
relatedTarget: null,
});
element.dispatchEvent(event);
}

// Function to get coin value
function getCoinValue(coin) {
return parseInt(coin.textContent);
}

// Function to check if coins are in a straight line
function areInStraightLine(coins, indices) {
if (indices.length < 2) return true;

const rects = indices.map(i => coins[i].getBoundingClientRect());
const centers = rects.map(rect => ({
x: rect.left + rect.width/2,
y: rect.top + rect.height/2
}));

// Check if all coins are horizontally aligned (same y)
const isHorizontal = centers.every(c => Math.abs(c.y - centers[0].y) < 15);
if (isHorizontal) {
// Sort by x coordinate
const sortedIndices = [...indices].sort((a, b) => {
const rectA = coins[a].getBoundingClientRect();
const rectB = coins[b].getBoundingClientRect();
return (rectA.left + rectA.width/2) - (rectB.left + rectB.width/2);
});

// Check if coins are consecutive
for (let i = 1; i < sortedIndices.length; i++) {
const rect1 = coins[sortedIndices[i-1]].getBoundingClientRect();
const rect2 = coins[sortedIndices[i]].getBoundingClientRect();
const distance = (rect2.left + rect2.width/2) - (rect1.left + rect1.width/2);
if (distance > rect1.width * 2) return false;
}
return true;
}

// Check if all coins are vertically aligned (same x)
const isVertical = centers.every(c => Math.abs(c.x - centers[0].x) < 15);
if (isVertical) {
// Sort by y coordinate
const sortedIndices = [...indices].sort((a, b) => {
const rectA = coins[a].getBoundingClientRect();
const rectB = coins[b].getBoundingClientRect();
return (rectA.top + rectA.height/2) - (rectB.top + rectB.height/2);
});

// Check if coins are consecutive
for (let i = 1; i < sortedIndices.length; i++) {
const rect1 = coins[sortedIndices[i-1]].getBoundingClientRect();
const rect2 = coins[sortedIndices[i]].getBoundingClientRect();
const distance = (rect2.top + rect2.height/2) - (rect1.top + rect1.height/2);
if (distance > rect1.height * 2) return false;
}
return true;
}

return false;
}

// Function to find sequence of adjacent coins that sum to 10
function findCoinCombination(coins) {
const startTime = Date.now();

// Try all possible combinations
for (let i = 0; i < coins.length; i++) {
const value1 = getCoinValue(coins[i]);
if (value1 > 10) continue;

// Get nearby coins for efficiency
const rect1 = coins[i].getBoundingClientRect();
const nearby = [];
for (let j = 0; j < coins.length; j++) {
if (i === j) continue;
const rect2 = coins[j].getBoundingClientRect();
const dx = (rect2.left + rect2.width/2) - (rect1.left + rect1.width/2);
const dy = (rect2.top + rect2.height/2) - (rect1.top + rect1.height/2);
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < rect1.width * 2.5) {
nearby.push(j);
}
}

// Try two-coin combinations with nearby coins
for (const j of nearby) {
const value2 = getCoinValue(coins[j]);
const sequence = [i, j];

if (value1 + value2 === 10 && areInStraightLine(coins, sequence)) {
return sequence;
}

// Try three-coin combinations with another nearby coin
if (value1 + value2 < 10) {
for (const k of nearby) {
if (k === i || k === j) continue;
const value3 = getCoinValue(coins[k]);

if (value1 + value2 + value3 === 10) {
const sequence3 = [i, j, k];
if (areInStraightLine(coins, sequence3)) {
return sequence3;
}
}
}
}
}

// Check if we're taking too long
if (Date.now() - startTime > 50) {
return null;
}
}

return null;
}

// Function to handle game over sequence
async function handleGameOver() {
// Check for "Game Over!" text
const gameOverText = document.evaluate(
'/html/body/div[1]/main/div[1]/div/div/div[2]/div/div/div[2]/div/div/h2',
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
).singleNodeValue;

if (gameOverText && gameOverText.textContent.includes('Game Over!')) {
console.log('Game Over detected, handling end sequence...');

// Click "Confirm Score"
const confirmScoreBtn = document.evaluate(
'/html/body/div[1]/main/div[1]/div/div/div[2]/div/div/div[2]/div/div/div[2]/button[1]',
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
).singleNodeValue;

if (confirmScoreBtn) {
confirmScoreBtn.click();
await sleep(1000); // Wait for confirmation dialog

// Click "Confirm"
const confirmBtn = document.evaluate(
'/html/body/div[1]/main/div[1]/div/div/div[2]/div/div/div[3]/div/div/button[2]',
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
).singleNodeValue;

if (confirmBtn) {
confirmBtn.click();
await sleep(1000); // Wait for play again button

// Click "Play Again!"
const playAgainBtn = document.evaluate(
'/html/body/div[1]/main/div[1]/div/div/div[2]/div/div/div[2]/div/div/div[2]/button[1]',
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
).singleNodeValue;

if (playAgainBtn) {
playAgainBtn.click();
await sleep(1000); // Wait for new game to start
return true;
}
}
}
}
return false;
}

while (true) {
try {
// Check for game over first
if (await handleGameOver()) {
console.log('Starting new game...');
continue;
}

// Get all coins using the specific selector
const gameBoard = document.querySelector('body > div.fixed.inset-0.flex.flex-col.overflow-hidden.bg-cover.bg-center > main');
if (!gameBoard) {
await sleep(100);
continue;
}

// Try different selectors for the coin container
let container = gameBoard.querySelector('.game-board');
if (!container) {
container = gameBoard.querySelector('[class*="aspect-square"]');
}
if (!container) {
container = gameBoard.querySelector('div[class*="relative"] > div > div');
}

if (!container) {
await sleep(100);
continue;
}

// Get all button elements within the container
const coins = Array.from(container.querySelectorAll('button'));
if (coins.length === 0) {
await sleep(100);
continue;
}

// Remove pointer-events-none class from parent elements
let parent = container;
while (parent) {
if (parent.classList && parent.classList.contains('pointer-events-none')) {
parent.classList.remove('pointer-events-none');
}
parent = parent.parentElement;
}

// Find combination that sums to 10
const combination = findCoinCombination(coins);
if (!combination) {
await sleep(100);
continue;
}

// Log the selected coins and their sum
const values = combination.map(i => getCoinValue(coins[i]));
const sum = values.reduce((a, b) => a + b, 0);
console.log(`Selected ${values.length} coins:`, values.join(' + '), '=', sum);

// Select the coins
const firstCoin = coins[combination[0]];
simulateMouseEvent(firstCoin, 20, 20, 'mousedown');

// Only move to the last coin directly
const lastCoin = coins[combination[combination.length - 1]];
simulateMouseEvent(lastCoin, 20, 20, 'mousemove');
simulateMouseEvent(lastCoin, 20, 20, 'mouseup');

// Give the game a short break
await sleep(100);
} catch (error) {
console.error('Error:', error);
await sleep(100);
}
// Add a small break between iterations to prevent freezing
await new Promise(resolve => setTimeout(resolve, 0));
}
}

// Start the solver
solveCoinCraze();

这脚本并不是完美,只能查看4个位置之内的数字之和,但是已经足够获得60积分

image.png