기능구현
- 연산 가능한 기본 계산기 구현
참여소감
- 구글에 '계산기'라고 치면 기본 css랑 html 구조가 나와서 편했다.
- js 는 https://velog.io/@whwodgns 이 블로그를 참고했는데 기본틀을 가져와서 제약사항에서 걸리는 부분만 수정했다
- spring으로 만들었으면 더 쉬웠을것같은데 내일배움캠프 node과정 수료중이라 js만 사용했더니 코드가 엄청 길어지고 복잡해졌다.
다른사람들은 어떻게 만들었을지 궁금하다
고육데 이벤트 페이지 링크
https://hanghaeplus-coyukdae.oopy.io
개발언어
제약사항
•세뱃돈의 총 금액은 항상 0 이상이며, 디스플레이는 0으로 시작합니다.
•입력에서는 연산자가 숫자 사이에만 나타납니다.
•연산자가 주어지면, 해당 연산자를 사용하여 앞뒤 숫자를 계산하세요.
•연산 결과는 소수점 이하를 버림하여 정수로 표시합니다.
•세뱃돈은 한국 원화(KRW)로 주어지며, 최대 10자리 숫자까지만 입력됩니다.
•10자리 숫자를 넘어가는 결과값은 Infinity 로 표기됩니다.
•더하기, 곱하기, 나누기 다음 숫자를 입력하지 않고 ‘=’ 를 입력할 경우 alert을 띄워줍니다.
•실수로 입력한 것을 모두 지울 수 있는 ‘AC’, 마지막에 입력한 값만 지울 수 있는 ‘C’ 버튼이 있어야 합니다.
•0 나누기 0 과 같은 예외 결과값은 ‘숫자 아님’ 으로 표시됩니다.
•연산자를 연달아 선택할 경우 마지막에 선택한 연산자가 적용되어야 합니다.
html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>세뱃돈계산기</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="calculator">
<div class="display">
<div>0</div>
</div>
<div class="button_container">
<div class="button_content">
<button class="button_reset">CE</button>
<button class="button_reset">C</button>
</div>
<div class="button_content">
<button class="button_number">7</button>
<button class="button_number">8</button>
<button class="button_number">9</button>
<button class="button_operator">-</button>
</div>
<div class="button_content">
<button class="button_number">4</button>
<button class="button_number">5</button>
<button class="button_number">6</button>
<button class="button_operator">÷</button>
</div>
<div class="button_content">
<button class="button_number">1</button>
<button class="button_number">2</button>
<button class="button_number">3</button>
<button class="button_operator">×</button>
</div>
<div class="button_content">
<button class="button_number">0</button>
<button class="button_number">.</button>
<button class="calculate">=</button>
<button class="button_operator">+</button>
</div>
</div>
</div>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="index.js" type="module"></script>
</html>
css
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
@font-face {
font-family: 'LAB디지털';
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_20-07@1.0/LAB디지털.woff') format('woff');
font-weight: normal;
font-style: normal;
}
.container {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.calculator {
border: 3px solid rgb(164,164,151);
width: 350px;
height: 500px;
padding: 5px;
display: flex;
flex-direction: column;
justify-content: space-evenly;
background-color: rgb(176, 176, 159);
box-shadow: 3px 3px 3px 3px black;
border-radius: 15px;
}
.display {
display: flex;
height: 20%;
border: 1px solid white;
justify-content: right;
align-items: center;
margin-left: 8%;
margin-right: 8%;
color: rgb(249, 128, 0);
background-color: rgb(5,5,5);
font-size: x-large;
}
.display span {
margin-right: 10px;
font-family: 'LAB디지털';
}
.button_container {
display: flex;
flex-direction: column;
height: 60%;
border: 1px solid black;
margin-left: 8%;
margin-right: 8%;
background-color: rgb(18, 17, 17);
}
.button_content{
border: 1px solid black;
flex: 1 0 20%;
display: flex;
flex-direction: row;
}
.button_number {
flex: 1 0 25%;
background-color: rgb(82, 86, 78);
color: white;
font-family: 'LAB디지털';
font-size: large;
border-radius: 15px;
}
.button_number:hover{
background-color: rgb(58, 60, 56);
}
.button_operator {
flex: 1 0 25%;
background-color: ivory;
color: black;
font-family: 'LAB디지털';
font-size: large;
border-radius: 15px;
}
.button_operator:hover{
background-color: rgb(234, 240, 222);
}
.calculate {
flex: 1 0 25%;
background-color: ivory;
color: black;
font-family: 'LAB디지털';
font-size: large;
border-radius: 15px;
}
.calculate:hover{
background-color: rgb(234, 240, 222);
}
.button_reset {
flex: 1 0 25%;
background-color: rgb(249, 128, 0);
color: white;
font-family: 'LAB디지털';
font-size: large;
border-radius: 15px;
}
.button_reset:hover{
background-color: chocolate;
}
body {
background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Hubble_ultra_deep_field.jpg/400px-Hubble_ultra_deep_field.jpg");
}
java script
const calculator = document.querySelector('.calculator'); // calculator 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있음.
const buttons = calculator.querySelector('.button_container'); // calculator__keys 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있음.
const operator = document.querySelector('.calculator__operator'); // calculator__operator 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있음.
const display = document.querySelector('.display'); // calculator__display 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있음.
function calculate(n1, operator, n2) {
console.log(n1, operator, n2)
let result = 0;
if(Number(n1)==0 && Number(n2)==0){
return "숫자아님"
}else if (operator === '+') {
result = Math.floor(Number(n1) + Number(n2)); // '+'버튼을 눌렀을 때
}
else if (operator === '-') {
result = Math.floor(Number(n1) - Number(n2)); // '-'버튼을 눌렀을 때
}
else if (operator === '×') {
result = Math.floor(Number(n1) * Number(n2)); // '*'버튼을 눌렀을 때
}else if (operator === '÷') {
result = Math.floor(Number(n1) / Number(n2)); // '/'버튼을 눌렀을 때
}
if(String(result).length>10){
return "Infinity"
}
return String(result);
}
let firstNum = '';
let operatorForAdvanced = '';
let previousKey = '';
let previousNum = '';
buttons.addEventListener('click', function (event) {
const target = event.target; // 클릭된 HTML 엘리먼트의 정보가 저장되어 있음.
const action = target.classList[0]; // 클릭된 HTML 엘리먼트에 클레스 정보를 가져옴.
const buttonContent = target.textContent; // 클릭된 HTML 엘리먼트의 텍스트 정보를 가져옴.
if (target.matches('button')) {
// if(previousKey ===''){
// display.textContent=0
// }
if(display.textContent<0){
alert("세뱃돈은 항상 양수입니다")
}
if (action === 'button_number') { //클릭된 HTML 엘리먼트의 클래스 네임이 'number'라면
if (display.textContent == 0 && operatorForAdvanced === '') {
display.textContent = buttonContent;
firstNum = display.textContent // 첫번째 숫자를 변수에 할당
} // 기존 계산기 숫자가 0이고, 오퍼레이터 버튼이 안눌린 상태의 분기
else if (display.textContent != 0 && operatorForAdvanced === '' && display.textContent.length<10) {
display.textContent = display.textContent + buttonContent;
// textContent는 문자열이기 때문에 기존 계산기에서 보여지는 숫자에 +연산자로 구현
firstNum = display.textContent;
} // 기존 계산기 숫자가 0이 아니고, 오퍼레이터 버튼이 안눌린 상태의 분기
// ex) 15를 누르기 위해 1을 누른 상태의 분기(두자리 연속 누르기 위한 코드)
else if (display.textContent != 0 && operatorForAdvanced !== '') {
if (previousKey === operatorForAdvanced) {
display.textContent = buttonContent;
previousKey = display.textContent;
// 직전키를 변수에 할당 (직전키가 오퍼레이터냐 숫자냐에 따라 계산기의 다양한 기능을 구현하기 위함)
previousNum = display.textContent; // 직전 숫자를 변수에 할당
} // 기존 계산기 숫자가 0이 아니고, 오퍼레이터 버튼이 눌린 상태의 분기
// ex) 15+7을 하기 위해 15와 +를 누른 상태(두번째 숫자를 누르기 위한 코드)
else if (previousKey !== operatorForAdvanced && display.textContent.length<10) {
display.textContent = display.textContent + buttonContent;
previousNum = display.textContent;
} // ex) 15+17을 하기 위해 15와 +, 1을 누른 상태(17을 완성하기 위한 코드)
}
}
if (action === 'button_operator') { // //클릭된 HTML 엘리먼트의 클래스 네임이 'operator'일때 분기
operatorForAdvanced = buttonContent; // 오퍼레이터 누를 때 누른 텍스트 정보 할당
previousKey = operatorForAdvanced; // 직전키에 오퍼레이터 텍스트 정보 할당
}
if (target.textContent === 'AC') { // AC(초기화) 버튼을 누를 때 분기
display.textContent = 0;
firstNum = '';
previousNum = '';
operatorForAdvanced = '';
previousKey = '';
}
if (target.textContent === 'C') { // AC(초기화) 버튼을 누를 때 분기
display.textContent = display.textContent.slice(0,-1);
previousNum = display.textContent;
// alert(1)
}
if (buttonContent === '=') { // Enter(계산) 버튼을 누를 때
if (firstNum !== '' && operatorForAdvanced === '') {
display.textContent = 0;
firstNum = '';
previousNum = '';
operatorForAdvanced = '';
previousKey = '';
alert("잘못된 계산식")
}
else if (firstNum !== '' && previousNum === '') {
display.textContent = calculate(display.textContent, operatorForAdvanced, display.textContent)
} // 기존에 작성했던 calculate 함수를 이용하여 계산 상황에 따른 전달인자와 함께 호출
else if (previousKey === display.textContent) {
display.textContent = calculate(firstNum, operatorForAdvanced, previousNum)
firstNum = display.textContent;
previousNum = '';
operatorForAdvanced = '';
previousKey = '';
}
else if (previousKey !== display.textContent && previousNum !== '') {
display.textContent = calculate(display.textContent, operatorForAdvanced, previousNum)
}
else if (previousKey !== display.textContent && previousNum === '') {
display.textContent = firstNum;
}
}
}
});