분류 javascript

JavaScript로 지뢰 찾기를 구축하는 방법

컨텐츠 정보

  • 조회 247 (작성일 )

본문

마지막 포스트에서는 JavaScript를 사용하여 만든 틱택 토 게임을 보여 주었고 그 전에는 일치하는 게임을 만들었습니다. 이번 주 게시물에서는 복잡성을 조금씩 늘리기로 결정했습니다. JavaScript를 사용하여 지뢰 찾기를 작성하는 방법을 배우려고 합니다. 또한 HTML과 상호 작용하는 데 도움이 되는 JavaScript 라이브러리 인 jQuery를 사용했습니다. 선행 달러 기호가 있는 함수 호출이 표시되면 jQuery가 작동합니다. 그것에 대해 더 배우고 싶다면 설명서가 매우 좋습니다.


https://mitchum.blog/how-to-build-minesweeper-with-javascript 


지뢰 찾기를 하려면 여기를 클릭하십시오! 제어 체계로 인해 데스크톱 컴퓨터에서 재생하려고 합니다.


게임을 만드는 데 필요한 세 가지 파일은 다음과 같습니다.


JavaScript로 지뢰 찾기를 작성하는 방법을 배우려면 첫 번째 단계는 게임 작동 방식을 이해하는 것입니다. 바로 뛰어 들어 규칙에 대해 이야기합시다.


게임의 규칙 

  1. 지뢰 찾기 보드는 10 x 10 정사각형입니다. 클래식 Windows 버전과 같은 다른 크기로 만들 수도 있지만 데모 목적으로 게임의 더 작은 "초보자"버전을 고수 할 것입니다.
  2. 보드에는 미리 정해진 수의 무작위로 배치 된 광산이 있습니다. 플레이어가 볼 수 없습니다.
  3. 셀은 열린 상태 또는 닫힌 상태 중 하나에 존재할 수 있습니다. 셀을 클릭하면 열립니다. 광산이 숨어 있었다면 게임은 실패로 끝납니다. 셀에 광산이 없지만 하나 이상의 인접 셀에 광산이 있는 경우 열린 셀에 인접 광산 수가 표시됩니다. 셀의 이웃이 채굴 되지 않으면 해당 셀 각각이 자동으로 열립니다.
  4. 셀을 마우스 오른쪽 버튼으로 클릭하면 플래그가 표시됩니다. 깃발은 플레이어가 그곳에 숨어있는 광산이 있음을 알고 있음을 나타냅니다.
  5. 열린 셀을 클릭하는 동안 Ctrl 버튼을 누르고 있으면 약간 복잡한 규칙이 있습니다. 셀 주변의 플래그 수가 인접 광산 수와 일치하고 각 플래그 지정된 셀에 실제로 광산이 포함 된 경우 닫히고 닫히지 않은 모든 인접 셀이 자동으로 열립니다. 그러나 이러한 플래그 중 하나라도 잘못된 셀에 배치 된 경우 게임이 실패합니다.
  6. 광산 없이 모든 세포를 열면 플레이어가 게임에서 승리합니다.

데이터 구조 


Cell 

JavaScript code for a minesweeper cell 

지뢰 찾기 셀을 나타내는 JavaScript 코드.​ 


각 셀은 여러 속성이 있는 개체입니다.

  • id : 행과 열을 포함하는 문자열. 이 고유 식별자를 사용하면 필요할 때 신속하게 셀을 쉽게 찾을 수 있습니다. 주의 깊게 살펴보면 id와 관련된 몇 가지 지름길이 있음을 알 수 있습니다. 보드 크기가 작기 때문에 이러한 단축키를 피할 수 있지만 이러한 기술은 더 큰 보드로 확장되지 않습니다. 당신이 그들을 발견 할 수 있는지 확인하십시오. 그렇다면 의견에 지적하십시오!
  • row : 보드 내에서 셀의 가로 위치를 나타내는 정수입니다.
  • column : 보드 내에서 셀의 세로 위치를 나타내는 정수입니다.
  • opened : 셀이 열렸는지 여부를 나타내는 부울 속성입니다.
  • flagged : 플래그가 셀에 배치되었는지 여부를 나타내는 다른 부울 특성입니다.
  • mined : 셀이 채굴 되었는지 여부를 나타내는 또 다른 부울 속성.
  • neighborMineCount : 광산을 포함하는 인접 셀의 수를 나타내는 정수.


