Skip to content

Instantly share code, notes, and snippets.

@YangSeungWon
Last active February 7, 2025 06:05
Show Gist options
  • Save YangSeungWon/4d2f9504f36609d2b9bf916c3647482e to your computer and use it in GitHub Desktop.
Save YangSeungWon/4d2f9504f36609d2b9bf916c3647482e to your computer and use it in GitHub Desktop.
Fruit box helper - 사과게임 도움 스크립트
(function () {
console.log("[Fruit Box Helper] 스크립트 시작");
let lastMapState = '';
let gridWidth = null;
let gridHeight = null;
let gridMinX = null;
let gridMinY = null;
// 게임 객체 감시 함수
function waitForGame(callback) {
const interval = 200; // 200ms마다 체크
setInterval(() => {
if (window.exportRoot?.mm?.mg) {
callback(window.exportRoot.mm.mg);
}
}, interval);
}
// 격자 크기 초기화
function initializeGrid(mg) {
let minX = Infinity, maxX = -Infinity;
let minY = Infinity, maxY = -Infinity;
// 범위 찾기
for (const prop in mg) {
if (mg.hasOwnProperty(prop) && prop.indexOf("mk") === 0) {
const apple = mg[prop];
if (apple && typeof apple.nu === 'number') {
minX = Math.min(minX, apple.x);
maxX = Math.max(maxX, apple.x);
minY = Math.min(minY, apple.y);
maxY = Math.max(maxY, apple.y);
}
}
}
gridWidth = (maxX - minX) / (17 - 1);
gridHeight = (maxY - minY) / (10 - 1);
gridMinX = minX;
gridMinY = minY;
console.log("격자 크기 초기화 완료");
}
// 사과 데이터 추출 함수
function extractMapData(mg) {
const apples = [];
// 격자 크기가 아직 계산되지 않았다면 초기화
if (gridWidth === null) {
initializeGrid(mg);
}
// 2D 배열 초기화 (10x17 크기)
const map = Array(10).fill().map(() => Array(17).fill(null));
// 사과 데이터 채우기
for (const prop in mg) {
if (mg.hasOwnProperty(prop) && prop.indexOf("mk") === 0) {
const apple = mg[prop];
if (apple && typeof apple.nu === 'number' && !apple.flDroped) {
const col = Math.floor((apple.x - gridMinX) / gridWidth);
const row = Math.floor((apple.y - gridMinY) / gridHeight);
if (row >= 0 && row < 10 && col >= 0 && col < 17) {
map[row][col] = apple.nu;
apples.push({ row, col, num: apple.nu });
}
}
}
}
return { map, apples };
}
function findAllCombinations(apples) {
const combinations = [];
for (let i = 0; i < apples.length; i++) {
for (let j = i + 1; j < apples.length; j++) {
const apple1 = apples[i];
const apple2 = apples[j];
// 사각형 영역 계산
const minRow = Math.min(apple1.row, apple2.row);
const maxRow = Math.max(apple1.row, apple2.row);
const minCol = Math.min(apple1.col, apple2.col);
const maxCol = Math.max(apple1.col, apple2.col);
// 영역 내 사과들 찾기
const applesInRect = apples.filter(a =>
a.row >= minRow && a.row <= maxRow &&
a.col >= minCol && a.col <= maxCol
);
const sum = applesInRect.reduce((acc, a) => acc + a.num, 0);
if (sum === 10) {
const maxNum = Math.max(...applesInRect.map(a => a.num));
// 적은 개수의 사과 우선, 같은 개수면 큰 숫자 우선. 1과 2는 아끼기
let score = 1000
score -= applesInRect.length * 100
score -= applesInRect.filter(a => a.num === 1).length * 50
score -= applesInRect.filter(a => a.num === 2).length * 30
score -= Math.abs(5 - minRow) * 5
score -= Math.abs(8 - minCol) * 5
score -= Math.abs(5 - maxRow) * 5
score -= Math.abs(8 - maxCol) * 5
score += (maxRow - minRow) * 20
score += (maxCol - minCol) * 20
score += maxNum
combinations.push({
apples: applesInRect,
score: score
});
}
}
}
// 점수순으로 정렬
combinations.sort((a, b) => b.score - a.score);
return combinations;
}
function createController() {
removeController();
const controller = document.createElement('div');
controller.id = 'fruit-box-controller';
const canvas = document.querySelector('canvas');
const rect = canvas.getBoundingClientRect();
Object.assign(controller.style, {
position: 'absolute',
left: `${rect.left}px`,
top: `${rect.bottom + 10}px`,
padding: '10px',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderRadius: '5px',
color: 'white',
fontFamily: 'Arial',
fontSize: '14px',
display: 'flex',
alignItems: 'center',
gap: '10px',
zIndex: '10000'
});
const label = document.createElement('label');
label.textContent = '표시할 조합 수: ';
const slider = document.createElement('input');
Object.assign(slider, {
type: 'range',
min: '1',
max: '10',
value: maxDisplayCount,
style: 'width: 100px'
});
const valueDisplay = document.createElement('span');
valueDisplay.textContent = maxDisplayCount;
slider.addEventListener('input', (e) => {
maxDisplayCount = parseInt(e.target.value);
valueDisplay.textContent = maxDisplayCount;
// 강제로 lastMapState를 초기화하여 다시 렌더링되도록 함
lastMapState = '';
if (lastCombinations) {
createOverlays(lastCombinations);
// 콘솔 출력도 업데이트
console.clear();
console.log('=== Fruit Box 맵 ===');
console.log(mapToString(lastMap, lastCombinations));
console.log('\n=== 발견된 조합들 ===');
lastCombinations.slice(0, maxDisplayCount).forEach((combo, index) => {
const maxNum = Math.max(...combo.apples.map(c => c.num));
console.log(`${index + 1}. ${combo.apples.map(c => c.num).join(' + ')} = 10 (최대 숫자: ${maxNum})`);
});
}
});
controller.appendChild(label);
controller.appendChild(slider);
controller.appendChild(valueDisplay);
document.body.appendChild(controller);
}
function removeController() {
const existing = document.getElementById('fruit-box-controller');
if (existing) {
existing.remove();
}
}
// 전역 변수 추가
let maxDisplayCount = 3; // 기본값
let lastMap = null;
let lastCombinations = null;
function createOverlays(combinations) {
removeOverlays();
// maxDisplayCount만큼만 표시
combinations.slice(0, maxDisplayCount).forEach((combo, index) => {
const overlay = document.createElement('div');
overlay.id = `fruit-box-overlay-${index}`;
const minRow = Math.min(...combo.apples.map(a => a.row));
const maxRow = Math.max(...combo.apples.map(a => a.row));
const minCol = Math.min(...combo.apples.map(a => a.col));
const maxCol = Math.max(...combo.apples.map(a => a.col));
const canvas = document.querySelector('canvas');
const rect = canvas.getBoundingClientRect();
const canvasPaddingLeft = 67;
const canvasPaddingTop = 73;
const canvasPaddingRight = 88;
const canvasPaddingBottom = 68;
const cellWidth = (rect.width - canvasPaddingLeft - canvasPaddingRight) / 17;
const cellHeight = (rect.height - canvasPaddingTop - canvasPaddingBottom) / 10;
const isBest = index === 0;
Object.assign(overlay.style, {
position: 'absolute',
left: `${rect.left + minCol * cellWidth + canvasPaddingLeft + 4}px`,
top: `${rect.top + minRow * cellHeight + canvasPaddingTop + 4}px`,
width: `${(maxCol - minCol + 1) * cellWidth - 8}px`,
height: `${(maxRow - minRow + 1) * cellHeight - 8}px`,
border: `3px solid ${isBest ? 'black' : '#666666'}`,
backgroundColor: isBest ? 'rgba(255, 255, 0, 0.2)' : 'rgba(128, 128, 128, 0.2)',
pointerEvents: 'none',
zIndex: isBest ? '9999' : '9998',
boxSizing: 'border-box'
});
document.body.appendChild(overlay);
});
}
function removeOverlays() {
const overlays = document.querySelectorAll('[id^="fruit-box-overlay-"]');
overlays.forEach(overlay => overlay.remove());
}
function mapToString(map, combinations) {
return map.map((row, rowIdx) => {
return row.map((cell, colIdx) => {
if (cell === null) return ' · ';
const isHighlighted = combinations[0]?.apples.some(h => h.row === rowIdx && h.col === colIdx);
if (isHighlighted) {
return `\x1b[1m\x1b[33m[${cell}]\x1b[0m`;
}
return ` ${cell} `;
}).join('');
}).join('\n');
}
function renderMap(map, combinations) {
lastMap = map;
lastCombinations = combinations;
const mapStr = mapToString(map, combinations);
const fullDisplay = mapStr;
if (fullDisplay !== lastMapState) {
console.clear();
console.log('=== Fruit Box 맵 ===');
console.log(fullDisplay);
if (combinations.length > 0) {
console.log('\n=== 발견된 조합들 ===');
combinations.slice(0, maxDisplayCount).forEach((combo, index) => {
const maxNum = Math.max(...combo.apples.map(c => c.num));
console.log(`${index + 1}. ${combo.apples.map(c => c.num).join(' + ')} = 10 (최대 숫자: ${maxNum})`);
});
createOverlays(combinations);
createController();
} else {
removeOverlays();
removeController();
}
lastMapState = fullDisplay;
}
}
// 메인 실행 로직
waitForGame((mg) => {
const { map, apples } = extractMapData(mg);
const combinations = findAllCombinations(apples);
renderMap(map, combinations);
});
})();
@beginner3579
Copy link

이거 써보고싶어서 가입했는데요.. 할 줄을 아예 모르겠어요.. 그냥 다운받아서 fruit-box-helper 실행하니까 "4행7번째줄 ";"가 필요합니다."라고 오류메세지 나오고 그래서 찾아보다가 뒤지다가 크롬 확장프로그램 Tampermonkey 받아서 여기다가 스크립트 입력하라고 해서 했는데도 안되더라구요. 이거 혹시 어떻게 해야 쓸 수 있나요 ㅠ? 바보라서 죄송합니다

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment