자바스크립트 #07 가위바위보(이미지 스프라이트, 비동기)

수박·2020년 6월 10일
0

JavaScript

목록 보기
8/22

자바스크립트 #07 가위바위보(이미지 스프라이트, 비동기)

이미지스프라이트란 이미지를 로드할 때 한 장의 이미지를 로드하고 위치를 바꾸어 출력해주는 것을 말합니다.

예전에 사양이 좋지않을때 많이 사용했던 방법이라고 합니다.

가위바위보 사진 한장전체를 로드하고, 위치를 바꾸어 가위, 바위, 보를 순차적으로 띄워보겠습니다.

먼저 사진을 div의 backgrond에 로드합니다.

   <style>
        #computer{
            width: 200px;
            height: 250px;
            background: url('./img_.jpg') 0 0;     }
    </style>
</head>
<body>
    <div id ="computer"></div>

url뒤의 0 0은 이미지의 좌표를 지정합니다.

left, top, centor ,bottom, right 등 을 사용할 수 있습니다.

왼쪽부터 가위, 바위, 보 순서로 이미지는 이루어져있습니다.

이미지를 출력할 좌표를 왼쪽으로 밀면 나머지 이미지를 출력할 수 있습니다. 0.1초마다 해당 연산을 하는 스크립트를 작성해보겠습니다.

var imagelocation = '0';

var dict ={
    scissors : '0',
    rock: '-188px',
    paper : '-405px'
};

setInterval(function(){
    if(imagelocation === dict.scissors)
        imagelocation =dict.rock;
    else if(imagelocation === dict.rock)
        imagelocation = dict.paper;
    else if(imagelocation === dict.paper)
        imagelocation = dict.scissors;
    document.querySelector('#computer').style.background =
       'url(./img_.jpg)' + imagelocation + ' 0';
}, 100);

전역변수 imagelocation를 초기화하고 setInterval 함수로 0.1초마다 함수의 내용을 수행하도록 작성합니다.

초기 imagelocation값은 0이므로 왼쪽으로 -188px만큼 좌표를 이동합니다.

그 후 -405, 0 순서로 imagelocation 좌표를 계속 바꿔줍니다.

document의 querySelector메소드로 id가 computer인 객체를 지정하고, 그에 대한 background 속성 값을 다음과 같은 문자열로 변경해줍니다.

url을 지정하고, 변화하는 imagelocation값, 그리고 top좌표를 지정해줍니다.

작성하고 실행하면 가위, 바위, 보 순서로 이미지가 계속 반복되며 출력되는 것을 확인할 수 있습니다.


버튼마다 이벤트리스너 등록하기(querySelectorAll)

이제 class가 btn인 3개의 버튼(가위 바위 보)을 만들어 각 버튼마다 이벤트리스너를 등록하겠습니다.

여기서 모든 class를 지정해주기 위해 querySelectorAll 메소드를 사용하며 해당 메소드는 for 반복문이 아닌 forEach를 통해 리스너를 등록해줄 수 있습니다.

document.querySelectorAll('.btn').forEach(function(btn){
    btn.addEventListener('click', function()
    {
        console.log(this.textContent, computer);
    });
});

실행결과

가위 computer 인터벌에 의해 계속해서 변함
바위 
보 

버튼을 클릭했을때 컴퓨터의 값이 무엇인지 확인하기 위해서 dict객체의 key값을 출력해야합니다.

value는 버튼이 클릭될 때마다 출력되는 것을 확인했으니 value에 맞는 key값을 출력해서 비교해야합니다.

dict의 value와 key값을 거꾸로 가지는 객체를 하나 더 생성해서 computer을 key값으로 사용하여 value를 출력합니다.

var dict2 ={
    '0' : 'scissors',
    '-188px': 'rock',
    '-405px' : 'paper'
};
...
...
console.log(this.content, dict2[imagelocation]);
가위 rock
바위 scissors
보 scissors

클릭할 때마다 컴퓨터의 값과 내가 누른 버튼의 값이 나오는 것을 확인할 수 있습니다.

이렇게 일일히 치는 것보다 Object.entries(객체)를 통해 객체 to 배열로 할 수 있습니다.

