JavaScript

부트캠프37일차(BOM,game)

동곤일상 2025. 3. 26. 17:50
반응형

1)BOM

1-1)screen

1-2)history

1-3) location

1-4)window

2) imageMove

3) game

3-1) 야구게임(이해해보자)

 


1)BOM

  BOM : browser object Model(브라우저객체모델)
        1. 브라우저의 구성요소를 객체로 처리할 수 있는 기능
        ==> 브라우저의 구성요소가 이미 객체로 생성되어있음(내장객체)


        2.BOM객체
        1) window : 브라우저 창을 의미 , 최상위 객체임(생략가능)
        2)screen : 화면을 의미 (화면의너비/높이 등 처리)
        3)history : 방문경로를 저장 . (뒤/앞) 이동가능
        4)location : 현재브라우저 경로
        5)document   : 현재브라우저의 문서
DOM : 문서상의 모든요소
        document
        -html
            -head
                -meta
                -title
            -body
                -div
                -ul
                 -li
        ......
        노드(Node) : HTML의 요소
         -요소노드(Element Node): 
태그,요소,객체
         -텍스트노드(Text Node) : 
태그 내의 내용
            <div>텍스트</div>  => 
텍스트노드 존재
            <input type='...'> =>
텍스트 노드가 존재X (빈 태그)


1-1)Screen

화면을 의미 (화면의너비/높이 등 처리)

   <script>//screen 객체
        console.log("화면너비 : ",screen.width)
        console.log("화면높이 : ",screen.height)
        console.log("실제너비 : ",screen.availWidth)
        console.log("실제높이 : ",screen.availHeight)
    </script>

1-2)history

방문경로를 저장 . (뒤/앞) 이동가능

<input type="button" onclick="history.back()" value="뒤로">
<input type="button" onclick="history.forward()" value="앞으로">
<input type="button" onclick="history.go(-1)" value="뒤로1번">
<input type="button" onclick="history.go(-2)" value="뒤로2번">
<br>

 

 


1-3)location (현재페이지를 의미함)

함수 : reload() 사용가능 (페이지새로고침)

<input type="button" onclick="location.href='https://www.naver.com'"value=네이버>
<input type="button" onclick="location.href='https://www.google.com'"value=구글>

 


1-4)window

브라우저 창을 의미 , 최상위 객체임(생략가능)

 

wndow.open() 새로운 창을 띄우기 : open("출력할페이지의Url", 화면의이름, 옵션)

[window].close() : 현재창을 닫기

<div>
    <input type="button" id="btn_open" value="창 열기">
    <input type="button" id="btn_close" value="창 닫기">
</div>
    <script>
        document.getElementById("btn_open").addEventListener("click",()=>{
            let width=480;
            let height = 360;
            let left = (screen.width - width)/2;//가로기준 가운데
            let top = (screen.height - height)/2;//세로기준 가운데
            let feature = `width${width},height=${height},left=${left},top=${top}`;
            //wndow.open() 새로운 창을 띄우기 : open("출력할페이지의Url", 화면의이름, 옵션)
             nwin = open("ex21_popup.html",'',feature);
        })
        //창닫기 클릭시 nwin(새로운창)을 닫음
        document.getElementById("btn_close").addEventListener("click",()=>{
            nwin.close();
        })
        
    </script>

새로운창의 HTML 정보

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{ padding: 0; margin: 0;}
        .img{
            width: 480px;
            height: 317px;
            background-image: url(./img/apple.gif);
            background-size: 480px 317px;
        }
        .footer{
            width: 480px;
            height: 36px;
            text-align: right;
            line-height: 36px;
        }
    </style>
</head>
<body>
    <div class="img"></div>
    <div class="footer">
        <input type="button" id="btn_close" value="닫기">
    </div>

    <script>
        document.getElementById("btn_close").addEventListener("click",()=>{close();})
                                //[window].close() : 현재창을 닫기
    </script>
