Web Dev/Game Development :: 게임개발

자바스크립트로 게임만들기(3/7) - Connect 4

HJPlumtree 2020. 5. 28. 23:46

밑의 글로 내려가기전 이 글을 먼저 읽어보는걸 추천 드립니다.

https://forgottenknowledge.tistory.com/entry/%EA%B2%8C%EC%9E%84-%EB%A7%8C%EB%93%A4%EB%A9%B0-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%B0%B0%EC%9A%B0%EA%B8%B007

 

게임 만들며 자바스크립트 배우기(0/7)

웹 개발을 독학하며 배우고 있습니다. FreeCodeCamp 커리큘럼을 따라가고 있고, 6개의 인증서를 다 받으면 풀스택이 될 수 있다고 하네요. 2번째 인증서까지 받았고 다음 부트스트랩으로 넘어가기전

forgottenknowledge.tistory.com

 

 

이번 게임은 조금 생소할 수도 있는 미국판 사목 Connect Four 입니다.

우리가 하는 5목과 비슷하게, 4개를 먼저 만들면 이기는 게임입니다.

돌을 밑에서부터 하나씩 채워가면서 플레이하게 됩니다.

 

 

 

 

밑의 코딩을 따라하면 이런 결과물이 나옵니다.

 

 

 

코딩에 들어가기전 준비물

전에 올린 게임과 달리 이미지 파일이 필요없습니다.

index.html / style.css / script.js 만 있으면 됩니다.

 

밑의 함수를 사용합니다

미리 알고 있으면 편하게 볼 수 있을겁니다.

• querySelector()

• addEventListener()

• onclick

• classList.contains()

• classList.add()

• For loops

• Arrow functions

 

그럼 HTML부터 시작합니다!

 

HTML

<html>
<head>
  <meta charset="utf-8">
  <title>Connect Four</title>
  
  //자바스크립트, css 연결
  <link rel="stylesheet" href="style.css">
  <script src="script.js" charset="utf-8"></script>
</head>

<body>
<h1>Connect Four</h1>

//현재 누구 차례인지 알려주기위해 기본 1과 빨강(🔴)으로 시작
<h3>Current Player: Player<span id="current-player">1</span> <span id="current-color">🔴</span></h3>

//게임판 6x7 크기지만 div 전체 49개 만들어주고 밑에 7개는 클래스 'taken'을 붙여준다.
<div class="grid">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div class="taken"></div>
  <div class="taken"></div>
  <div class="taken"></div>
  <div class="taken"></div>
  <div class="taken"></div>
  <div class="taken"></div>
  <div class="taken"></div>
</div>

//결과가 보여줄 곳
<h3 id="result">Have fun!</h3>



</body>

</html>

 

CSS

//마음에 드는 폰트를 바꿔주고, 문서 가운데 정렬
*{
  font-family: 'Trebuchet MS';
  text-align: center;
}

//제목 크기 변경
h1{
  font-size: 2.625rem;
}

//결과창 글자 크기변경
h3{
  font-size: 1.625rem;
}

//게임판
//안에들어갈 div에 맞게 크기를 정해준다.
//각 div에 border 크기를 1px로 해줘서 크기를 맞췄다
.grid{
  background-color: #FFE900;
  display: flex;
  flex-flow: row wrap;
  width: 434px;
  height: 372px;
  margin: 0 auto;
  
  //이 판의 크기를 넘어가는 div는 보이지 않는다.
  overflow: hidden;
}

//게임 돌 옵션
.grid div{
  width: 60px;
  height: 60px;
  background-color: #fff;
  
  //크기에 반을 둥글게해주면 원이 된다.
  border-radius: 30px;
  
  //border에 transparent 색상을 넣어주면 색상이 없다.
  border: 1px solid transparent;
}

//플레이어1 빨강
.player-one{
  background-color: red;
  border-radius: 30px;
}

//플레이어2 파랑
.player-two{
  background-color: blue;
  border-radius: 30px;
}

 

JAVASCRIPT

