랜덤한 수 생성

자바스크립트에서는 Math.random() 함수로 0 이상 1 미만인 랜덤한 수를 만들 수 있습니다. (0은 나올 수도 있지만 1은 절대 나오지 않습니다.)

Math.random();

이런식으로 소수점이 있는 수가 생성됩니다.

이 함수를 이용해서 0 이상 10 미만인 랜덤한 수를 만들려면? 결과에 10을 곱해주면 되겠죠.

Math.random()*10;

소수점 없이 0, 1, 2, 3, 4, 5, 6, 7, 8, 9의 10가지 수 중에 하나를 얻고 싶다면 소수점 이하의 값을 버리면 됩니다.

Math.floor()함수로 소수점 이하의 값을 버릴 수 있습니다. 반올림이 아니라 소수점 이하의 값을 무조건 버리는 함수입니다.

Math.floor(Math.random()*10);

위 내용을 바탕으로 눈금이 1부터 6까지 있는 주사위 함수를 만들 수 있습니다.

function dice6(){
  return Math.floor(Math.random()*6)+1;
}

Math.floor(Math.random()*6)는 0부터 5까지의 정수가 나오므로 여기에 1을 더해주면 1부터 6까지의 값이 나오게되는 것이죠.

일반화

만약 어떤 게임을 개발하는데, 눈금이 1에서 6까지 있는 주사위와 1에서 10까지 있는 주사위 두 개를 사용한다면 함수를 어떻게 만들어야 할까요?

function dice6(){
  return Math.floor(Math.random()*6)+1;
}

function dice10(){
  return Math.floor(Math.random()*10)+1;
}

이렇게 두가지 함수를 만들어서 사용할 수도 있겠지만, 위 두가지 기능을 모두 할 수 있는 하나의 함수만 만들 수도 있습니다.

function dice(maxNumber){
  return Math.floor(Math.random()*maxNumber)+1;
}

dice(6), dice(10)로 dice6과 dice10의 기능을 할 수 있습니다. 이때 dice 함수를 dice6, dice10함수에 비해 더 일반화가 되었다라고 표현합니다.

일반화된 코드는 여러 장점이 있습니다.

  • 우선 작성해야 할 코드의 전체 길이가 줄어듭니다.
  • 확장성이 좋습니다. 만약 1에서 12까지의 눈금이 있는 새 주사위가 필요하다고 하면 dice12 함수를 새로 만들 필요 없이 dice(12)를 사용할 수 있습니다.
  • 유지보수가 간편합니다. 만약에 그럴일은 없겠지만 어떠한 이유로 Math.random함수를 사용하지 말고 다른 코드로 변경해야하는 일이 있다고 하면, 주사위 함수가 여러가지인 경우 모든 함수를 각각 수정해 주어야 합니다. 일반화된 주사위 함수 하나뿐이라면 그곳만 수정하면 됩니다.

주사위 게임

위에서 만든 dice함수를 사용해 주사위 게임 함수를 만들어 봅시다.

- 주사위는 눈금이 1에서 6까지입니다.
- 컴퓨터의 주사위 값을 구하여 "컴퓨터의 주사위는 x입니다."라고 콘솔에 출력합니다. x는 주사위 눈금의 값입니다.
- 사용자의 주사위 값을 구하여 "당신의 주사위는 x입니다."라고 콘솔에 출력합니다. x는 주사위 눈금의 값입니다.
- 컴퓨터의 주사위 값과 사용자의 주사위 값을 비교하여 "x의 승리입니다."를 출력합니다. 컴퓨터의 주사위 값이 높으면 x에 "컴퓨터", 아니라면 "당신" 이 들어갑니다.
- 비긴 경우 "비겼습니다."를 콘솔에 출력합니다.

// 주사위 값을 생성하는 함수
function dice(maxNumber){
  return Math.floor(Math.random()*maxNumber)+1;
}

// 주사위 값을 출력하는 함수
function printDice(name, num){
  console.log(name+"의 주사위는 "+num+"입니다.");
}

// 승자를 출력하는 함수
function printWinner(name){
  console.log(name+"의 승리입니다.");
}

// 비겼음을 출력하는 함수
function printDraw(){
  console.log("비겼습니다.");
}

/*
   위의 함수들은 게임의 각 부분을 담당하는 함수들이며,
   아래 게임 메인 함수는 전체적인 프로그램의 진행을 담당합니다.
*/