</body>

</html>

 


2) image Move

drop(event) : 드래그 완료 시 
 dragover(event): 드래그 대상이 내 영역위에존재

event.dataTransfer : drag and drop 기능 구현 시 드래그 중인 데이터에 접근할 수 있도록 함

setData("형식",event.target.id); : 이동중인 태그의 id속성값
event.target : 이벤트 발생 객체 . img,p,h1 태그

appendChild : 하위객체로 추가

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style type="text/css">
        .droptarget{
            float: left;    min-width: 400px;
            min-height: 35px;  margin: 15px;
            padding: 10px;  border: 1px solid gray;
            overflow: auto;
        }

    </style>
</head>
<body>
    <!-- drop(event) : 드래그 완료 시 
     dragover(event): 드래그 대상이 내 영역위에존재
    
    -->
    <div class="droptarget" ondrop="drop(event)" ondragover="allowDrop(event)">
        <!--
        dragstart : 드래그시작
        drapend : 드래그종료
        event : DragEvent
        draggable = "true" : 드래그 가능
        -->
        <img src="img/apple.gif" ondragstart="dragStart(event)" ondragend="dragEnd(event)" 
            draggable="true" id="dragtarget1" width="100">
        <img src="img/apple.gif" ondragstart="dragStart(event)" ondragend="dragEnd(event)" 
            draggable="true" id="dragtarget2" width="100">
            <p ondragstart="dragStart(event)" ondragend="dragEnd(event)" 
                draggable="true" id="dragtarget3">이동해주세요</p>

            <h1 ondragstart="dragStart(event)" ondragend="dragEnd(event)" 
                draggable="true" id="dragtarget4">이동해주세요</h1>
    </div>
    <div class="droptarget" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <p id="demo1"></p>
    <p id="demo2"></p>
    <script>
        let demo1 = document.querySelector("#demo1");
        let demo2 = document.querySelector("#demo2");
        function dragStart(event){
            //event.dataTransfer : drag and drop 기능 구현 시 드래그 중인 데이터에 접근할 수 있도록
            //event.target : 이벤트 발생 객체 . img,p,h1 태그
            //setData("형식",event.target.id); : 이동중인 태그의 id속성값
            event.dataTransfer.setData("Text",event.target.id)
            demo1.innerHTML = "이동시작"
        }

        function dragEnd(event){//드래그종료시
            demo1.innerHTML = "이동완료"
        }
        function allowDrop(event){
            event.preventDefault();// 기본이벤트 중지 . 
            demo2.innerHTML = "drag over 시작"
        }
        function drop(event){
            event.preventDefault();//기본이벤트 중지
            let data = event.dataTransfer.getData("Text");//이동중인 태그의 id조회
            //event.target : div 태그
            //appendChild : 하위객체로 추가
            event.target.appendChild(document.getElementById(data))

            demo2.innerHTML = "drag drop 이벤트발생"
        }


    </script>
</body>
</html>

 

 


3) game 예제

move() 함수를 이용

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>글자잡기 겜</title>
    <style>
        h3{
            color: red;
            text-align: center;
        }
    </style>