Board 

JavaScript code for the minesweeper board 

게임 보드를 나타내는 JavaScript 코드. 


내가 만든 뱀 게임과 마찬가지로 우리 보드는 셀 모음입니다. 우리는 여러 가지 방법으로 보드를 대표 할 수 있습니다. 키 값 쌍이있는 객체로 표시하기로 선택했습니다. 앞에서 보았 듯이 각 셀에는 ID가 있습니다. 보드는 이러한 고유 키와 해당 셀 사이의 매핑입니다.


보드를 만든 후에는 두 가지 작업을 더 수행해야 합니다. 지뢰를 무작위로 할당하고 주변 광산 수를 계산합니다. 다음 섹션에서 이러한 작업에 대해 자세히 설명합니다.


알고리즘 


무작위로 광산 할당 

JavaScript code for randomly assigning mines 

셀에 무작위로 광산을 할당하기 위한 JavaScript 코드. 


지뢰 찾기 게임을 하기 전에 가장 먼저 해야 할 일은 지뢰를 세포에 할당하는 것입니다. 이를 위해 보드와 원하는 광산 수를 매개 변수로 사용하는 함수를 만들었습니다.


우리가 배치 할 때마다 무작위 행과 열을 생성해야 합니다. 또한 동일한 행과 열 조합이 두 번 이상 나타나지 않아야 합니다. 그렇지 않으면 우리는 원하는 수의 광산보다 적은 양으로 끝납니다. 중복이 나타나면 난수 생성을 반복해야 합니다.


각 임의의 셀 좌표가 생성되면 보드의 해당 셀에 대해 마이닝 속성을 true로 설정합니다.


원하는 범위 내에서 난수를 생성하는 작업을 돕기 위해 도우미 함수를 만들었습니다. 아래를 보십시오 :

JavaScript code for random integer generator. 

난수 생성을 위한 도우미 함수. 


이웃 광산 수 계산 

calculateneighborminecounts-1.png?w=740&ssl=1 

각 셀의 주변 광산 수를 계산하기 위한 JavaScript 코드. 


이제 보드에서 각 셀의 주변 광산 수를 계산하는 데 필요한 사항을 살펴 보겠습니다.


우리는 보드의 각 행과 열을 반복하면서 매우 일반적인 패턴으로 시작한다는 것을 알 수 있습니다. 이를 통해 각 셀에서 동일한 코드를 실행할 수 있습니다.


먼저 각 셀이 채굴 되었는지 확인합니다. 그렇다면 주변 광산 수를 확인할 필요가 없습니다. 결국, 플레이어가 그것을 클릭하면 게임을 잃게 됩니다!


만약 전지가 채굴 되지 않았다면, 주변에 얼마나 많은 광산이 있는지 볼 필요가 있습니다. 가장 먼저 하는 일은 getNeighbors 도우미 함수를 호출하는 것인데,이 함수는 인접 셀의 ID 목록을 반환합니다. 그런 다음이 목록을 반복하여 광산 수를 합산하고 셀의 neighborMineCount 속성을 적절하게 업데이트합니다.


당신은 내 이웃이 아니십니까?


getNeighbors 함수를 자세히 살펴 보겠습니다. 코드 전체에서 여러 번 사용됩니다. 앞서 디자인 선택 중 일부가 더 큰 보드 크기로 확장되지 않는다고 언급했습니다. 지금 시도하고 발견하기에 좋은 시간입니다.

getneighbors.png?w=740&ssl=1 

지뢰 찾기 셀의 모든 인접 ID를 가져 오기 위한 JavaScript 코드. 


이 함수는 셀 ID를 매개 변수로 사용합니다. 그런 다음 즉시 행과 열에 대한 변수를 갖도록 두 조각으로 나눕니다. JavaScript에 내장 된 parseInt 함수를 사용하여 이러한 변수를 정수로 바꿉니다. 이제 수학 연산을 수행 할 수 있습니다.


다음으로 행과 열을 사용하여 각 인접 셀의 잠재적 ID를 계산하고 목록으로 푸시합니다. 특수 시나리오를 처리하기 위해 정리하기 전에 목록에 8 개의 ID가 있어야 합니다.


