차이
문서의 선택한 두 판 사이의 차이를 보여줍니다.
양쪽 이전 판 이전 판 | |||
dice [2025/07/29 19:48] – 제거됨 - 바깥 편집 (Unknown date) 127.0.0.1 | dice [2025/07/29 19:48] (현재) – ↷ 문서 이름이 주사위에서 dice(으)로 바뀌었습니다 dndkr | ||
---|---|---|---|
줄 1: | 줄 1: | ||
+ | ====== 주사위 굴리기! ====== | ||
+ | < | ||
+ | <div class=" | ||
+ | < | ||
+ | .dice-simulator { | ||
+ | font-family: | ||
+ | max-width: 900px; | ||
+ | margin: 20px auto; | ||
+ | padding: 20px; | ||
+ | border: 1px solid #ddd; | ||
+ | border-radius: | ||
+ | background-color: | ||
+ | box-shadow: 0 2px 4px rgba(0, | ||
+ | } | ||
+ | .dice-container { | ||
+ | display: flex; | ||
+ | justify-content: | ||
+ | gap: 20px; /* 버튼 사이 간격 확장 */ | ||
+ | margin-bottom: | ||
+ | flex-wrap: wrap; | ||
+ | } | ||
+ | .dice-button { | ||
+ | width: 90px; /* 버튼 너비 확장 */ | ||
+ | height: 90px; /* 버튼 높이 확장 */ | ||
+ | background-color: | ||
+ | color: white; | ||
+ | border: none; | ||
+ | border-radius: | ||
+ | font-size: 32px; /* 버튼 텍스트 크기 확장 */ | ||
+ | font-weight: | ||
+ | cursor: pointer; | ||
+ | transition: background-color 0.2s ease, transform 0.1s ease; | ||
+ | box-shadow: 0 5px 8px rgba(0, | ||
+ | display: flex; | ||
+ | justify-content: | ||
+ | align-items: | ||
+ | } | ||
+ | .dice-button: | ||
+ | background-color: | ||
+ | transform: translateY(-3px); | ||
+ | } | ||
+ | .dice-button: | ||
+ | background-color: | ||
+ | transform: translateY(0); | ||
+ | } | ||
+ | .result-display { | ||
+ | background-color: | ||
+ | padding: 15px 20px; /* 패딩 확장 */ | ||
+ | border-radius: | ||
+ | text-align: center; | ||
+ | margin-bottom: | ||
+ | min-height: 70px; /* 최소 높이 확장 */ | ||
+ | display: flex; | ||
+ | flex-direction: | ||
+ | align-items: | ||
+ | justify-content: | ||
+ | color: #333; | ||
+ | font-weight: | ||
+ | } | ||
+ | .main-result-value { | ||
+ | font-size: 60px; /* 결과값 숫자 훨씬 더 크게 확장 */ | ||
+ | line-height: | ||
+ | margin-bottom: | ||
+ | } | ||
+ | .result-expression-text { | ||
+ | font-size: 18px; /* 수식 텍스트도 약간 확장 */ | ||
+ | font-weight: | ||
+ | color: #555; | ||
+ | } | ||
+ | .expression-section { | ||
+ | display: flex; | ||
+ | flex-direction: | ||
+ | gap: 10px; | ||
+ | margin-bottom: | ||
+ | } | ||
+ | .expression-input { | ||
+ | padding: 12px; /* 입력창 패딩 확장 */ | ||
+ | border: 1px solid #ccc; | ||
+ | border-radius: | ||
+ | font-size: 18px; /* 입력창 글씨 크기 확장 */ | ||
+ | width: calc(100% - 24px); /* 패딩 고려하여 너비 조정 */ | ||
+ | } | ||
+ | .expression-button { | ||
+ | padding: 12px 18px; /* 버튼 패딩 확장 */ | ||
+ | background-color: | ||
+ | color: white; | ||
+ | border: none; | ||
+ | border-radius: | ||
+ | cursor: pointer; | ||
+ | font-size: 18px; /* 버튼 글씨 크기 확장 */ | ||
+ | transition: background-color 0.2s ease; | ||
+ | } | ||
+ | .expression-button: | ||
+ | background-color: | ||
+ | } | ||
+ | .error-message { | ||
+ | color: #d32f2f; | ||
+ | font-size: 15px; /* 오류 메시지 글씨 크기 확장 */ | ||
+ | margin-top: 5px; | ||
+ | } | ||
+ | .history-section { | ||
+ | margin-top: 25px; /* 내역 섹션 상단 마진 확장 */ | ||
+ | border-top: 1px solid #eee; | ||
+ | padding-top: | ||
+ | } | ||
+ | .history-list { | ||
+ | list-style: none; | ||
+ | padding: 0; | ||
+ | margin: 0; | ||
+ | max-height: 250px; /* 내역 목록 최대 높이 확장 */ | ||
+ | overflow-y: auto; | ||
+ | border: 1px solid #eee; | ||
+ | border-radius: | ||
+ | background-color: | ||
+ | } | ||
+ | .history-list li { | ||
+ | padding: 10px 12px; /* 내역 항목 패딩 확장 */ | ||
+ | border-bottom: | ||
+ | font-size: 15px; /* 내역 항목 글씨 크기 확장 */ | ||
+ | color: #555; | ||
+ | } | ||
+ | .history-list li: | ||
+ | border-bottom: | ||
+ | } | ||
+ | </ | ||
+ | <div class=" | ||
+ | <button class=" | ||
+ | <button class=" | ||
+ | <button class=" | ||
+ | <button class=" | ||
+ | <button class=" | ||
+ | <button class=" | ||
+ | <button class=" | ||
+ | </ | ||
+ | |||
+ | <div class=" | ||
+ | <div class=" | ||
+ | <div class=" | ||
+ | </ | ||
+ | |||
+ | <hr> | ||
+ | |||
+ | <div class=" | ||
+ | < | ||
+ | <input type=" | ||
+ | <button id=" | ||
+ | <div id=" | ||
+ | </ | ||
+ | |||
+ | <div class=" | ||
+ | < | ||
+ | <ul id=" | ||
+ | </ul> | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | document.addEventListener(' | ||
+ | const diceButtons = document.querySelectorAll(' | ||
+ | const mainResultValue = document.getElementById(' | ||
+ | const resultExpressionText = document.getElementById(' | ||
+ | const expressionInput = document.getElementById(' | ||
+ | const calculateExpressionButton = document.getElementById(' | ||
+ | const expressionError = document.getElementById(' | ||
+ | const rollHistoryList = document.getElementById(' | ||
+ | |||
+ | const MAX_HISTORY_ITEMS = 20; | ||
+ | let history = []; | ||
+ | |||
+ | // 초기 화면 설정 | ||
+ | mainResultValue.textContent = ''; | ||
+ | resultExpressionText.textContent = ' | ||
+ | |||
+ | function formatKST(date) { | ||
+ | const year = date.getFullYear(); | ||
+ | const month = String(date.getMonth() + 1).padStart(2, | ||
+ | const day = String(date.getDate()).padStart(2, | ||
+ | const hours = String(date.getHours()).padStart(2, | ||
+ | const minutes = String(date.getMinutes()).padStart(2, | ||
+ | const seconds = String(date.getSeconds()).padStart(2, | ||
+ | return `${year}년 ${month}월 ${day}일 ${hours}시 ${minutes}분 ${seconds}초`; | ||
+ | } | ||
+ | |||
+ | function updateHistoryDisplay() { | ||
+ | rollHistoryList.innerHTML = ''; | ||
+ | history.forEach(item => { | ||
+ | const listItem = document.createElement(' | ||
+ | listItem.textContent = item; | ||
+ | rollHistoryList.prepend(listItem); | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | function addRollToHistory(resultText) { | ||
+ | const now = new Date(); | ||
+ | const formattedDateTime = formatKST(now); | ||
+ | history.push(`${resultText} (${formattedDateTime})`); | ||
+ | if (history.length > MAX_HISTORY_ITEMS) { | ||
+ | history.shift(); | ||
+ | } | ||
+ | updateHistoryDisplay(); | ||
+ | } | ||
+ | |||
+ | // 개별 주사위 굴리기 기능 | ||
+ | diceButtons.forEach(button => { | ||
+ | button.addEventListener(' | ||
+ | const sides = parseInt(button.dataset.sides); | ||
+ | const result = Math.floor(Math.random() * sides) + 1; | ||
+ | | ||
+ | mainResultValue.textContent = result; | ||
+ | resultExpressionText.textContent = `d${sides}`; | ||
+ | expressionError.textContent = ''; | ||
+ | | ||
+ | addRollToHistory(`${result}(d${sides})`); | ||
+ | }); | ||
+ | }); | ||
+ | |||
+ | // 수식 계산 기능 | ||
+ | calculateExpressionButton.addEventListener(' | ||
+ | const expression = expressionInput.value.trim().toLowerCase(); | ||
+ | expressionError.textContent = ''; | ||
+ | |||
+ | if (!expression) { | ||
+ | mainResultValue.textContent = ''; | ||
+ | resultExpressionText.textContent = ' | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | try { | ||
+ | const evaluatedResult = evaluateDiceExpression(expression); | ||
+ | const finalValue = evaluatedResult.split(' | ||
+ | const fullExpressionWithRolls = evaluatedResult; | ||
+ | |||
+ | mainResultValue.textContent = finalValue; | ||
+ | resultExpressionText.textContent = expression; | ||
+ | | ||
+ | addRollToHistory(`${finalValue}(${expression})`); | ||
+ | } catch (e) { | ||
+ | expressionError.textContent = e.message; | ||
+ | mainResultValue.textContent = ' | ||
+ | resultExpressionText.textContent = ' | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | // 주사위 수식 파싱 및 계산 함수 | ||
+ | function evaluateDiceExpression(expression) { | ||
+ | const diceRegex = / | ||
+ | let calculatedExpression = expression; | ||
+ | const rollDetails = []; | ||
+ | |||
+ | calculatedExpression = calculatedExpression.replace(diceRegex, | ||
+ | const numDice = parseInt(numDiceStr); | ||
+ | const numSides = parseInt(numSidesStr); | ||
+ | |||
+ | if (numSides <= 0) { | ||
+ | throw new Error(`주사위 면 수는 0보다 커야 합니다. (${match})`); | ||
+ | } | ||
+ | |||
+ | let sumOfRolls = 0; | ||
+ | let currentRolls = []; | ||
+ | for (let i = 0; i < numDice; i++) { | ||
+ | const roll = Math.floor(Math.random() * numSides) + 1; | ||
+ | sumOfRolls += roll; | ||
+ | currentRolls.push(roll); | ||
+ | } | ||
+ | rollDetails.push(`${numDice}d${numSides} (${currentRolls.join(', | ||
+ | return sumOfRolls; | ||
+ | }); | ||
+ | |||
+ | const singleDiceRegex = / | ||
+ | calculatedExpression = calculatedExpression.replace(singleDiceRegex, | ||
+ | const numSides = parseInt(numSidesStr); | ||
+ | |||
+ | if (numSides <= 0) { | ||
+ | throw new Error(`주사위 면 수는 0보다 커야 합니다. (${match})`); | ||
+ | } | ||
+ | |||
+ | const roll = Math.floor(Math.random() * numSides) + 1; | ||
+ | rollDetails.push(`d${numSides} (${roll})`); | ||
+ | return roll; | ||
+ | }); | ||
+ | |||
+ | let finalResult; | ||
+ | try { | ||
+ | if (/ | ||
+ | throw new Error(' | ||
+ | } | ||
+ | finalResult = eval(calculatedExpression); | ||
+ | } catch (e) { | ||
+ | throw new Error(' | ||
+ | } | ||
+ | |||
+ | if (rollDetails.length > 0) { | ||
+ | return `${finalResult} (굴림: ${rollDetails.join(', | ||
+ | } else { | ||
+ | return finalResult.toString(); | ||
+ | } | ||
+ | } | ||
+ | }); | ||
+ | </ | ||
+ | </ |