Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Fake User List</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
</head>

<body>
  
  <div id="game-bg">
    <div id="customized-zone" class="border-style-outer">
      <div id="customized-zone-title">Customize your own Minesweeper</div>
      <div id="show-input-container">
        <div id="show-input-row" class="show-input">Row</div>
        <div id="show-input-col" class="show-input">Column</div>
        <div id="show-input-bomb-number" class="show-input">Bomb Number</div>
      </div>
      <div id="customized-input-create">
        <input type="text" class="customized-input" id="customized-input-row" placeholder="row size">
        <input type="text" class="customized-input" id="customized-input-col" placeholder="column size">
        <input type="text" class="customized-input" id="customized-input-bomb-number" placeholder="bomb number">
        <buttton id="customized-create-btn" class="btn btn-danger">create</buttton>
      </div>
    </div>
    <div id="main-area" class="border-style-outer">
      <div id="status-bar" class="border-style-inner">
        <div id="remain-bomb" class="numeral-zone">
          <div id="remain-bomb-number-container"></div>
        </div>
        <div class="border-style-outer"><i id="face-btn" class="far fa-smile"></i></div>
        <div id="clock" class="numeral-zone">
          <div id="clock-number-container"></div>
        </div>
      </div>
      <div id="click-zone" class="border-style-inner"></div>
    </div>
  </div>
  
  <!-- for using axios and bootstrap -->
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
    integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
    crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"
    integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ"
    crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"
    integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm"
    crossorigin="anonymous"></script>
  <script src="index.js"></script>
</body>

</html>
              
            
!

CSS

              
                #game-bg {
  background-color: #8E8E8E;
  min-height: 100vh;
  padding: 2vh 0px;
}

#customized-zone {
  width: 500px;
  height: 120px;
  margin: 0 auto;  
  background-color: #D0D0D0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

#customized-zone-title {
  font-size: 25px;
  font-weight: 700;
  margin-bottom: 3px;
}

#show-input-container{
  display: flex;
  justify-content: flex-start;
  align-items: center;
  width: 100%;
}

.show-input {
  font-size: 16px;
  font-weight: 700;
  width: 25%; 
  margin: 0 7px;
}

#customized-input-create {
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.customized-input {
  width: 25%;
  height: 100%;
}

#main-area {
  width: 358px;
  margin: 1vh auto;  
  background-color: #D0D0D0;
  padding: 15px;
}

#status-bar {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  margin: 0px auto;
  margin-bottom: 15px;
  padding: 5px 10px;
}

.numeral-zone {
  background-color: #000000;
  height: 52px;
  display: flex;
  align-items: center;
}

#clock-number-container, #remain-bomb-number-container {
  height: 46px;
  display: flex;
  align-items: center;
  margin: 0 5px;
}

#clock-number-container > *, #remain-bomb-number-container > * {
  margin: 0 2px;
}

#face-btn {
  font-size: 40px;
  line-height: 40px;
  border-radius: 50%;
  background-color: #F9F900;
  margin: 3px;
}

#click-zone {
  height: 322px;
  margin: 0px auto;
}

.border-style-inner {
  border-top: 3px solid #5B5B5B;
  border-right: 3px solid #FCFCFC;
  border-bottom: 3px solid #FCFCFC;
  border-left: 3px solid #5B5B5B;
}

.border-style-outer {
  border-top: 3px solid #FCFCFC;
  border-right: 3px solid #5B5B5B;
  border-bottom: 3px solid #5B5B5B;
  border-left: 3px solid #FCFCFC;
}

.box {
  width: 35px;
  height: 35px;
  font-size: 24px;
  line-height: 30px;
  font-weight: 900;
  text-align: center;
/*   when opened */
  border: 1px solid #5B5B5B;
  background-color: #ADADAD;
}

.opened-box {
  border: 1px solid #5B5B5B;
}

.covered-box {
  border-top: 3px solid #FCFCFC;
  border-right: 3px solid #5B5B5B;
  border-bottom: 3px solid #5B5B5B;
  border-left: 3px solid #FCFCFC;
  background-color: #D0D0D0;
}

.opened-bomb {
  background-color: #FF2D2D;
}

.flag {
  color: #FF2D2D;
}

