<head>
  <meta charset="UTF-8">
  <title>オセロ</title>
  <script src="main.js"></script>
<style>
  body{
    background-color: black
  }
  h3{
    color:white;
  }
  #table{
    background-color:#555000;
  }
  td.masu{
    background-color:#54b549;
    width:40px;
    height:40px;
    margin:2px;
    font-size:20px;
    text-align:center;
  }
  td.black{
    color:black;
  }
  td.white{
    color:white;
  }
</style>  
</head>
<body>
  <h3 class="white">
    白(YOU):<span id="countWhite"></span>枚
  </h3>
  <table id="table"></table>
  <h3 class="black">
    黒(CPU):<span id="countBlack"></span>枚
  </h3>
</body>
</html>
let omomiData = [
  [30, -12, 0, -1, -1, 0, -12, 30],
  [-12, -15, -3, -3, -3, -3, -15, -12],
  [0, -3, 0, -1, -1, 0, -3, 0],
  [-1, -3, -1, -1, -1, -1, -3, -1],
  [-1, -3, -1, -1, -1, -1, -3, -1],
  [0, -3, 0, -1, -1, 0, -3, 0],
  [-12, -15, -3, -3, -3, -3, -15, -12],
  [30, -12, 0, -1, -1, 0, -12, 30]
]; // 重みづけデータ
let SIRO = 1;
let KURO = 2;
let data = [];
let myTurn = false;

function init() {
  let table = document.getElementById("table");
  for (let i = 0; i < 8; i++) {
    let yokoretu = document.createElement("tr");
    data[i] = [0, 0, 0, 0, 0, 0, 0, 0];
    for (let j = 0; j < 8; j++) {
      let itimasu = document.createElement("td");
      itimasu.className = "masu";
      itimasu.id = "masu" + i + j;
      itimasu.onclick = touch; //②追加分
      yokoretu.appendChild(itimasu);
    }
    table.appendChild(yokoretu);
  }
  //初期配置
  put(3, 3, SIRO);
  put(4, 4, SIRO);
  put(3, 4, KURO);
  put(4, 3, KURO);
  kousin();
}

function put(i, j, color) {
  let masu = document.getElementById("masu" + i + j);
  masu.textContent = "●";
  masu.className = "masu " + (color === SIRO ? "white" : "black");
  data[i][j] = color;
}

function kousin() {
  //白と黒の数を数えて、表示する
  let countWhite = 0;
  let countBlack = 0;
  for (let x = 0; x < 8; x++) {
    for (let y = 0; y < 8; y++) {
      if (data[x][y] === SIRO) {
        countWhite++;
      }
      if (data[x][y] === KURO) {
        countBlack++;
      }
    }
  }
  document.getElementById("countBlack").textContent = countBlack;
  document.getElementById("countWhite").textContent = countWhite;

  //②追加分//②追加分//②追加分//②追加分//②追加分
  let turnSIRO = canReverce(SIRO);
  let turnKURO = canReverce(KURO);

  if (
    countWhite + countBlack === 64 ||
    (turnKURO === false && turnSIRO === false)
  ) {
    if (countWhite > countBlack) {
      alert("白の勝ち");
    } else if (countWhite < countBlack) {
      alert("黒の勝ち");
    } else {
      alert("引き分け");
    }
    return;
  }

  if (turnSIRO === false) {
    alert("白スキップ");
    myTurn = false;
  } else if (turnKURO === false) {
    alert("黒スキップ");
    myTurn = true;
  } else {
    myTurn = !myTurn;
  }

  if (myTurn === false) {
    setTimeout(cpuThinking, 1000);
  }
}

function touch(masu) {
  if (!myTurn) {
    return;
  }

  let id = masu.target.id;
  let tate = parseInt(id.charAt(4));
  let yoko = parseInt(id.charAt(5));
  let canReverseMasu = canReverceMasu(tate, yoko, SIRO);

  if (canReverseMasu.length > 0) {
    for (let k = 0; k < canReverseMasu.length; k++) {
      put(canReverseMasu[k][0], canReverseMasu[k][1], SIRO);
    }
    put(tate, yoko, SIRO);
    kousin();
  }
}