</head>
<body>
    <h3></h3>
    <script type="text/javascript">
        function nextRandomInteger(limit){
            return Math.round(Math.random() * limit); //0~limit범위의 정수리턴
        }

        function randomSpeed(maxSpeed){
            return (Math.random() * maxSpeed) - (Math.random() * maxSpeed);
            //-4 ~ 4 사이의 임의 실수
        }
        let canvasWidth = 700; // 이동 가로크기
        let canvasHeight = 500; // 이동 세로크기
        let total = 10;//글자수
        function MovingText(){ // 생성자(x,y,vX,vY,body의 변수보유)
            this.x = nextRandomInteger(canvasWidth); //랜덤하게 x의 위치를 정해줌
            this.y = nextRandomInteger(canvasHeight);
            this.vX = randomSpeed(4);
            this.vY = randomSpeed(4);
            this.h = document.createElement("h1");//h1태그를만든다
            this.h.innerHTML = "A";//태그에 A를 넣는다
            this.h.setAttribute("style","background-color : white");//h1에 style을 넣고 뒤에속성을 추가
            this.h.style.position = "absolute";
            let text = this.h; // h1태그

            this.h.onclick = function(){
                --total;
                document.getElementsByTagName("h3")[0].innerHTML 
                            = ("남은 문자 수 : "+total);
                text.innerHTML = "B"; //클릭시 B로 변경
            }
            //document.body : <body></body>
            //appendChild : 하위태그에 추가 (즉 body안에넣는다)
            document.body.appendChild(this.h); //화면에 추가
        }

        //prototype : 객체외부에서 멤버함수 추가
        //MovingText.move() 추가 ( 움직이게하는 함수)
        MovingText.prototype.move = function(){ 
            if(this.h.innerHTML == 'B')return; //잡힌글자(움직임X)
            if(this.x < 0 || this.x > canvasWidth){ //가로범위벗어날 시
                this.vX *= -1;// vx를 반대방향으로 바꾸기
            }
            if(this.y < 0 || this.y > canvasHeight){
                this.vY *= -1; // vY를 반대방향으로
            }
            this.x += this.vX;//가로위치값변경(-4~4사이의값이 추가됨)
            this.y += this.vY;//세로위치값변경(-4~4사이의값이 추가됨)
            this.h.style.left = this.x +"px";
            this.h.style.top = this.y +"px";
            //<h1 style=background-color:white; position:absoulute; left : 123px; top:30px>A</h1>
        }
        //onload : 화면이 시작됐을경우 발생되는이벤트
        window.onload = function(){
            let movingTexts = [];
            for(let i =0 ; i<10 ; i++){
                movingTexts.push(new MovingText());
            }//창이 켜질 떄 MovingText객체 10개 생성

            // 1/60초 마다 계속실행되는 함수
            let game = setInterval(function(){
                for(let i in movingTexts){
                    if(total<4){//남은A의 갯수가 4개 이하면종료
                        alert("게임종료");
                        clearInterval(game);//함수중지
                        return;
                    }
                    movingTexts[i].move(); //모든movingText객체를 move
                }
            },1000/100); //해당 시간을 줄일수록 빠르게움직일것임
        }
        
    </script>
    
</body>
</html>

 

 

 

 


3-1) 야구게임 (코드를 완전히 이해해보자)

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>숫자야구겜</title>
    <style>
        *{text-align: center; margin: 0px; padding: 0px;}
        img{
            border: 4px solid black;
            width: 100px;
            height: 100px;
            padding: 5px;
        }
    </style>
</head>
<body>
    <h3>숫자야구</h3>
    <div id="wrap">
        <div id="card"></div>
        <div id="left">
            <input type="text" id="userNum" placeholder="4자리숫자">
            <input type="button" value="입력" id="inbtn">
        </div>
        <div id="result"></div>
    </div>
    <script src="ex24.baseball.js"></script>
</body>
</html>

JS

 

함수선언 및 정답 , img 태그 생성

 

let trycount=0;
let nums = new Array(10);//10크기의배열 (0~9를 넣을듯)
let answer = new Array(4);//4크기의 배열(정답)
let inputArr = new Array(4);//4크기 배열(입력값)
for(let i=0; i<nums.length ; i++){
    nums[i] = i;//배열번호에 해당하는 i 대입
}

for(let a=0;a<100;a++){
    //0~9의 랜덤함숫자
    //floor : 작은 근사정수
    let ran = Math.floor(Math.random()*nums.length);
    let tmp = nums[0];
    nums[0] = nums[ran];
    nums[ran] = tmp; //100번 동안 섞는다(num배열)
}

for(let i =0 ; i<answer.length ; i++){
    answer[i] = nums[i]; // num[0~3](4개) answer에 집어넣는다
}