.question {
  color: #3C3C3C;
}

/* color of number of bomb */
.color-number-1 {
  color: #2828FF;
}

.color-number-2 {
  color: #009100;
}

.color-number-3 {
  color: #FF0000;
}

.color-number-4 {
  color: #3A006F;
}

.color-number-5 {
  color: #842B00;
}

.color-number-6 {
  color: #007979;
}

.color-number-7 {
  color: #272727;
}

.color-number-8 {
  color: #8E8E8E;
}

/* ------------------------------------- */
/* for digital clock number */
.number-template {
  position: relative;
  margin: 0 0.5%;
  overflow: hidden;
}

.number-part {
  width: 100%;
  height: 100%;
  position: absolute;
  padding: 0 10%;
}

.number-part-1 {
  transform: translate(0%, -45%);
}

.number-part-2 {
  transform: rotate(-90deg) translate(45%, -20%);
}

.number-part-3 {
  transform: rotate(-90deg) translate(45%, 20%);
}

.number-part-4 {
  transform: translate(0%, 0%);
}

.number-part-5 {
  transform: rotate(-90deg) translate(-45%, -20%);
}

.number-part-6 {
  transform: rotate(-90deg) translate(-45%, 20%);
}

.number-part-7 {
  transform: translate(0%, 45%);
}

.number-part-component {
  width: 100%;
  height: 50%;
  border-style: solid;
  border-color: rgba(0,0,0,0);
}

.number-part-component-1 {
  border-bottom-color: red;
}

.number-part-component-2 {
  border-top-color: blue;
}

* {
/*   border:1px solid; */
}

body {
  /*   文字不會被選取 */
  user-select: none;
}

              
            
!

JS

              
                const GAME_STATE = {
  FirstClickAwaits: "FirstClickAwaits",
  GamePlaying: "GamePlaying",
  GameFinished: "GameFinished",
}

const model = {
  sizeRow: 9,
  sizeCol: 9,
  bombNumber: 10,
  bombPosition: [],
  boxType: {},  //box-8-7: number 1-9, bomb or empty  
  openEmptyBoxesIdArray: [],
  tempEmptyBoxesIdArray: [],
  openNumberBoxesIdArray: [],  
  countTime: 0,
}