일반적인 경우에는 문제가 없지만 걱정해야 할 특별한 경우가 있습니다. 즉, 게임 보드의 경계를 따라있는 셀입니다. 이  셀들은 이웃이 8 개 미만입니다.


이를 처리하기 위해 이웃 ID 목록을 반복하고 길이가 2보다 큰 ID를 제거합니다. 모든 유효하지 않은 이웃은 -1 또는 10이되므로 이 작은 검사는 문제를 훌륭하게 해결합니다.

neighborsexample.png?w=740&ssl=1 

지뢰 찾기 셀과 그 이웃.


또한 리스트에서 ID를 제거 할 때마다 인덱스 변수를 동기화 하기 위해 인덱스 변수를 줄여야 합니다.


채굴되어 있습니까?


이 섹션에서 마지막으로 살펴볼 기능은 isMined입니다.

JavaScript function that checks if a cell is mined. 

셀이 마이닝 되었는지 확인하는 JavaScript 함수입니다. 


isMined 함수는 매우 간단합니다. 셀이 마이닝 되었는지 여부 만 확인합니다. 이 함수는 마이닝 된 경우 1을, 마이닝 하지 않은 경우 0을 반환합니다. 이 기능을 사용하면 루프에서 반복해서 호출 할 때 함수의 반환 값을 요약 할 수 있습니다.


그것은 지뢰 찾기 게임 보드를 설정하기 위한 알고리즘을 마무리합니다. 실제 게임 플레이로 넘어 갑시다.


셀 열기 

JavaScript code that executes when a minesweeper cell is opened. 

지뢰 찾기 셀이 열릴 때 실행되는 JavaScript 코드입니다. 


플레이어가 셀을 클릭 할 때마다 이 기능을 실행합니다. 많은 작업을 수행하며 재귀라는 것을 사용합니다. 개념에 익숙하지 않은 경우 아래 정의를 참조하십시오.


Recursion: See recursion.


아, 컴퓨터 과학 농담. 그들은 항상 술집과 커피 숍에서 잘 지나 갑니다. 당신은 정말 당신이 분쇄하고 있던 귀염둥이에 그들을 시도해야 합니다.


어쨌든 재귀 함수는 그 자체를 호출하는 함수일뿐입니다. 스택 오버플로가 발생하기를 기다리는 것 같습니다. 그렇기 때문에 후속 재귀 호출 없이 값을 반환하는 기본 사례가 필요합니다. 우리의 함수는 더 이상 열려야 할 셀이 없기 때문에 결국 자체 호출을 중단합니다.


재귀가 실제 프로젝트에서 올바른 선택은 아니지만 도구 상자에 유용한 도구입니다. 우리는 재귀 없이 이 코드를 작성할 수 있었지만, 여러분 모두가 실제로 코드의 예를 보고 싶을 것이라고 생각했습니다.


HANDLE CLICK EXPLAINED


handleClick 함수는 셀 ID를 매개 변수로 사용합니다. 플레이어가 셀을 클릭하는 동안 Ctrl 버튼을 누른 경우를 처리 해야하지만 이후 섹션에서 이에 대해 이야기 할 것입니다.


게임이 끝나지 않고 기본 왼쪽 클릭 이벤트를 처리한다고 가정하면 몇 가지 확인해야 합니다. 플레이어가 이미 셀을 열거 나 플래그를 지정한 경우 클릭을 무시하고 싶습니다. 이미 플래그가 지정된 셀을 부정확하게 클릭하면 게임이 종료되면 플레이어에게는 실망스러울 것입니다.


둘 중 하나라도 해당되지 않으면 계속 진행합니다. 셀에 광산이 있으면 게임 오버 로직을 시작하고 폭발 된 광산을 빨간색으로 표시해야 합니다. 그렇지 않으면, 우리는 세포를 열 것입니다.


열린 셀에 주변에 지뢰가 있으면 주변 광산 수를 플레이어에 적절한 글꼴 색으로 표시합니다. 셀 주변에 지뢰가 없다면 재귀가 시작될 때입니다. 셀의 배경색을 약간 어두운 회색 음영으로 설정 한 후, 플래그 없이 열린 각 인접 셀에 대해 handleClick을 호출합니다.