// 挟める石があるか?
//ターンプレイヤーを確定させるために64マスを調べている
function canReverce(color) {
  for (let x = 0; x < 8; x++) {
    for (let y = 0; y < 8; y++) {
      let canReverseMasu = canReverceMasu(x, y, color);
      if (canReverseMasu.length > 0) {
        return true;
      }
    }
  }
  return false;
}

// (i,j)に石を置いた時 挟める座標(配列) を返す
function canReverceMasu(i, j, color) {
  if (data[i][j] === KURO || data[i][j] === SIRO) {
    return []; // すでに石があるときは何もしない
  }

  // 相手を挟めるか、左上、上、右上、左、右、左下、下、右下と順番に調査
  let touchedMawari = [
    [-1, -1],
    [0, -1],
    [1, -1],
    [-1, 0],
    [1, 0],
    [-1, 1],
    [0, 1],
    [1, 1]
  ];

  let result = [];
  for (let p = 0; p < touchedMawari.length; p++) {
    let canReverseMasu = canReverceHoukou(
      i,
      j,
      touchedMawari[p][0],
      touchedMawari[p][1],
      color
    );
    result = result.concat(canReverseMasu);
  }
  return result;
}

// (i,j)に石を置いたときに、(Xhoukou,Yhoukou)方向で石を挟めるか?
function canReverceHoukou(i, j, Xhoukou, Yhoukou, color) {
  let checkedX = i + Xhoukou;
  let checkedY = j + Yhoukou;

  if (
    checkedX < 0 ||
    checkedY < 0 ||
    checkedX > 7 ||
    checkedY > 7 ||
    data[checkedX][checkedY] === color ||
    data[checkedX][checkedY] === 0
  ) {
    return []; // 盤外、同色、空ならfalse(挟めない)
  }

  // 挟める候補の座標 = クリックした座標から見て違う色の石を重複配列で格納
  let canReverseMasu = [];
  canReverseMasu.push([checkedX, checkedY]);

  while (true) {
    checkedX += Xhoukou;
    checkedY += Yhoukou;
    if (
      checkedX < 0 ||
      checkedY < 0 ||
      checkedX > 7 ||
      checkedY > 7 ||
      data[checkedX][checkedY] === 0
    ) {
      return []; //  盤外、空ならfalse(挟めない)
    }
    if (data[checkedX][checkedY] === color) {
      return canReverseMasu; // 挟めた!
    } else {
      canReverseMasu.push([checkedX, checkedY]);
    }
  }
}

function cpuThinking() {
  let highScore = -1000;
  let px = -1;
  let py = -1;
  for (let x = 0; x < 8; x++) {
    for (let y = 0; y < 8; y++) {
      let kariData = copyData();
      let cpuCanReverceMasu = canReverceMasu(x, y, KURO);
      if (cpuCanReverceMasu.length > 0) {
        for (let i = 0; i < cpuCanReverceMasu.length; i++) {
          let p = cpuCanReverceMasu[i][0];
          let q = cpuCanReverceMasu[i][1];
          kariData[p][q] = KURO;
          kariData[x][y] = KURO;
        }
        let score = keisanOmomiData(kariData);
        if (score > highScore) {
          highScore = score;
          (px = x), (py = y);
        }
      }
    }
  }

  if (px >= 0 && py >= 0) {
    let cpuCanReverceMasu = canReverceMasu(px, py, KURO);
    if (cpuCanReverceMasu.length > 0) {
      for (let k = 0; k < cpuCanReverceMasu.length; k++) {
        put(cpuCanReverceMasu[k][0], cpuCanReverceMasu[k][1], KURO);
      }
    }
    put(px, py, KURO);
  }

  kousin();
}

// 重みづけ計算;
function keisanOmomiData(kariData) {
  let score = 0;
  for (let x = 0; x < 8; x++) {
    for (let y = 0; y < 8; y++) {
      if (kariData[x][y] === KURO) {
        score += omomiData[x][y];
      }
    }
  }
  return score;
}

// 石テーブルデータをコピー;
function copyData() {
  let kariData = [];
  for (let x = 0; x < 8; x++) {
    kariData[x] = [];
    for (let y = 0; y < 8; y++) {
      kariData[x][y] = data[x][y];
    }
  }
  // console.log(kariData);
  return kariData;
}

window.addEventListener("load", init);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.