const view = {
  buildClickZone() {
    const clickZone = document.querySelector("#click-zone");
    let htmlContent = "";
    for (let i = 1; i <= model.sizeRow; i++) {
      htmlContent += `<div class="each-row d-flex flex-row">`;
      for (let j = 1; j <= model.sizeCol; j++) {
        htmlContent += `<div id="box-${i}-${j}" class="box covered-box"></div>`;
      }
      htmlContent += `</div>`;
    }
    clickZone.innerHTML = htmlContent;
  },
  removeCoverAndShowNumber() {
    model.openEmptyBoxesIdArray.forEach(boxId => {
      const boxHTML = document.querySelector(`#${boxId}`);
      boxHTML.classList.remove("covered-box");
      boxHTML.classList.remove("flag");
      boxHTML.classList.remove("question");
      boxHTML.innerHTML = "";
    });
    model.openNumberBoxesIdArray.forEach(boxId => {
      const boxHTML = document.querySelector(`#${boxId}`);
      boxHTML.classList.remove("covered-box");
      boxHTML.classList.remove("flag");
      boxHTML.classList.remove("question");
      controller.addNumberColorClass(boxId);
      boxHTML.innerHTML = model.boxType[boxId];
    });
    // 同時清空array
    model.openEmptyBoxesIdArray.splice(0, model.openEmptyBoxesIdArray.length);
    model.openNumberBoxesIdArray.splice(0, model.openNumberBoxesIdArray.length);
  },
  showBomb() {
    model.bombPosition.forEach(bombBoxPosition => {
      const boxHTML = document.querySelector(`#${bombBoxPosition}`);
      boxHTML.classList.remove("covered-box");
      boxHTML.classList.remove("flag");
      boxHTML.classList.remove("question");
      // boxHTML.classList.add("opened-bomb");
      boxHTML.innerHTML = `<i class="fas fa-bomb"></i>`;
    });
  },
  showClickedBombBG(boxHTML) {
    boxHTML.classList.add("opened-bomb");
  },
  showCryFace() {
    const facrBtnHTML = document.querySelector("#face-btn");
    facrBtnHTML.classList.remove("fa-smile");
    facrBtnHTML.classList.add("fa-dizzy");
  },
  showWinFace() {
    const facrBtnHTML = document.querySelector("#face-btn");
    facrBtnHTML.classList.remove("fa-smile");
    facrBtnHTML.classList.add("fa-laugh-beam");
  },
  resetFace() {
    const facrBtnHTML = document.querySelector("#face-btn");
    facrBtnHTML.classList.remove("fa-dizzy");
    facrBtnHTML.classList.remove("fa-laugh-beam");
    facrBtnHTML.classList.add("fa-smile");
  },
  showRemainBombNumber() {
    const remainBombContainerHTML = document.querySelector("#remain-bomb-number-container");
    // 目前不處理大於1000情形
    const remainBombNumber = controller.calculateRemainBombNumber() % 1000;
    const hundredthNumber = Math.floor(remainBombNumber / 100);
    const tenthNumber = Math.floor(remainBombNumber % 100 / 10);
    const digitNumber = remainBombNumber % 10;
    remainBombContainerHTML.innerHTML = "";    
    remainBombContainerHTML.append(utility.createDigitalClockNumber(remainBombContainerHTML, hundredthNumber));
    remainBombContainerHTML.append(utility.createDigitalClockNumber(remainBombContainerHTML, tenthNumber));
    remainBombContainerHTML.append(utility.createDigitalClockNumber(remainBombContainerHTML, digitNumber));  
  },
  showCountTime() {
    const clockNumberContainer = document.querySelector("#clock-number-container");
    // 處理顯示,目前不處理大於1000情形
    const time = model.countTime % 1000;
    const hundredthNumber = Math.floor(time / 100);
    const tenthNumber = Math.floor(time % 100 / 10);
    const digitNumber = time % 10;
    clockNumberContainer.innerHTML = "";    
    clockNumberContainer.append(utility.createDigitalClockNumber(clockNumberContainer, hundredthNumber));
    clockNumberContainer.append(utility.createDigitalClockNumber(clockNumberContainer, tenthNumber));
    clockNumberContainer.append(utility.createDigitalClockNumber(clockNumberContainer, digitNumber));        
  },
  showFlagOnBombBox() {
    model.bombPosition.forEach(bombBoxPosition => {
      const boxHTML = document.querySelector(`#${bombBoxPosition}`);
      boxHTML.classList.add("flag");
      boxHTML.innerHTML = `<i class="far fa-flag"></i>`;
    });
  },
  adjustMainAreaSize() {
    const mainArea = document.querySelector("#main-area");
    const width = 35 * model.sizeCol + 43;
    mainArea.style.width = `${width}px`;
    const clickZone = document.querySelector("#click-zone");
    const height = 35 * model.sizeRow + 7;
    clickZone.style.height = `${height}px`;;
  },
}