// 게임 메인 함수
function diceGame(){
  var computerName = "컴퓨터";
  var yourName = "당신";

  var computerDice = dice(6); // 컴퓨터의 주사위 값 을 구함
  printDice(computerName, computerDice); // 컴퓨터 주사위 값 출력

  var yourDice = dice(6); // 사용자의 주사위 값을 구함
  printDice(yourName, yourDice); // 사용자 주사위 값 출력

  if(computerDice > yourDice){ // 만약 컴퓨터의 주사위 값이 더 크면,
    printWinner(computerName); // 컴퓨터 승리 문구 출력
  }
  else if(computerDice < yourDice){ // 그렇지 않고 만약 사용자의 주사위 값이 더 크면,
    printWinner(yourName); // 사용자 승리 문구 출력
  }
  else { // 다 아니라면,
    printDraw(); // 비겼음을 출력
  }
}

위 코드에서 //, /*, */라고 표시된 부분을 주석(comment)이라고 합니다. 코드를 읽는 사람에게 도움을 주기 위해 작성한 글로 프로그램에 아무런 영향을 끼치지 않습니다.

//는 한 줄에서 // 뒷부분에 입력된 내용을 코드에 포함시키지 않는 역할을 하고, /*는 */가 나올 때까지 그 사이의 모든 내용을 무시합니다.

이번 글은 연습문제 풀이입니다. 이전 글에서 연습문제를 풀어 보신 분들만 아래 내용을 확인하시길 바랍니다.











9-1 풀이

function supplementaryClass(koreanScore, englishScore, mathScore){
  if(koreanScore <= 50 && englishScore <= 50 && mathScore <= 50){
    return "종합반";
  } 
  else if(koreanScore <= 50 || englishScore <= 50 || mathScore <= 50){
    return "단과반";
  }
  else {
    return "보충 수업 없음";
  }
}

if, if else, else와 and 연산자, or 연산자를 사용하여 조건에 맞는 함수를 만들 수 있습니다.

9-2 풀이

주어진 조건을 다시 한번 살펴봅시다.

  • 연수가 4로 나누어떨어지는 해는 윤년으로 한다.
  • 이 중에서 100으로 나누어떨어지는 해는 평년으로 한다.
  • 그중에 400으로 나누어떨어지는 해는 윤년으로 둔다.

이 중 첫번째 조건만 if문으로 나타내면 다음과 같습니다. 윤년은 영어로 leap year이므로 isLeapYear를 윤년인지 아닌지를 담는 변수명으로 하였습니다.

var isLeapYear;

if(year%4 == 0){
  isLeapYear = true;
} 
else {
  isLeapYear = false;
}

첫번째 조건을 만족하는 년도들은 두번째 조건에 따라 다시 윤년인지 아닌지가 갈립니다. 두번째 조건을 첫번째 if 코드에 다시 적용해 봅시다.

var isLeapYear;

if(year%4 == 0){
  if(year%100 == 0){
    isLeapYear = false;
  } 
  else {
    isLeapYear = true;
  }
} 
else {
  isLeapYear = false;
}

두번째 조건을 만족하는 년도들은 다시 세번째 조건에 따라 윤년인지 아닌지가 갈립니다. 세번째 조건을 다시 두번째 if 코드에 적용해 봅시다.

var isLeapYear;

if(year%4 == 0){
  if(year%100 == 0){
    if(year%400 == 0) {
      isLeapYear = true;
    }
    else {
      isLeapYear = false;
    }
  } 
  else {
    isLeapYear = true;
  }
} 
else {
  isLeapYear = false;
}

이 코드를 함수로 감싸면 아래와 같이 함수가 완성됩니다. (정답예제 1)

function checkLeapYear(year){
  var isLeapYear;

  if(year%4 == 0){
    if(year%100 == 0){
      if(year%400 == 0) {
        isLeapYear = true;
      }
      else {
        isLeapYear = false;
      }
    } 
    else {
      isLeapYear = true;
    }
  } 
  else {
    isLeapYear = false;
  }

  return isLeapYear;
}

수학시간에 배운 '명제의 대우은 사실이다'라는 것 생각나시나요? 만약 생각이 나지 않는 다면 인터넷으로 명제의 역, 이 대우를 다시 한번 알아보고 오세요.

주어진 조건에 대우를 구하면 다음과 같이 변경할 수 있습니다.

  • 조건1: 연수가 4로 나누어떨어지지 않는 해는 평년이다.
  • 조건2: 조건1에 해당하지 않지만 100으로 나누어떨어지지 않는 해는 윤년이다.
  • 조건3: 조건 1, 조건 2에 해당하지 않지만 400으로 나누어떨어지는 해는 평년이다.

이 조건으로 함수를 만들면 다음과 같이 좀 더 간단하게 만들 수 있습니다. (정답예제 2)