console.log(Object.entries(dict));

해당 메소드를 수행하면

(3) [Array(2), Array(2), Array(2)]

    1. 0: (2) ["scissors", "0"]
    2. 1: (2) ["rock", "-188px"]
    3. 2: (2) ["paper", "-405px"]

객체가 키, 값으로 2차원배열로 변환됩니다.

var lookUp = Object.entries(dict).find(function(v){
    return v[0] === 'rock';
});

배열에서 find메소드를 수행할 수 있습니다. find는 배열에서 return이 true일 때 반복을 멈추는 반복문입니다.

dict배열에서 2차원배열의 첫번째 요소값이 rock일 때 멈춥니다.

log를 찍어보면 해당 배열값이 출력되는 것을 확인할 수 있습니다.

발견하지 못하면 undefined가 반환됩니다.

인덱스를 찾고싶다면 findIndex를 사용합니다.

이제 버튼을 클릭했을때 그때의 이미지 좌표를 통해 컴퓨터가 어느 값을 출력하는지를 확인할 수 있습니다.

function computerPick(imagelocation){
    return  Object.entries(dict).find(function(v){
        return v[1] ===  imagelocation;
    });
}

imageLocation을 매개변수로받는 computerPick 메소드를 수행하면, 2차원배열로 변환된 dict객체에서 value(좌표값)가 받아온 매개변수인 imageLocation과 같은 key값을 출력해줍니다.

해당 메소드는 배열을 반환합니다. 배열의 첫번째원소가 키값이므로 [0]을 통해 key값을 출력해줍니다.

console.log(this.textContent, computerPick(imageLocation)[0]);

log에 원하는 값이 출력되는 것을 확인할 수 있습니다.

가위 rock
가위 paper
바위 rock
바위 pape

가위바위보 로직

가위바위보를 인덱스로 나타내보면

가위 : 0

바위 : 1

보 : 2

입니다.

승리조건은

가위(0) : 보(2)

바위(1) : 가위(0)

보(2) : 바위(1)이고 앞에서 뒤로 뺐을 때 -2, 1, 1의 값이 나옵니다. 여기에 3을 더하면 1,4,4 그리고 3으로 나눈 나머지는 전부 1의 값을 갖습니다.

패배조건은 위의 계산대로 했을 때

2 , 2, 5가나오고 나머지는 모두 2의 값을 갖습니다.

이를 로직으로 구현합니다.

그렇게 하기 위해서 지금까지 scissors, rock, paper의 값을 출력하도록 만든 메소드를 인덱스를 출력하도록 수정합니다.

function myPick(btnValue){
    return  Object.entries(dict).findIndex(function(v){
        return v[0] ===  btnValue;
    });
}

function computerPick(imageLocation){
    return  Object.entries(dict).findIndex(function(v){
        return v[1] ===  imageLocation;
    });
}
document.querySelectorAll('.btn').forEach(function(btn){
    btn.addEventListener('click', function()
    {
        var playerIndex = myPick(this.textContent);

        //컴퓨터의 인덱스
        var comIndex =  computerPick(imageLocation);
        
        var resultIndex =  (3 + playerIndex - comIndex) % 3;
        record[resultIndex]++;
        alert(this.textContent + "를 내셨으므로 " +result[resultIndex] +" 입니다!");
        var score = document.getElementById('score');
        score.textContent = "승: " + record[1]+ "  무:" +record[0] + " 패: "+record[2];
    });
    initBtn.addEventListener('click',function(){ record.forEach(function(value,index){
            record[index] = 0;
        });
        score.textContent = "승: " + record[1]+ "  무:" +record[0] + " 패: "+record[2];
    });
});

myPick함수는 버튼의 textContent값과 같은 값을 가지는 배열의 인덱스를 찾고, computerPick은 버튼을 누른 시점의 이미지좌표값을 가지고 해당 인덱스를 찾습니다.

그리고 인덱스를 계산하여 승, 무, 패를 확인하고 record배열에 스코어를 기록하고 해당 값을 화면에 출력합니다.

init버튼을 클릭했을때 record배열의 값들을 전부 0으로 초기화하도록 작성했습니다.

결과

0개의 댓글