개발
유희왕 초동 확률 계산기 제작
오랜만에 덱 연구를 좀 하다가 초동확률을 계산해보고 싶어서 초동확률 계산기를 찾으러 가보았다.
예전엔 유기오.파티라는 도메인에서 초동확률 계산기를 사용했었는데, 지금 해당 사이트에 뭔 문제가 생겼는지 사이트가 열리지 않게 되었다.
그이후에는 여러 확률 계산기 사이트를 돌아다니면서 몇개 보았지만 그냥 직관적으로 가볍게 숫자 몇개로 특정 패조합이 뜰 확률을 계산하는 사이트가 없어서 답답했다.
그래서 그냥 직접 만들면 되지 않을까 해서 아래와 같이 초동확률 계산기 페이지를 만들어 보았다.


유희왕 초동확률 계산기
유희왕 덱 구성에 필요한 초등확률을 계산하는 기능을 제공합니다
https://erulabo.com/yugioh-probability-simulator
위 링크에서 기능을 바로 사용해볼 수 있다.
사용법은 기존의 유기오파티의 초동확률 계산기를 사용해보았으면 쉽게 사용할 수 있고, 해당 사이트를 사용할때 번거로웠던 부분도 조금 보완해서 적용해보았다.
먼저 Step 1에서 덱과 패의 매수를 설정하고 Step 2에서 내가 패로 잡기 원하는 카드 분류와 매수를 입력하면 바로 아래에 조합에 따른 확률 계산 결과가 나오게 된다.
통상적으로 아래 경우처럼 원핸드 계산이나 원핸드+케어 카드 계산이 의도한대로 잘 돌아간다.


기존 유기오 파티에서는 무한이 패 구성을 늘릴 수 있긴한데 해당기능은 너무 복잡하고 쓸일이없어서 고정적으로 최대 3핸드 기준의 계산결과만 보여줄 수 있게 해당 기능을 구현했다.
특히나 확률을 구하는데있어 원래는 콤비네이션을 전부 고려한 아래 계산식을 구현해야한다.

하지만 상식적으로 이런건 가볍게 온라인상에서 구현할만한건 아니기 때문에 나는 10만회의 데이터 샘플링 결과를 이용한 확률 결과를 구현하는 방식으로 만들어 보았다.
function calculateProbabilityBySampling() {
const deckSize = parseInt(document.getElementById('inputDeckSize').value) || 40;
const handSize = parseInt(document.getElementById('inputHandSize').value) || 5;
const rows = document.querySelectorAll('.table_simulator tbody tr');
let groupData = [];
rows.forEach(row => {
const nameInput = row.querySelector('td:nth-child(1) input');
if (!nameInput || nameInput.value.trim() === '' || nameInput.value.trim() === '나머지 카드') return;
const count = parseInt(row.querySelector('td:nth-child(2) input').value) || 0;
const min = parseInt(row.querySelector('td:nth-child(3) input').value) || 0;
const max = parseInt(row.querySelector('td:nth-child(4) input').value) || 0;
if (count > 0 && min <= max && min > 0) {
groupData.push({ count, min, max });
}
});
if (groupData.length === 0) {
document.getElementById('result').innerText = '0%';
return;
}
const iterations = 100000;
let successCount = 0;
for (let i = 0; i < iterations; i++) {
let deck = [];
let groupId = 0;
groupData.forEach(group => {
for (let j = 0; j < group.count; j++) {
deck.push(groupId);
}
groupId++;
});
const used = groupData.reduce((acc, g) => acc + g.count, 0);
const miscCount = deckSize - used;
for (let j = 0; j < miscCount; j++) {
deck.push('misc');
}
shuffle(deck);
const hand = deck.slice(0, handSize);
let hit = new Array(groupData.length).fill(0);
hand.forEach(card => {
if (card !== 'misc') hit[card]++;
});
const isValid = groupData.every((group, idx) => {
return hit[idx] >= group.min && hit[idx] <= group.max;
});
if (isValid) successCount++;
}
const probability = (successCount / iterations) * 100;
document.getElementById('result').innerText = probability.toFixed(1) + '%';
}
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
Copy
쉽게말해 내가 주어진 핸드 조합에 맞는 카드군을 포함한 임의의 덱을 만들고 랜덤으로 직접 뽑아보고 해당되는 결과가 있는지 체크하는 방식이다.
실제로 100,000회 샘플링시 오차범위가 ±0.31% 여서 나름 빠르게 확률을 구하는데는 문제가 없다고도 확인이 된 부분이다.
이제 여기서 한발 더 나가면 아래 사이트와 같이 2핸드, 3핸드 패조합을 전부 입력후 경우의 수를 전체적으로 계산한다면 그 경우의수로 확률을 계산하는 방법이 있긴한데, 이 방식은 덱을 전체적으로 입력해줘야 하며 조합 또한 일일히 추가해줘야해서 온라인에서 가볍게 사용하긴 힘든 기능이라고 판단된다.
遊戯王パターン計算ツール
遊戯王カードのデッキとカードの組み合わせを指定して組み合わせにマッチする手札になる確率を計算できるツールです
https://yugioh-probability-tool.netlify.app
뭐 결국 한번 만들어보고 싶었던걸 만들어봤다! 라는 느낌으로 제작해본 내용이다.
#JavaScript
0
개의 댓글
개발 카테고리의 다른 글

03/20
라라벨에서 RSS / ATOM 피드 생성기 구현하기
진짜 오랜만에 개발글 하나 써봅니다. 오늘 소개할 내용은 대부분의 블로그에서 RSS 피드를 제공하는데, 그 RSS 피드를 직접 만...

03/19
프록시 서버 환경에서 HTTPS 요청시 잘못된 사이트가 나오는 문제 해결
워낙 특수한 상황인 경우다보니 검색해도 잘 나오지 않아 삽질하다가 해결한 기록을 남겨보고자한다. 프록시 서버에서 HTTPS 요...

02/27
JSON 뷰어 구현 노트
요즘 작업에 필요한 유틸리티 사이트들의 기능을 직접 내 블로그에 올려두는 작업을 하고있다.서버단 자원사용하는것도아니고 자...