기술 관련/etc

지뢰찾기를 만들어보자 #6 - 게임 난이도 설정

ID 홍차 2022. 10. 2. 15:58

지난번 지뢰찾기의 사용성 개선에 대해 이야기 했었다. https://mc500.tistory.com/672 이번 글에서는 좀 더 게임답게 게임 설정 및 시작에 대한 메뉴를 만들어 보도록 하겠다.

지금까지는 정해진 크기와 지뢰 갯수만으로 게임을 할 수 있었고, 새로운 게임을 시작하려면 화면을 다시 로딩했어야 했다. 그래서 이와 관련된 메뉴를 추가해 보기로 하자. 필요한 기능은 다음과 같다.

  1. 게임 시작/종료 버튼
  2. 게임 난이도 선택 상자


게임 시작/종료 버튼의 기능은 다음과 같다.

  • 버튼을 눌러 새로운 게임을 시작한다
  • 게임 중에 누르면 게임을 포기하고 다시 새로운 게임을 시작한다


HTML에 기본 버튼을 추가하고 클릭 시 게임을 초기화 해보자

<h1>Mine Sweeper</h1>
<button @click="onClickMainButton">New Game</button>
<br><br>
<canvas id="base" width="480" height="320"></canvas>
onClickMainButton() {
  this.initGames()
},
initGames() {
  this.gameover = false
  this.cleared = 0
  this.target = this.width * this.height - this.mines    
  this.initBoxes()
  this.refreshAll()
},


다음으로 게임 난이도를 조절하는 부분을 추가해보자. 난이도는 게임판의 크기와 지뢰츼 개수가 결정하게 된다. 따라서 현재 상태 정보를 나보여 주는 부분을 추가해 보자.

<h1>Mine Sweeper</h1>
<button @click="onClickMainButton">New Game</button><br>
<br>
<div>
  {{width}}x{{height}} with {{mines}} mines
</div>
<br>
<canvas id="base" width="480" height="320"></canvas>

이제 사용자가 난이도 선택 할 수 있도록 선택 상자를 추가한다.

  • 초급 : 9x9, 10개
  • 중급 : 16x16, 40개
  • 고급 : 30x16, 99개
  <select id="levels" @change="onChangeLevel">
    <option value="beginner">Beginner</option>
    <option value="intermediate">Intermediate</option>
    <option value="expert">Expert</option>
  </select>
  &nbsp;
  {{width}}x{{height}} with {{mines}} mines
onChangeLevel(evt) {
  this.level = evt.target.value
  this.initGames()
},
const CONST_GAME_CONFIG = {
  beginner : {
    width: 9, height: 9, mines: 10
  },
  intermediate : {
    width: 16, height: 16, mines: 40
  },
  expert : {
    width: 30, height: 16, mines: 99
  }
}
  let cfg = CONST_GAME_CONFIG[this.level]
  if (!cfg) {
    cfg = CONST_GAME_CONFIG.beginner
  }

  this.width = cfg.width
  this.height = cfg.height
  this.mines  = cfg.mines

error

  217:7  error  Unexpected mutation of "width" prop   vue/no-mutating-props
  218:7  error  Unexpected mutation of "height" prop  vue/no-mutating-props
  219:7  error  Unexpected mutation of "mines" prop   vue/no-mutating-props


이는 위의 설정 값이 상위 영역에서 property 형태로 전달되었기 때문이다. 따라서, 이를 변경하려면 상위 영역인 App.vue에 이벤트를 보내서 해당 정보를 변경해야 한다. 이는 나중에 할 숙제로 남겨두고 지금은 property에서 data 값으로 변경한다.

  width: CONST_GAME_CONFIG.beginner.width,
  height: CONST_GAME_CONFIG.beginner.height,
  mines: CONST_GAME_CONFIG.beginner.mines,

근데, 선택 상자의 값을 바꾸면 설정 값도 변하는 것은 눈에 보이지만 게임 화면은 그대로인 것을 볼 수 있다. 이는 처음 시작할 때 설정된 정보로 화면도 구성된 상태로 고정되기 때문이다. 따라서, 난이도 변경과 함께 게임판도 변경해 주어야 한다. 이를 위해 intiGame에 코드를 더 추가한다.

this.canvas.width = this.width * this.box_width
this.canvas.height = this.height * this.box_width

또한, 처음 게임이 초기화 되는 부분과 나중에 새게임으로 시작하는 부분은 이벤트 처리 부분을 제외하면 상당 부분이 중복된다. 따라서, initGames() 호출로 초기화 되는 부분은 삭제하고 initGames()를 호출하는 형태로 구성한다.

게임 난이도 조절
다음은 게임 승리 시간에 대해서