HELPER FUNCTIONS


handleClick 함수 내부에서 사용 중인 도우미 함수를 살펴 보겠습니다. 우리는 이미 getNeighbors에 대해 이야기 했으므로 건너 뛸 것입니다. 손실 기능부터 시작하겠습니다.

JavaScript code that gets called whenever the player has lost at minesweeper. 

플레이어가 게임을 잃을 때마다 호출되는 JavaScript 코드. 


손실이 발생하면 이를 추적하는 변수를 설정 한 다음 플레이어에게 게임이 끝났다는 메시지를 표시합니다. 또한 각 셀을 반복하고 광산 위치를 표시합니다. 그런 다음 시계를 멈 춥니 다.


둘째, getNumberColor 함수가 있습니다. 이 기능은 주변 광산 수에 해당하는 색상을 제공합니다.


JavaScript code that gets passed a number and returns a color. 

숫자를 전달 받고 색상을 반환하는 JavaScript 코드입니다. 


고전적인 Windows 버전의 지뢰 찾기처럼 색상을 일치 시키려고 했습니다. 여기에 switch 문을 사용해야 했을 수도 있지만 이미 스크린 샷을 찍었으므로 별 문제가 되지 않습니다. 셀에 플래그를 넣을 때의 코드 모양으로 넘어 갑시다.


Flagging A Cell 


JavaScript code for putting a flag on a minesweeper cell. 

지뢰 찾기 셀에 플래그를 넣는 JavaScript 코드. 


셀을 마우스 오른쪽 버튼으로 클릭하면 플래그가 표시됩니다. 플레이어가 빈 셀을 마우스 오른쪽 버튼으로 클릭하고 플래그를 지정해야 할 지뢰가 더 있으면 셀에 빨간색 플래그를 표시하고 플래그가 지정된 속성을 true로 업데이트 한 다음 남아있는 지뢰 수를 줄입니다. 셀에 이미 플래그가 있다면 반대의 행동을 합니다. 마지막으로, 남은 광산 수를 표시하도록 GUI를 업데이트합니다.


주변 셀 열기 


JavaScript code for handling ctrl + left click 

Ctrl + 왼쪽 클릭 처리를 위한 JavaScript 코드 


셀을 여는 작업과 플래그로 표시하는 작업을 다루었으므로 플레이어가 수행 할 수 있는 마지막 작업 인 이미 열려있는 셀의 인접한 셀을 여는 방법에 대해 이야기하겠습니다. handleCtrlClick 함수에는 이에 대한 논리가 포함되어 있습니다. 이 플레이어는 ctrl 키를 누른 상태에서 인접 광산이 포함 된 열린 셀을 마우스 왼쪽 버튼으로 클릭하여 이 작업을 수행 할 수 있습니다.


이러한 조건을 확인한 후 가장 먼저 해야 할 일은 인접 플래그가 지정된 셀 목록을 작성하는 것입니다. 플래그가 지정된 셀의 수가 실제 주변 광산의 수와 일치하면 계속 진행할 수 있습니다. 그렇지 않으면 아무것도 하지 않고 함수를 종료합니다.


진행할 수 있다면 다음으로 플래그가 지정된 셀에 광산이 포함되어 있지 않은지 확인합니다. 이것이 사실이라면, 우리는 플레이어가 광산 위치를 잘못 예측했으며, 깃발이 붙어 있지 않은 모든 인접 셀을 클릭하면 손실로 끝날 것입니다. 로컬 손실 변수를 설정하고 손실 함수를 호출해야 합니다. 이 기사의 앞부분에서 손실 기능에 대해 이야기했습니다.


플레이어가 패배하지 않았다면, 플래 깅되지 않은 이웃 셀을 열어야 합니다. 우리는 단순히 그것들을 반복하고 각각에 handleClick 함수를 호출해야 합니다. 그러나 실수로 handleCtrlClick 함수에 빠지지 않도록 ctrlIsPressed 변수를 false로 설정해야 합니다.


새로운 게임 시작 


지뢰 찾기를 구축하는 데 필요한 모든 JavaScript를 분석했습니다. 우리가 남긴 것은 새 게임을 시작하는 데 필요한 초기화 단계입니다.