const controller = {
  currentState: GAME_STATE.FirstClickAwaits,
  clickBox(boxHTML) {
    switch (this.currentState) {
      case GAME_STATE.FirstClickAwaits:
        // 產生bomb position array並記錄於boxType
        this.createBombPositionArrayAndRecordBoxType(boxHTML.id);
        // 計算所有box該顯示的數字(顯示周圍炸彈數量)
        this.calculateBoxNumberAndRecordBoxType(model.bombPosition);
        // 如果是empty box,但第一格一定是empty
        // 找出empty box
        // 找出number box
        model.tempEmptyBoxesIdArray.push(boxHTML.id);
        this.openBoxAction();
        // remove cover and show number
        view.removeCoverAndShowNumber();
        // count time
        model.timeCounter = setInterval(function () {
          controller.countTime();
          view.showCountTime();
        }, 1000)
        // change state
        this.currentState = GAME_STATE.GamePlaying;
        break;
      case GAME_STATE.GamePlaying:
        const boxType = model.boxType[boxHTML.id];
        if (boxType === undefined) {
          model.tempEmptyBoxesIdArray.push(boxHTML.id);
          this.openBoxAction();
          view.removeCoverAndShowNumber();
        } else if (boxType === "bomb") {
          view.showBomb();
          // 修正為只有被點到的炸彈會顯示紅色底色背景
          view.showClickedBombBG(boxHTML);
          view.showCryFace();
          // pause time
          clearInterval(model.timeCounter);
          this.currentState = GAME_STATE.GameFinished;
          return;
        } else {
          boxHTML.classList.remove("covered-box");
          boxHTML.innerHTML = model.boxType[boxHTML.id];
          this.addNumberColorClass(boxHTML.id);
        }      
        break;
    }
    // check win
    if (this.isWin()) {
      view.showWinFace();
      view.showFlagOnBombBox();
      // pause time
      clearInterval(model.timeCounter);
      this.currentState = GAME_STATE.GameFinished;
    }
  },
  createBombPositionArrayAndRecordBoxType(firstClickBoxId) {
    for (let i = 1; i <= model.bombNumber; i++) {
      const randomBombBoxId = this.createRandomBombBoxId(firstClickBoxId);
      model.bombPosition.push(randomBombBoxId);
      model.boxType[randomBombBoxId] = "bomb";
    }
  },
  createRandomBombBoxId(firstClickBoxId) {
    const avoidBombPosition = this.getAroundBoxesIdArray(firstClickBoxId);
    const row = Math.floor(Math.random() * model.sizeRow) + 1;
    const col = Math.floor(Math.random() * model.sizeCol) + 1;
    const randomBombBoxId = `box-${row}-${col}`;
    if (avoidBombPosition.includes(randomBombBoxId) || model.bombPosition.includes(randomBombBoxId)) {
      return this.createRandomBombBoxId(firstClickBoxId);
    } 
    return randomBombBoxId;        
  },
  calculateBoxNumberAndRecordBoxType(bombArray) {
    bombArray.forEach(bombId => {
      const aroundBoxesIdArray = this.getAroundBoxesIdArray(bombId);
      aroundBoxesIdArray.forEach(boxId => {
        if (model.boxType[boxId] !== "bomb" && model.boxType[boxId] === undefined) {
          model.boxType[boxId] = 1;
        } else if (model.boxType[boxId] !== "bomb" && model.boxType[boxId] !== undefined) {
          model.boxType[boxId]++;
        }
      });
    });
  },
  getOnly4SidesBoxesIdArray(boxId) {
    const only4SidesBoxesIdArray = [boxId];
    const clickBoxRow = +boxId.split("-")[1];
    const clickBoxCol = +boxId.split("-")[2];
    // up, right, down, left
    const only4SidesBoxesIdRow = [clickBoxRow - 1, clickBoxRow, clickBoxRow + 1, clickBoxRow];
    const only4SidesBoxesIdCol = [clickBoxCol, clickBoxCol + 1, clickBoxCol, clickBoxCol - 1];
    only4SidesBoxesIdRow.forEach((row, index) => {
      if (!(row === 0 || only4SidesBoxesIdCol[index] === 0 || row === model.sizeRow + 1 || only4SidesBoxesIdCol[index] === model.sizeCol + 1)) {
        only4SidesBoxesIdArray.push(`box-${row}-${only4SidesBoxesIdCol[index]}`);
      }
    });    
    return only4SidesBoxesIdArray;
  },
  getAroundBoxesIdArray(boxId) {
    const aroundBoxesIdArray = [];
    const clickBoxRow = +boxId.split("-")[1];
    const clickBoxCol = +boxId.split("-")[2];
    for (let i = clickBoxRow - 1; i <= clickBoxRow + 1; i++) {
      for (let j = clickBoxCol - 1; j <= clickBoxCol + 1; j++) {
        // 避免超出範圍的box
        if (!(i === 0 || j === 0 || i === model.sizeRow + 1 || j === model.sizeCol + 1)) {
          aroundBoxesIdArray.push(`box-${i}-${j}`);
        }
      }
    }
    return aroundBoxesIdArray;
  },
  openEmptyBoxAction() {
    // 開empty
    if (model.tempEmptyBoxesIdArray.length === 0) {
      return;
    }
    // 抓取temp資料,並清空
    const innerTempEmptyBoxesIdArray = [...model.tempEmptyBoxesIdArray];
    model.tempEmptyBoxesIdArray.splice(0, model.tempEmptyBoxesIdArray.length);
    innerTempEmptyBoxesIdArray.forEach(eachTempBoxId => {
      const only4SidesBoxesIdArray = this.getOnly4SidesBoxesIdArray(eachTempBoxId);
      only4SidesBoxesIdArray.forEach(boxId => {
        if (!model.openEmptyBoxesIdArray.includes(boxId) && model.boxType[boxId] === undefined) {
          model.tempEmptyBoxesIdArray.push(boxId);
          model.openEmptyBoxesIdArray.push(boxId);
        }
      });
    })
    if (model.tempEmptyBoxesIdArray.length > 0) {
      return this.openEmptyBoxAction();
    }
  },
  openNumberBoxAction() {
    model.openEmptyBoxesIdArray.forEach(emptyBoxId => {
      const aroundBoxesIdArray = this.getAroundBoxesIdArray(emptyBoxId);
      aroundBoxesIdArray.forEach(boxId => {
        if (!model.openEmptyBoxesIdArray.includes(boxId) && model.boxType[boxId] !== undefined) {
          model.openNumberBoxesIdArray.push(boxId);
        } else if (!model.openEmptyBoxesIdArray.includes(boxId) && model.boxType[boxId] === undefined) {
          model.tempEmptyBoxesIdArray.push(boxId);
          model.openEmptyBoxesIdArray.push(boxId);
        }
      });
    });
  },
  openBoxAction() {
    if (model.tempEmptyBoxesIdArray.length === 0) {
      return;
    }
    this.openEmptyBoxAction();
    this.openNumberBoxAction();
    if (model.tempEmptyBoxesIdArray.length > 0) {
      return this.openBoxAction();
    }
  },  
  isWin() {
    let countCoveredBoxNumber = 0;
    for (let i = 1; i <= model.sizeRow; i++) {
      for (let j = 1; j <= model.sizeCol; j++) {
        const boxHTML = document.querySelector(`#box-${i}-${j}`);
        if (boxHTML.matches(".covered-box")) {
          countCoveredBoxNumber++;
        }
      }
    }
    return countCoveredBoxNumber === model.bombNumber;
  },  
  calculateRemainBombNumber() {
    let countFlagNumber = 0;
    for (let i = 1; i <= model.sizeRow; i++) {
      for (let j = 1; j <= model.sizeCol; j++) {
        const boxHTML = document.querySelector(`#box-${i}-${j}`);
        if (boxHTML.matches(".flag")) {
          countFlagNumber++;
        }
      }
    }
    return model.bombNumber - countFlagNumber;
  },  
  countTime() {
    model.countTime++;
  },  
  reset() {
    // clear all
    model.bombPosition.splice(0, model.bombPosition.length);
    for (let boxId in model.boxType) {
      delete model.boxType[boxId];
    }
    view.buildClickZone();
    // change face
    view.resetFace();
    // reset remain bomb number
    view.showRemainBombNumber();
    // reset time
    clearInterval(model.timeCounter);
    model.countTime = 0;
    view.showCountTime();
    // change state
    controller.currentState = GAME_STATE.FirstClickAwaits;
  },
  addNumberColorClass(boxId) {
    const boxHTML = document.querySelector(`#${boxId}`);
    const number = model.boxType[boxId];
    const className = `color-number-${number}`;
    boxHTML.classList.add(className);
  },
  createGame() {
    // reset
    this.reset();
    // Listener
    const mainArea = document.querySelector("#main-area");
    // 對box左鍵時或點笑臉時
    mainArea.addEventListener("click", e => {
      if (e.target.matches(".box") || e.target.parentElement.matches(".box")) {
        // 用以確定選到的元素是box,前提是box父層沒有id,已修改為確認id當中是否有box
        let boxId;
        if (e.target.parentElement.id.split("-")[0] === "box") {
          boxId = e.target.parentElement.id;
        } else if (e.target.id.split("-")[0] === "box") {
          boxId = e.target.id;
        }
        // const boxId = e.target.parentElement.id || e.target.id;
        const boxHTML = document.querySelector(`#${boxId}`);

        // 旗子不可click,點開的也不用再開
        if (boxHTML.matches(".flag") || !boxHTML.matches(".covered-box")) {
          return;
        }    
        // 做出button效果,先有壓下去的感覺,再展開
        boxHTML.classList.remove("covered-box");
        setTimeout(function () {
          controller.clickBox(boxHTML);
          view.showRemainBombNumber();
        }, 100)
        // controller.clickBox(boxHTML);
        // view.showRemainBombNumber();
      } else if (e.target.matches("#face-btn")) {
        controller.reset();
        // 做出button效果
        const faceBtnParentHTML = e.target.parentElement;
        faceBtnParentHTML.classList.remove("border-style-outer");
        faceBtnParentHTML.classList.add("border-style-inner");
        setTimeout(function () {
          faceBtnParentHTML.classList.remove("border-style-inner");
          faceBtnParentHTML.classList.add("border-style-outer");
        }, 100)
      }
    });
    // 對box右鍵時
    mainArea.oncontextmenu = function (e) {
      // 用以確定選到的元素是box,前提是box父層沒有id,已修改為確認id當中是否有box
      let boxId;
      if (e.target.parentElement.id.split("-")[0] === "box") {
        boxId = e.target.parentElement.id;
      } else if (e.target.id.split("-")[0] === "box") {
        boxId = e.target.id;
      }
      // const boxId = e.target.parentElement.id || e.target.id;
      const boxHTML = document.querySelector(`#${boxId}`);
      // 用以確認是否為尚未點開的box
      if (controller.currentState === GAME_STATE.GameFinished || !boxHTML.matches(".covered-box")) {
        return;
      }

      const remainBombNumber = controller.calculateRemainBombNumber();
      if (!boxHTML.matches(".flag") && !boxHTML.matches(".question") && remainBombNumber > 0) {
        boxHTML.classList.add("flag");
        boxHTML.innerHTML = `<i class="far fa-flag"></i>`;
      } else if (boxHTML.matches(".flag")) {
        boxHTML.classList.remove("flag");
        boxHTML.classList.add("question");
        boxHTML.innerHTML = `<i class="fas fa-question"></i>`;
      } else if (boxHTML.matches(".question")) {
        boxHTML.classList.remove("question");
        boxHTML.innerHTML = "";
      }

      view.showRemainBombNumber();

    };
    // 阻止點右鍵跳出視窗
    window.oncontextmenu = function () {
      return false;
    };
    // 客製化區域
    const customizedCreateBtn = document.querySelector("#customized-create-btn");
    const customizedInputRow = document.querySelector("#customized-input-row");
    const customizedInputCol = document.querySelector("#customized-input-col");
    const customizedInputBombNumber = document.querySelector("#customized-input-bomb-number");
    customizedCreateBtn.addEventListener("click", function (e) {
      const inputRow = +customizedInputRow.value;
      const inputCol = +customizedInputCol.value;
      const inputBombNumber = +customizedInputBombNumber.value;
      if (isNaN(inputRow) || isNaN(inputCol) || isNaN(inputBombNumber)) {
        alert("拜託輸入數字!");
        customizedInputRow.value = "";
        customizedInputCol.value = "";
        customizedInputBombNumber.value = "";
        return;
      } else if (inputRow % 1 !== 0 || inputCol % 1 !== 0 || inputBombNumber % 1 !== 0) {
        alert("可以輸入整數嗎?");
        customizedInputRow.value = "";
        customizedInputCol.value = "";
        customizedInputBombNumber.value = "";
        return;
      } else if (inputRow < 0 || inputCol < 0 || inputBombNumber < 0) {
        alert("不要輸入負數!");
        customizedInputRow.value = "";
        customizedInputCol.value = "";
        customizedInputBombNumber.value = "";
        return;
      } else if (inputRow <= 3 || inputCol <= 3) {
        alert("這樣太簡單了,建議大一點!");
        customizedInputRow.value = "";
        customizedInputCol.value = "";
      } else if (inputRow * inputCol - inputBombNumber < 9) {
        alert("炸彈太多塞不下啦!");      
        customizedInputBombNumber.value = "";
      } else if (inputBombNumber <= 0) {
        alert("你沒有放地雷,還叫踩地雷嗎?");
        customizedInputBombNumber.value = "";
      } else {
        // 建議別太窄,因為版型會跑掉
        if (inputCol <= 7) {
          alert("建議寬一點,因為版型會跑掉XD");  
        }
        if (inputRow >= 100 && inputCol >= 100) {
          alert("真的太大了!拜託小一點~"); 
          customizedInputRow.value = "";
          customizedInputCol.value = "";
          return;
        } else if (inputRow >= 30 || inputCol >= 30) {
          alert("太大了吧!但還是可以玩~");  
        }
        // 輸入設定
        model.sizeRow = inputRow;
        model.sizeCol = inputCol;
        model.bombNumber = inputBombNumber;
        controller.reset();
        view.adjustMainAreaSize();
      }
      
    });
  },
}