function checkLeapYear(year){
  var isLeapYear;

  if(year%4 != 0){
    isLeapYear = false;
  }
  else if(year%100 != 0){
    isLeapYear = true;
  }
  else if(year%400 != 0) {
    isLeapYear = false;
  }
  else {
    isLeapYear = true;
  }

  return isLeapYear;
}


연습문제(9-1)

한 학교에서 학생들의 국어, 영어, 수학 점수로 보충수업 대상자를 뽑습니다. 아래 규칙을 만족하는 함수를 만들어 보세요.

  • 함수는 국어, 영어, 수학 점수 3가지의 값을 입력받습니다. 점수는 숫자입니다.
  • 모든 과목의 점수가 50점 이하라면 "종합반" 이라는 문자열을 return합니다.
  • 특별반이 아닌 학생들 중 한과목이라도 50점 이하라면 "단과반"이라는 문자열을 return합니다.
  • 나머지 학생들은 "보충 수업 없음"이라는 문자열을 return합니다.

위 조건을 만족하는 함수를 만들고, 테스트를 통해 제대로 작동하는지 확인해 보세요.

연습문제(9-2)

2월은 보통 28일까지 있지만 윤년인 경우 2월을 윤달이라고 하고 29일까지 있습니다. 예로, 2020년은 윤년으로 2020년 2월은 윤달이며, 2020년 2월은 29일까지 있습니다. 보통 윤년이 4년마다 돌아온다고 알고 있지만 이는 정확한 것은 아닙니다.