JavaScript code for initializing minesweeper 

지뢰 찾기 초기화를 위한 JavaScript 코드 


가장 먼저 할 일은 몇 가지 변수를 초기화하는 것입니다. 플래그와 광산 아이콘에 대한 html 코드를 저장하기 위한 상수가 필요합니다. 또한 보드 크기, 광산 수, 타이머 값 및 남은 광산 수를 저장하기 위한 상수가 필요합니다.


또한 플레이어가 ctrl 버튼을 누르면 저장을 위한 변수가 필요합니다. jQuery를 사용하여 이벤트 핸들러를 문서에 추가하며 이 핸들러는 ctrlIsPressed 변수를 설정합니다.


마지막으로 newGame 함수를 호출하고 이 함수를 새로운 게임 버튼에 바인딩합니다.


도우미 함수 

JavaScript code for starting a new game of minesweeper. 

새로운 지뢰 찾기 게임을 시작하기 위한 JavaScript 코드. 


newGame 함수는 게임이 플레이 준비 상태에 있도록 변수를 재설정 하는 역할을 합니다. 여기에는 플레이어에 표시되는 값을 재설정하고 initializeCells를 호출하고 새로운 임의 보드를 만드는 것이 포함됩니다. 또한 매 초 마다 업데이트 되는 시계 재설정이 포함됩니다.


initializeCells를 살펴보고 내용을 마무리하겠습니다.


JavaScript code for attaching click handlers to minesweeper cells. 

클릭 핸들러를 셀에 첨부하고 승리 조건을 확인하기 위한 JavaScript 코드. 


이 함수의 주요 목적은 HTML 게임 셀에 추가 속성을 추가하는 것입니다. 각 셀에는 게임 로직에서 쉽게 액세스 할 수 있도록 적절한 ID가 추가 되어야 합니다. 모든 셀에는 스타일 상의 이유로 적용된 배경 이미지가 필요합니다.


또한 왼쪽 및 오른쪽 클릭을 감지 할 수 있도록 모든 셀에 클릭 핸들러를 연결해야 합니다.


왼쪽 클릭을 처리하는 함수는 적절한 id를 전달하여 handleClick을 호출합니다. 그런 다음 광산이 없는 모든 셀이 열려 있는지 확인합니다. 이것이 사실이라면 플레이어가 게임에서 이겼으며 우리는 그를 축하 할 수 있습니다.


오른쪽 클릭을 처리하는 함수는 적절한 ID를 전달하여 handleRightClick을 호출합니다. 그런 다음 단순히 false를 반환합니다. 이로 인해 상황에 맞는 메뉴가 나타나지 않고 웹 페이지를 마우스 오른쪽 버튼으로 클릭하는 것이 기본 동작입니다. 표준 비즈니스 CRUD 응용 프로그램에는 이런 종류의 작업을 수행하고 싶지 않지만 지뢰 찾기에는 적합합니다.


결론 


JavaScript로 지뢰 찾기를 구축하는 방법을 배우 신 것을 축하합니다! 그것은 많은 코드였지만, 이런 식으로 모듈로 나눈 후에 의미가 있습니다. 이 프로그램의 재사용 성, 확장 성 및 가독성을 확실히 향상 시킬 수 있었습니다. 또한 HTML이나 CSS를 자세히 다루지 않았습니다. 궁금한 점이 있거나 코드를 개선 할 수 있는 방법이 있다면 의견을 듣고 싶습니다.


이 게시물을 통해 JavaScript로 좋은 프로그램을 작성하는 방법에 대해 더 배우고 싶다면 전설적인 Douglas Crockford의 JavaScript : The Good Parts를 추천합니다. 남자는 JSON을 데이터 교환 형식으로 대중화했으며 실제로 웹 발전에 크게 기여했습니다.


언어는 수년에 걸쳐 극적으로 개선되었지만 개발 역사로 인해 여전히 이상한 속성을 가지고 있습니다. 이 책은 글로벌 네임스페이스와 같이 보다 의심스러운 디자인 선택을 탐색하는 데 도움이 되는 훌륭한 작업을 수행합니다. 언어를 처음 배울 때 도움이 되었습니다.