window.onload = function(){ //창을 띄울 떄 발생함
    for(let i = 0; i<4 ; i++){
        let img = document.createElement("img");//img태그생성
        document.querySelector("#card").append(img);
    } // card태그 내에 img 4개만듬
}

 

입력버튼 클릭 시 발생하는 함수   



document.querySelector("#inbtn").onclick = ()=>{ //입력버튼 클릭시 발생
    let v_userNum = document.querySelector("#userNum").value;
    if(v_userNum == ""){
        alert("숫자를 입력하세요");
        document.querySelector("#userNum").focus();
        //커서가 text박스에 포커스를 두게 됨
    }
    if(isNaN(v_userNum)){
        alert("숫자타입으로입력해주세요");
        document.querySelector("#userNum").value="";
        document.querySelector("#userNum").focus();
        return;
    }
    if(v_userNum.length != 4){
        alert("4자리숫자만 입력해주세요");
        document.querySelector("#userNum").value="";
        document.querySelector("#userNum").focus();
        return;
    }
//4자리숫자를 정상적으로 입력했을 때
//inputArr : 입력값을 담을 배열(4자리숫자)
inputArr = v_userNum.split("");
for(let v1 in inputArr){ //중복숫자 검사
    let cc=0;
    for(let v2 in inputArr){
        if(inputArr[v1] == inputArr[v2]){
            cc++;
        }
    }
    if(cc>1){
        alert("중복숫자 입력불가능");
        document.querySelector("#userNum").focus();
        return;
        }
    }
//------------------
    //중복되지않은 4개의숫자 입력한 경우
    matchingNum(v_userNum); //입력숫자에대해 S,B의 갯수 or 성공여부 판단
    
    document.querySelector("#userNum").value="";//숫자입력 후 초기화

    document.querySelector("#userNum").onkeyup = (event)=>{
    //text의 value에서 enter키를 누른다면
        // 자바스크립트가  button을 클릭시킴
        if(event.keyCode==13){//keycode=13 (enter키)
            document.querySelector("#inbtn").onclick();
        }
    
    }
    // console.log(answer);답을 console에띄움
}
//--------------------

 

입력받은 숫자에 대한 S , B 여부 + 4S시 img넣는 함수

function matchingNum(usernum){//입력받은숫자를 받음
    let strike = 0;
    let ball=0;
    let inputarr = usernum.split("");
    for(let i =0; i<4 ; i++){
        for(let j=0;j<4 ;j++){
            if(answer[j] == inputarr[i]){//같은숫자가 존재시
                if(i==j) { //인덱스번호가같다면
                    strike++;
                }
                else{//인덱스번호가다르다면
                    ball++;
                }
            }
        }
    }
    console.log("strike : "+strike,"ball : "+ball);

    if(strike==4){ //4S 일때 실행
        let wrap = document.getElementById("wrap");
        let h1_1 = 
        document.querySelector("#result").innerHTML += ("<h1>정답입니다</h1>")
        document.querySelector("#wrap").innerHTML += `<button>다시시작</button>`
        document.querySelector("button").onclick = ()=>{
            location.reload();//F5버튼과 같은 동작(새로고침)
        }
        cimgs = document.getElementsByTagName("img");
        //cimgs = 배열객체 (4개의img태그 저장)
        for(let i in cimgs){
             //cimgs[i](4개의이미지)에  answer[i] 이름 가진 사진넣기
            cimgs[i].src = `./nums/num${answer[i]}.jpg`;
        }
    }

    else{
        strike +="S";
        ball+= "B";
        let result_div = document.querySelector("#result");
        result_div.innerHTML += ++trycount +"번쨰 도전 : "+strike+ball
        +",유저입력값 : "+usernum+"<br>"
        if(trycount>9){//10번쨰시도가 최대임(자동 페이지 새로고침)
            alert("최대시도 초과")
            location.reload();
        }
    }
}