

# 実現したいこと

Javascriptを使ってターミナル上で遊べる三目並べのゲームを作りたいのですが、Chat
GPTを活用して、コードを生成し、作りました。プレイはできるのですが、途中でエラー（0 1と入力しても、Invalid move. Try
again.と出てしまう点）が起きてしまいます。このエラーの解決策を教えていただきたいです。

# 前提

ゲームの操作方法としては0 1,0 2のように行と列の番号を入れていく感じです。  
プログラム自体はnodeで動かしています。

# お願い

プログラミング初心者なので基礎的な情報も絡めて教えていただけると幸いです。よろしくお願いいたします。

# 発生している問題・エラーメッセージ

[code]

    PC game % node TicTacToeCLI.js
    Debugger attached.
    Player 1, it's your turn.
    _ _ _ 
    _ _ _ 
    _ _ _ 
    Player 1, enter your move (row column): 0 1
    Invalid move. Try again.
    Player 1, it's your turn.
    _ _ _ 
    _ _ _ 
    _ _ _ 
    Player 1, enter your move (row column): 
    
[/code]

# 該当のソースコード

[code]

    const readline = require("readline").createInterface({
        input: process.stdin,
        output: process.stdout,
      });
      
      const GAME_DOESNT_EXIST = -2;
      const GAME_NOT_STARTED = -3;
      const GAME_ENDED = -4;
      const GAME_ONGOING = -5;
      const WRONG_TURN = -6;
      const INVALID_LOCATION = -7;
      
      let games = {};
      let gameIdCounter = 0;
      let playerIdCounter = 0;
      
      function createGame() {
        let gameId = gameIdCounter++;
        games[gameId] = {
          players: [],
          board: [
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
          ],
          turn: 0,
          ended: false,
        };
        return gameId;
      }
      
      function addPlayer(gameId) {
        if (!(gameId in games)) {
          return GAME_DOESNT_EXIST;
        }
        if (games[gameId].players.length >= 2) {
          return games[gameId].ended ? GAME_ENDED : GAME_ONGOING;
        }
        let playerId = playerIdCounter++;
        games[gameId].players.push(playerId);
        return playerId;
      }
      
      function makeMove(gameId, playerId, boardX, boardY) {
        if (!(gameId in games)) {
          return GAME_DOESNT_EXIST;
        }
        if (games[gameId].players.length < 2) {
          return GAME_NOT_STARTED;
        }
        if (games[gameId].ended) {
          return GAME_ENDED;
        }
        if (games[gameId].players[games[gameId].turn] !== playerId) {
          return WRONG_TURN;
        }
        if (
          boardX < 0 ||
          boardX > 2 ||
          boardY < 0 ||
          boardY > 2 ||
          games[gameId].board[boardX][boardY] !== 0
        ) {
          return INVALID_LOCATION;
        }
        games[gameId].board[boardX][boardY] = playerId;
        if (checkWin(games[gameId].board, playerId)) {
          games[gameId].ended = true;
          return playerId;
        }
        if (games[gameId].board.flat().every((cell) => cell !== 0)) {
          games[gameId].ended = true;
          return games[gameId].players[(games[gameId].turn + 1) % 2];
        }
        games[gameId].turn = (games[gameId].turn + 1) % 2;
        return GAME_ONGOING;
      }
      
      function checkWin(board, playerId) {
        let winLines = [
          [
            [0, 0],
            [0, 1],
            [0, 2],
          ],
          [
            [1, 0],
            [1, 1],
            [1, 2],
          ],
          [
            [2, 0],
            [2, 1],
            [2, 2],
          ],
          [
            [0, 0],
            [1, 0],
            [2, 0],
          ],
          [
            [0, 1],
            [1, 1],
            [2, 1],
          ],
          [
            [0, 2],
            [1, 2],
            [2, 2],
          ],
          [
            [0, 0],
            [1, 1],
            [2, 2],
          ],
          [
            [0, 2],
            [1, 1],
            [2, 0],
          ],
        ];
        return winLines.some((line) =>
          line.every(([x, y]) => board[x][y] === playerId)
        );
      }
      
      function printBoard(gameId) {
        const game = games[gameId];
        for (let i = 0; i < 3; i++) {
          let row = "";
          for (let j = 0; j < 3; j++) {
            if (game.board[i][j] === 0) {
              row += "_ ";
            } else if (game.board[i][j] === game.players[0]) {
              row += "X ";
            } else if (game.board[i][j] === game.players[1]) {
              row += "O ";
            }
          }
          console.log(row);
        }
      }
      
      function playTurn(gameId, playerId) {
        console.log(`Player ${playerId + 1}, it's your turn.`);
        printBoard(gameId);
        readline.question(
          `Player ${playerId + 1}, enter your move (row column): `,
          (move) => {
            const [row, column] = move.split(" ").map(Number);
            if (
              isNaN(row) ||
              isNaN(column) ||
              row < 1 ||
              row > 3 ||
              column < 1 ||
              column > 3
            ) {
              console.log("Invalid move. Try again.");
              playTurn(gameId, playerId);
              return;
            }
            const result = makeMove(gameId, playerId, row - 1, column - 1);
            if (result < 0) {
              console.log("Invalid move. Try again.");
              playTurn(gameId, playerId);
            } else if (result === GAME_ONGOING) {
              playTurn(gameId, (playerId + 1) % 2);
            } else {
              printBoard(gameId);
              if (result === playerId) {
                console.log(`Player ${playerId + 1} wins!`);
              } else {
                console.log("The game is a draw.");
              }
              readline.close();
            }
          }
        );
      }
      
      function startGame() {
        const gameId = createGame();
        const player1Id = addPlayer(gameId);
        const player2Id = addPlayer(gameId);
        if (player1Id < 0 || player2Id < 0) {
          console.log("Error: Unable to start the game.");
          return;
        }
        playTurn(gameId, player1Id);
      }
      
      startGame();
    
[/code]


CC BY-SA 4.0
2023-06-09T10:22:39.890
95163
2023-06-09T11:14:36.580
2023-06-09T10:29:46.453
48368
48368
question
javascript node.js
Javascriptの三目並べ


表示されているエラーは構文エラーの類ではなく、コード中に自分で設定したメッセージのはずです。

そして、コメント欄でも指摘がありますがコードを読む限り盤面の指定は 1 から 2
の間で受け取り、それ以外は弾くように条件を設定しているので、仕様通りに動いていると言えます。

言語仕様としては確かに配列は 0 から始まりますが、ユーザーに見せる際の仕様とどう整合をとるかはプログラムの設計次第です。

どう入力すればよいかのヒントを表示するのも一つの方法です。


CC BY-SA 4.0
2023-06-09T11:14:36.580
95164
2023-06-09T11:14:36.580
3060
95163
answer