자바스크립트를 이용하여
자스스톤 게임을 구현하는 예제(ver.3)입니다.
- 카드세팅 리팩토링 -
자스스톤 게임을 구현하는 예제(ver.3)입니다.
- 카드세팅 리팩토링 -
예제는 인프런의 제로초, "조현영"님의 강의를 들으면서 공부한 내용입니다.
리팩토링
중복되는 코드는 함수를 만들어 제거합니다.
딕셔너리 구조로 객체화
리팩토링 딕셔너리 구조를 위해서
변수를 상대 쪽 데이터/ 내쪽 데이터로 나눈 후, 객체화합니다.
before
const 상대영웅 = document.getElementById('rival-hero');
const 상대덱 = document.getElementById('rival-deck');
const 상대필드 = document.getElementById('rival-cards');
const 상대코스트 = document.getElementById('rival-cost');
let 상대덱data = [];
let 상대영웅data;
let 상대필드data = [];
const 내영웅 = document.getElementById('my-hero');
const 내덱 = document.getElementById('my-deck');
const 내필드 = document.getElementById('my-cards');
const 내코스트 = document.getElementById('my-cost');
let 내덱data = [];
let 내영웅data;
let 내필드data = [];
after
아래의 딕셔너리 구조로 세팅 후, 기존의 변수를 변경된 객체로 모두 바꿉니다.
반영한 코드는 아래의 전체 코드에서 확인할 수 있습니다.
const 상대 = {
영웅: document.getElementById('rival-hero'),
덱: document.getElementById('rival-deck'),
필드: document.getElementById('rival-cards'),
코스트: document.getElementById('rival-cost'),
덱data: [],
영웅data: [],
필드data: [],
}
const 나 = {
영웅: document.getElementById('my-hero'),
덱: document.getElementById('my-deck'),
필드: document.getElementById('my-cards'),
코스트: document.getElementById('my-cost'),
덱data: [],
영웅data: [],
필드data: [],
}
반복되는 코드 함수로 설정
//리팩토링 함수
function 덱에서필드로(데이터, 내턴) { //스코프안에 데이터가 없음
//-> 카드돔연결(데이터, 돔, 영웅)에서 데이터 선언을 가져와야하므로 데이터를 매개변수로 넣어줌
let 객체 = 내턴 ? 나 : 상대; //삼항연산자 나 = true, 상대 = false
let 현재코스트 = Number(객체.코스트.textContent);
if (현재코스트 < 데이터.cost) {
return;
}
let idx = 객체.덱data.indexOf(데이터);
객체.덱data.splice(idx, 1);
객체.필드data.push(데이터);
//화면 업데이트 구현이 어려워 전체 데이터 지웠다가 다시 필드, 덱 출력
객체.덱.innerHTML = '';
객체.필드.innerHTML = '';
객체.필드data.forEach(function(data) { //뽑은 카드 올라감
카드돔연결(data, 객체.필드);
});
객체.덱data.forEach(function(data) { //뽑은 카드는 배열에서 사라짐
카드돔연결(data, 객체.덱);
});
데이터.field = true; //필드에 올라간 카드(위에서 재클릭 방지)
객체.코스트.textContent = 현재코스트 - 데이터.cost;
}
조건문 삼항연산자
let 객체 = 내턴 ? 나 : 상대;
if문으로 사용할 경우,
if (내턴) {
객체 = 나;
} else {
객체 = 상대;
}
리턴문 오류 발생
리팩토링으로 인해 return문을 함수에 따로 빼내면서,
클릭할 때마다 무제한으로 카드가 하나씩 생성되는 오류 생김
문제 코드 before
if (현재코스트 < 데이터.cost) {
return;
}
카드.addEventListener('click', function(card) {
if (턴) { //내 필드, 내턴
if (!데이터.mine || 데이터.field) {
return;
}
덱에서필드로(데이터, true);
내덱생성(1); //카드 한개 더 뽑기
} else { //상대방 필드 상대턴
if (데이터.mine || 데이터.field) {
return;
}
덱에서필드로(데이터, false);
상대덱생성(1);
}
});
문제 해결 after
if (현재코스트 < 데이터.cost) {
return 'end';
}
카드.addEventListener('click', function(card) {
if (턴) { //내 필드, 내턴
if (!데이터.mine || 데이터.field) {
return;
}
if (덱에서필드로(데이터, true) !== 'end') { //true = 내턴
내덱생성(1); //카드 한개 더 뽑기
}
} else { //상대방 필드 상대턴
if (데이터.mine || 데이터.field) { //내카드를 뽑을 경우,
return;
}
if (덱에서필드로(데이터, false) !== 'end') { //false = 상대턴
상대덱생성(1);
}
}
전체 script 코드
//변수를 딕셔너리 구조로 세팅
const 상대 = {
영웅: document.getElementById('rival-hero'),
덱: document.getElementById('rival-deck'),
필드: document.getElementById('rival-cards'),
코스트: document.getElementById('rival-cost'),
덱data: [],
영웅data: [],
필드data: [],
}
const 나 = {
영웅: document.getElementById('my-hero'),
덱: document.getElementById('my-deck'),
필드: document.getElementById('my-cards'),
코스트: document.getElementById('my-cost'),
덱data: [],
영웅data: [],
필드data: [],
}
const 턴버튼 = document.getElementById('turn-btn');
const 턴타입 = document.getElementById('turn-type');
let 턴 = true; //true는 나의 턴, false는 상대 턴
//리팩토링 함수
function 덱에서필드로(데이터, 내턴) { //스코프안에 데이터가 없음 ->
카드돔연결(데이터, 돔, 영웅)에서 데이터 선언을 가져와야함
let 객체 = 내턴 ? 나 : 상대; //삼항연산자 나 = true, 상대 = false
let 현재코스트 = Number(객체.코스트.textContent);
if (현재코스트 < 데이터.cost) {
return 'end';
}
let idx = 객체.덱data.indexOf(데이터);
객체.덱data.splice(idx, 1);
객체.필드data.push(데이터);
//화면 업데이트 구현이 어려워 전체 데이터 지웠다가 다시 필드, 덱 출력
객체.덱.innerHTML = '';
객체.필드.innerHTML = '';
객체.필드data.forEach(function(data) { //뽑은 카드 올라감
카드돔연결(data, 객체.필드);
});
객체.덱data.forEach(function(data) { //뽑은 카드는 배열에서 사라짐
카드돔연결(data, 객체.덱);
});
데이터.field = true; //필드에 올라간 카드(위에서 재클릭 방지)
객체.코스트.textContent = 현재코스트 - 데이터.cost;
}
//카드 화면 출력
function 카드돔연결(데이터, 돔, 영웅) {
let 카드 = document.querySelector('.card-hidden .card').cloneNode(true);
카드.querySelector('.card-cost').textContent = 데이터.cost;
카드.querySelector('.card-att').textContent = 데이터.att;
카드.querySelector('.card-hp').textContent = 데이터.hp;
//영웅일때 cost 감추기
if (영웅) {
카드.querySelector('.card-cost').style.display = 'none';
let 이름 = document.createElement('div');
이름.textContent = '영웅',
카드.appendChild(이름);
}
//클릭한 카드 덱에서 필드로 그대로 옮기기
카드.addEventListener('click', function(card) {
if (턴) { //내 필드, 내턴
if (!데이터.mine || 데이터.field) { //상대카드를 뽑을 경우, 필드에 있는 카드 클릭 방지
return;
}
if (덱에서필드로(데이터, true) !== 'end') { //true = 내턴
내덱생성(1); //카드 한개 더 뽑기
}
} else { //상대방 필드 상대턴
if (데이터.mine || 데이터.field) { //내카드를 뽑을 경우,
return;
}
if (덱에서필드로(데이터, false) !== 'end') { //false = 상대턴
상대덱생성(1);
}
}
});
돔.appendChild(카드);
}
function 상대덱생성(개수) {
for (let i = 0; i < 개수; i++) {
상대.덱data.push(카드공장());
}
//자바스크립트로 바뀐 데이터만 화면 출력시키는 것이 힘들기 때문에 다 지웠다가 출력
상대.덱.innerHTML = '';
상대.덱data.forEach(function(data) {
카드돔연결(data, 상대.덱);
})
};
function 내덱생성(개수) {
for (let i = 0; i < 개수; i++) {
나.덱data.push(카드공장(false, true)); //영웅 X, 내카드 O
}
//다 지웠다가 출력
나.덱.innerHTML = '';
나.덱data.forEach(function(data) {
카드돔연결(data, 나.덱);
});
};
function 내영웅생성() {
나.영웅data = 카드공장(true, true); //영웅 O, 내카드 O
카드돔연결(나.영웅data, 나.영웅, true);
};
function 상대영웅생성() {
상대.영웅data = 카드공장(true);
카드돔연결(상대.영웅data, 상대.영웅, true);
};
function 초기세팅() {
상대덱생성(5);
내덱생성(5);
내영웅생성();
상대영웅생성();
}
function Card(영웅, 내카드) { //문제해결 내카드 추가
if (영웅) {
this.att = Math.ceil(Math.random() * 2);
this.hp = Math.ceil(Math.random() * 5) + 25;
this.hero = true;
} else {
this.att = Math.ceil(Math.random() * 2);
this.hp = Math.ceil(Math.random() * 5);
this.cost = Math.floor((this.att + this.hp) / 2);
}
if (내카드) {
this.mine = true;
}
}
function 카드공장(영웅, 내카드) {
return new Card(영웅, 내카드);
}
//턴 넘기기
턴버튼.addEventListener('click', function() {
턴 = !턴; //true는 false로, false는 true로
if (턴) {
나.코스트.textContent = 10; //코스트 10으로 채우기
턴타입.innerHTML = '나의 턴'
} else {
상대.코스트.textContent = 10;
턴타입.innerHTML = '상대방 턴'
}
});
초기세팅();
</script>
반응형
'개발 > Javascript' 카테고리의 다른 글
[js] react로 구구단 게임 만들기(ft. 클래스 방식, cdn 설치) (0) | 2021.03.14 |
---|---|
[js] 카드 공격 게임 완성 (ft. 자바스크립트로 자스스톤 게임 구현 ver.4) (0) | 2021.03.12 |
[js] 생성자, 카드세팅 (ft. 자바스크립트로 자스스톤 게임 구현 ver.2) (0) | 2021.03.02 |
[js] 팩토리, 생성자 패턴, 카드세팅 (ft. 자바스크립트 자스스톤 게임 구현 ver.1) (0) | 2021.02.28 |
[js] 생성자 패턴/인스턴스(ft. this, 팩토리 패턴과의 비교) (0) | 2021.02.26 |
댓글