const utility = {
  createDigitalClockNumber(targetHTML, number) {
    // 先確認高度
    let numberHeight = targetHTML.clientHeight;
    // 保有基本高度
    if (numberHeight === 0) {
      numberHeight = 200;
    }

    const numberHTML = this.createDigitalClockNumberTemplate(numberHeight);
    this.clearNumberPart(numberHTML);
    this.showNumber(numberHTML, number);

    return numberHTML;
  },
  createDigitalClockNumberTemplate(numberHeight) {

    const digitalClockNumberTemplateHTML = document.createElement("div");
    digitalClockNumberTemplateHTML.classList.add("number-template");
    // templateHeight等下要修改,參考外面高度,unit為px
    const templateHeight = numberHeight;
    digitalClockNumberTemplateHTML.style.height = `${templateHeight}px`;
    digitalClockNumberTemplateHTML.style.width = `calc(${templateHeight}px * 0.5)`;
    // 內部組成,分7個部分
    for (let i = 1; i <= 7; i++) {
      const partHTML = document.createElement("div");
      partHTML.classList.add("number-part", `number-part-${i}`);

      const component1HTML = document.createElement("div");
      component1HTML.style.borderWidth = `${templateHeight * 0.05}px`;
      component1HTML.classList.add("number-part-component", "number-part-component-1");

      const component2HTML = document.createElement("div");
      component2HTML.style.borderWidth = `${templateHeight * 0.05}px`;
      component2HTML.classList.add("number-part-component", "number-part-component-2");

      partHTML.append(component1HTML);
      partHTML.append(component2HTML);

      digitalClockNumberTemplateHTML.append(partHTML);
    }

    return digitalClockNumberTemplateHTML;
  },
  clearNumberPart(numberHTML) {
    for (let i = 1; i <= 7; i++) {
      const partClass = `number-part-${i}`;
      const partHTML = numberHTML.querySelector(`.${partClass}`);
      const component1HTML = partHTML.querySelector(".number-part-component-1");
      const component2HTML = partHTML.querySelector(".number-part-component-2");
      component1HTML.style.borderBottomColor = "rgba(255, 0, 0, 0.3)";
      component2HTML.style.borderTopColor = "rgba(255, 0, 0, 0.3)";
    }
  },
  showNumber(numberHTML, number) {
    const showPart = {
      0: [1, 2, 3, 5, 6, 7],
      1: [3, 6],
      2: [1, 3, 4, 5, 7],
      3: [1, 3, 4, 6, 7],
      4: [2, 3, 4, 6],
      5: [1, 2, 4, 6, 7],
      6: [1, 2, 4, 5, 6, 7],
      7: [1, 3, 6],
      8: [1, 2, 3, 4, 5, 6, 7],
      9: [1, 2, 3, 4, 6, 7],
    };

    const showPartArray = showPart[number];
    showPartArray.forEach(part => {
      const partClass = `number-part-${part}`;
      const partHTML = numberHTML.querySelector(`.${partClass}`);
      const component1HTML = partHTML.querySelector(".number-part-component-1");
      const component2HTML = partHTML.querySelector(".number-part-component-2");
      component1HTML.style.borderBottomColor = "rgba(255, 0, 0, 1)";
      component2HTML.style.borderTopColor = "rgba(255, 0, 0, 1)";
    }); 

  },
}

//////////////////////////////////////////
controller.createGame();


              
            
!
999px

Console