//기본 HTML이 로드, 파싱되고 실행되게 하기 위함
document.addEventListener("DOMContentLoaded", () =>{

  //미리 만든 css를 가져와서 변수에 저장
  const squares = document.querySelectorAll('.grid div');
  const result = document.querySelector('#result');
  const displayCurrentPlayer = document.querySelector('#current-player');
  const displayCurrentColor = document.querySelector('#current-color');

  //시작 플레이어는 1, 빨강
  var currentPlayer = 1;
  var currentColor = '🔴';

  //for 이용해서 돌이 들어갈 모든 장소를 돌림
  for(let i = 0; i < squares.length; i++) {
  
    //함수앞에 괄호 '('을 사용하면 부르지 않아도 실행
    (function(index){
    
      //각 자리가 클릭이 되면 밑의 함수 실행
      squares[index].onclick = function() {
        
        //제일 중요한 파트
        //html에 42개의 div가 아닌 49개 div을 만들었죠.
        //화면에는 맨밑 7개 'taken' 클래스 이름을 가진 div는 안보여요.
        //Connect four 라는 게임은 밑에서부터 깔아가면서 하는 게임
        //자기 돌 밑에 'taken'을 가진 div가 있으면 실행하게 하는 if
        if(squares[index + 7].classList.contains('taken')) {
        
          //그리고 플레이어가 1이면
          if(currentPlayer === 1){
          
            //현재 돌에 taken 클래스를 붙이고, CSS에서 만든 'player-one'를 붙이기
            squares[index].classList.add('taken');
            squares[index].classList.add('player-one');
            
            //사실 이코드로 코드가 깨끗하진 않습니다
            //처음 CSS에 .grid div에 색상을 주지 않으면 밑의 코드가 필요없어요.
            //배경색 흰색으로 자리를 표시하느라 밑의 코드로 플레이어 색상으로 덮어버리죠
            squares[index].style.backgroundColor = 'red';
            
            //이제 플레이어와 색상을 바꿔서 변수에 저장
            currentPlayer = 2;
            currentColor = '🔵';
            
            //화면에도 바뀐 플레이어 이름, 색상 표시
            displayCurrentPlayer.innerHTML = currentPlayer;
            displayCurrentColor.innerHTML = currentColor;
			
            
            //플레이어2일 때 실행되는 if 문, 1과 흡사해서 건너뜁니다.
          } else if(currentPlayer === 2) {
            squares[index].classList.add('taken');
            squares[index].classList.add('player-two');
            squares[index].style.backgroundColor = 'blue';
            currentPlayer = 1;
            currentColor = '🔴';
            displayCurrentPlayer.innerHTML = currentPlayer;
            displayCurrentColor.innerHTML = currentColor;
          }
          
          //자기 밑에 돌이 없으면 즉 [index + 7] div가 taken이 없으면 경고창으로 알림
        } else alert('can\'t go here');
      }
    })(i);
  }



  //게임돌을 확인해서 이겼는지 확인하는 함수
  function checkBoard() {
  
    //이기는 자리 조합을 배열에 넣어둔 겁니다.
    //이미 있는 것을 가져온거에요. 우리의 선생님 Ania Kubow 도
    const winningArr = [
      [0, 1, 2, 3], [41, 40, 39, 38], [7, 8, 9, 10], [34, 33, 32, 31], [14, 15, 16, 17], [27, 26, 25, 24], [21, 22, 23, 24],
      [20, 19, 18, 17], [28, 29, 30, 31], [13, 12, 11, 10], [35, 36, 37, 38], [6, 5, 4, 3], [0, 7, 14, 21], [41, 34, 27, 20],
      [1, 8, 15, 22], [40, 33, 26, 19], [2, 9, 16, 23], [39, 32, 25, 18], [3, 10, 17, 24], [38, 31, 24, 17], [4, 11, 18, 25],
      [37, 30, 23, 16], [5, 12, 19, 26], [36, 29, 22, 15], [6, 13, 20, 27], [35, 28, 21, 14], [0, 8, 16, 24], [41, 33, 25, 17],
      [7, 15, 23, 31], [34, 26, 18, 10], [14, 22, 30, 38], [27, 19, 11, 3], [35, 29, 23, 17], [6, 12, 18, 24], [28, 22, 16, 10],
      [13, 19, 25, 31], [21, 15, 9, 3], [20, 26, 32, 38], [36, 30, 24, 18], [5, 11, 17, 23], [37, 31, 25, 19], [4, 10, 16, 22],
      [2, 10, 18, 26], [39, 31, 23, 15], [1, 9, 17, 25], [40, 32, 24, 16], [9, 7, 25, 33], [8, 16, 24, 32], [11, 7, 23, 29],
      [12, 18, 24, 30], [1, 2, 3, 4], [5, 4, 3, 2], [8, 9, 10, 11], [12, 11, 10, 9], [15, 16, 17, 18], [19, 18, 17, 16],
      [22, 23, 24, 25], [26, 25, 24, 23], [29, 30, 31, 32], [33, 32, 31, 30], [36, 37, 38, 39], [40, 39, 38, 37], [7, 14, 21, 28],
      [8, 15, 22, 29], [9, 16, 23, 30], [10, 17, 24, 31], [11, 18, 25, 32], [12, 19, 26, 33], [13, 20, 27, 34]
      ];

	  //이기는 조합 배열을 처음부터 끝까지 돌리기
      for(let i = 0; i < winningArr.length; i++) {
      
        //이기는 조합 자리를 하나씩 변수에 저장
        const squares1 = squares[winningArr[i][0]];
        const squares2 = squares[winningArr[i][1]];
        const squares3 = squares[winningArr[i][2]];
        const squares4 = squares[winningArr[i][3]];

		//이기는 조합 자리에 모두 Player1이면 결과창에 축하한다는 메시지 출력
        if(squares1.classList.contains('player-one') &&
        squares2.classList.contains('player-one') &&
        squares3.classList.contains('player-one') &&
        squares4.classList.contains('player-one')) {
          result.innerHTML = 'Congratulations! Player 1 🔴 Wins!';
          
          //위와 마찬가지로 모두 Player2면 메시지 출력
        } else if(squares1.classList.contains('player-two') &&
        squares2.classList.contains('player-two')&&
        squares3.classList.contains('player-two')&&
        squares4.classList.contains('player-two')){
          result.innerHTML = 'Congratulations! Player 2 🔵 Wins!';
        }

      }
  }
  
  //게임판이 한번씩 클릭 될 때마다 위의 함수를 실행
  squares.forEach(square => square.addEventListener('click', checkBoard));
  

})