아래는 위키(https://ko.wikipedia.org/wiki/윤년)에서 가져온 윤년을 구하는 정확한 규칙입니다.

  • 서력 기원 연수가 4로 나누어떨어지는 해는 윤년으로 한다.(1992년, 1996년, 2004년, 2008년, 2012년, 2016년, 2020년 …)
  • 이 중에서 100으로 나누어떨어지는 해는 평년으로 한다.(1900년, 2100년, 2200년, 2300년, 2500년 …)
  • 그중에 400으로 나누어떨어지는 해는 윤년으로 둔다.(1600년, 2000년, 2400년 …)

이 규칙을 사용하여 입력된 년도가 윤년인지 아닌지를 구하는 함수를 만들어 보세요.

  • 함수는 하나의 양의 정수를 년도로 받습니다.
  • 윤년 규칙에 따라 윤년이면 true를, 윤년이 아니면 false를 return합니다.

위 조건을 만족하는 함수를 만들고, 2020(윤년), 1992(윤년), 1900(평년),  1600(윤년) 등의 값을 넣어서 제대로 작동하는지 확인해 보세요.

else if

else if는 if와 else 사이에 사용되어 2가지 이상의 분기를 줄 수 있습니다.

if(조건1){
  조건1을 만족하는 경우 이곳의 코드가 실행됨
}
else if(조건2){
  조건1을 만족하지 못하지만 조건2를 만족하는 경우 이곳의 코드가 실행됨
}
else{
  어떠한 조건도 만족하지 못하는 경우 이곳의 코드가 실행됨
}

- if else 문에서 if 와 else 사이에 else if가 끼어 들어간 형태로, if else 문의 확장입니다.
- if의 조건이 만족하지 않을 경우에만, else if의 조건을 확인합니다. if의 조건이 만족된다면 if else의 조건을 확인하지 않습니다.

if, else if, else를 사용해서 주어진 값이 음수인지, 양수인지 혹은 0인지를 확인하는 함수를 만들어 봅시다.

function checkNumber(num){

  if(num > 0){
    console.log("양수입니다.");
  }
  else if(num == 0){
    console.log("0입니다.");
  }
  else{
    console.log("음수입니다.");
  }

}

주어진 값에 따라 3가지 분기를 가질 수 있게 되었습니다. 3가지보다 더 많은 분기가 필요하다면, else if를 더 반복하면 됩니다.

성적에 따라 A, B, C, D, F를 주는 함수를 만들어 봅시다.

function getGrade(score){

  var grade;

  if(score > 90){
    grade = 'A';
  }
  else if(score > 80){
    grade = 'B';
  }
  else if(score > 70){
    grade = 'C';
  }
  else if(score > 60){
    grade = 'D';
  }
  else{
    grade = 'F';
  }

  return grade;

}

if else가 여러번 사용된 경우, if의 조건을 포함하여 첫번째로 만족하는 조건의 {}안의 코드가 실행되고, 그 다음의 조건들은 아예 확인조차 하지 않고 if문 다음 코드로 진행합니다. 위 함수에서 만약 score가 80이라면, 처음 if의 score > 90을 확인한 후 해당되지 않으므로 다음 else if의 score > 80 을 확인하고, 이 조건에 해당하므로 해당 {}안의 코드를 실행하지만, 그 뒤에 있는 score > 70, score > 60의 조건은 아에 확인조차 않고 다음 코드인 return grade;로 넘어갑니다.

첫번째 예제는 console.log로 결과를 콘솔에 표시하도록 하였고, 두번째 예제는 return을 통해 결과값을 return합니다. 이 둘의 차이점은 무엇일까요?

console.log로 결과를 표시하면 콘솔을 보는 사람이 바로 결과를 알아 볼 순 있지만 콘솔에 표시된 값을 어딘가에 저장한다거나, 다시 사용할 수 없습니다. return을 사용하면 해당 함수는 데이터를 return하게 되므로 이 데이터를 활용할 수가 있습니다. 아래처럼 말이죠.

var myGrade = getGrade(86);

console.log("내성적: "+myGrade);

논리연산자

논리연산자는 Boolean 데이터(true/false)를 연산하여 새로운 Boolean 데이터를 생성합니다.

 논리연산자  하는 일  예제  결과
 &&

 좌항과 우항이 모두 true이면 true, 나머지는 false

 true && true  true
 true && false  false
 false && true  false
 false && false  false
 ||  좌항과 우항 중 하나라도 true이면 true  true || true  true
 true || false  true
 false || true  true
 false || false  false
 !  true이면 false, false이면 true  !true  false
 !false  true

&& 연산자는 and 연산자, || 연산자는 or 연산자로 불리며, 이 둘을 사용해서 if문의 조건부에 두가지 이상의 조건 줄 수 있습니다.

키가 80cm 이상, 195cm 이하인 사람만 탑승할 수 있는 롤러코스터가 있습니다. 이 롤러코스터에 탑승할 수 있는지 없는지를 true/false로 나타내는 함수를 만들어 봅시다.

function checkHeight(height){

  if(height >= 80 && height <= 195){
    return true;
  }
  else {
    return false;
  }

}

조건 그 자체가 Boolean 데이터를 생성하는 연산식이므로 아래와 같이 나타낼 수도 있습니다.

function checkHeight(height){

  return height >= 80 && height <= 195;

}

한 식에 덧셈과 곱셈이 같이 있는 경우 곱셈을 먼저 계산하는 것처럼, &&와 ||이 같이 있는 경우 &&이 먼저 연산된 후 ||이 연산됩니다.

true || true && false

위 값은 &&가 먼저 계산되어 true가 됩니다. 수학과 마찬가지로 괄호를 이용하여 연산 순서를 조절할 수 있습니다.

(true || true) && false

위 값은 괄호안이 먼저 계산되어 false가 됩니다.

나머지 연산자

마지막으로 나머지 연산자라는 조금 특별한 연산자에 대해 알아봅시다.

숫자1 % 숫자2

%는 나머지 연산자로 숫자1숫자2로 나누었을 경우 나머지가 몇인지 알려주는 연산자입니다.

예를 들어, 13%3은 13을 3으로 나누면 4로 나누어진 후 1이 남으므로 1이 되고, 100%20은 100을 20으로 나누면 5로 나누어 떨어지므로 0이 됩니다.

나머지 연산자의 연산 결과는 항상 숫자2보다 작다는 특징이 있습니다.

주로 주어진 수가 홀수(odd) 인지 짝수(even)인지 구별하는 용도로 쓰입니다. 2로 나누어 떨어지면 짝수, 2로 나누어서 1이 남으면 홀수입니다.

function isEven(num){
  return num%2 == 0;
}

위 함수에 수를 넣어서 호출하면, 짝수인 경우 true가, 홀수인 경우 false가 return됩니다.

정리 및 요약

  • else if는 if와 else 사이에 사용되어 2가지 이상의 분기를 줄 수 있음. 한번 이상 사용도 가능
  • 조건들 중에 가장 먼저 만족하는 조건의 {}안의 코드가 실행되고, 그 다음의 조건들은 아예 확인조차 하지 않고 if문 다음 코드로 진행됨
  • 논리연산자: Boolean 데이터(true/false)를 연산하여 새로운 Boolean 데이터를 생성하는 연산자
  •  논리연산자  하는 일
     &&

     좌항과 우항이 모두 true이면 true, 나머지는 false

     ||  좌항과 우항 중 하나라도 true이면 true
     !  true이면 false, false이면 true
  • &&와 ||이 같이 있는 경우 &&을 먼저 계산
  • 괄호를 이용하여 논리연산자의 연산 순서를 조절할 수 있음
  • %: 나머지 연산자. 좌항을 우항의 값으로 나눈 후 나머지의 값이 됨

+ Recent posts