Algorithm MinMax is not functioning as originally anticipated

In the process of creating a tic tac toe game for a project on Free Code Camp, I have successfully added a minmax algorithm to determine the best square for the computer player's next move.

While the algorithm performs as intended in most cases I've tested, there is one scenario where it does not:

var userIs = 'o'
var computerIs = 'x'

function countInArray(array, what) {
    var count = 0;
    for (var i = 0; i < array.length; i++) {
        if (array[i] === what) {
            count++;
        }
    }
    return count;
}

function nextMove(board, player) {
  var nextPlayer;
  if (computerIs !== player) {
    nextPlayer = userIs; 
  } else {
    nextPlayer = computerIs; 
  }
  if (isGameOver(board)) {
    if (player === userIs) {
      return {
        "willWin": -1,
        "nextMove": -1
      };
    } else {
      return {
        "willWin": 1,
        "nextMove": -1
      };
    }
  }

  var listOfResults = [];

  if (countInArray(board, '-') === 0) {
    return {
        "willWin": 0,
        "nextMove": -1,
      };
  }

  var _list = [];//keeping track of avalible moves
  for (var i=0; i < board.length; i++) {
    if (board[i] === '-') {
      _list.push(i);
    }
  }
  for (var j = 0; j < _list.length; j++) {
    board[_list[j]] = player;
    var nextTry = nextMove(board, nextPlayer);
    listOfResults.push(nextTry.willWin);  
    board[_list[j]] = '-';
  }
  if (player === computerIs) {
     var maxele = Math.max.apply(Math, listOfResults);
     return {
      "willWin": maxele,
      "nextMove": _list[listOfResults.indexOf(maxele)] 
     };
  } else {
    var minele = Math.min.apply(Math, listOfResults);
    return {
      "willWin": minele,
      "nextMove": _list[listOfResults.indexOf(minele)] 
    };
  }
}

function isGameOver(board) {
  //horizontal wins
  var gameOver = false;
  var rowOffset = [0,3,6];
  rowOffset.forEach(function(row){
     if (board[row] === board[row + 1]  && board[row + 1]  === board[row + 2] && board[row] !== "-") {
      gameOver = true;
     }
  });
  //vertical wins
  var colOffset = [0,1,2];
  colOffset.forEach(function(col){
    if (board[col] === board[col + 3] && board[col + 3] === board[col + 6] && board[col] !== "-" ){
      gameOver = true;
    }
  });

  ///diag wins
  if (board[0] === board[4] && board[4] === board[8]  && board[8] !== "-" ) {
    gameOver = true;
  }
  if (board[2] === board[4] && board[4] === board[6] && board[6] !== "-" ) {
    gameOver = true;
  }
 return gameOver;
}

nextMove(["x", "x", "o", "o", "x", "-", "-", "-", "o"], computerIs)

During testing, I encountered an unexpected outcome where it returned: {willWin: 1, nextMove: 5} instead of {willWin: 1, nextMove: 7}

Referring to a Python implementation example found here: https://gist.github.com/SudhagarS/3942029, I expected the same result as shown in the Python code.

Would you be able to identify any specific reason or issue that could explain this behavior?

Answer №1

After implementing some logging, I realized that I was not switching between players correctly.

Previously, I was toggling between players using the following logic:

 if (computerIs !== player) {
    nextPlayer = userIs; 
  } else {
    nextPlayer = computerIs; 
  }

After making the correction to:

if (computerIs === player) {
    nextPlayer = userIs; 
  } else {
    nextPlayer = computerIs; 
  }

Additionally, I reversed the scores (-1 to 1 and 1 to -1) for the winning player when the game ends, which resolved the issue.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Gather data from various textboxes and combine them into a unified string with the help of JavaScript

I am currently facing a challenge where I need to extract the values from multiple textboxes and combine them into a single string. This string will then be sent to my PHP processing page for insertion into a database table. The textboxes mentioned above ...

Adding text after a div in React-JS using Bootstrap: A quick guide

Just starting out with website development and I have a question. As I practice making this website, I am struggling to figure out how to add the text "To know more about us click here" below the 'Get started' button. I tried adding a simple < ...

What is the process for creating a line using points in three.js?

Can anyone provide a solution for creating a straight line using new THREE.Points()? I attempted to place particles and set their positions with an array and for loop, but the spacing was inconsistent. ...

Interface-derived properties

One of the challenges I'm facing is dealing with a time interval encapsulation interface in TypeScript: export interface TimeBased { start_time: Date; end_time: Date; duration_in_hours: number; } To implement this interface, I've created ...

I'm struggling to grasp the concept of State in React.js

Even though I'm trying my best, I am encountering an issue with obtaining JSON from an API. The following error is being thrown: TypeError: Cannot read property 'setState' of undefined(…) const Main = React.createClass({ getInitia ...

Neglecting the inclusion of a property when verifying for empty properties

In the code snippet below, I have implemented a method to check for empty properties and return true if any property is empty. However, I am looking for a way to exclude certain properties from this check. Specifically, I do not want to include generalReal ...

Zod vow denial: ZodError consistently delivers an empty array

My goal is to validate data received from the backend following a specific TypeScript structure. export interface Booking { locationId: string; bookingId: number; spotId: string; from: string; to: string; status: "pending" | "con ...

The jQuery carousel script is not functioning

Currently developing a jQuery slideshow for my website, and I stumbled upon a code that fits my requirements perfectly. I made some adjustments to the code from this source: . My specifications were that the code should be created from scratch, lightweight ...

Setting the height to 100% on the body and html tags can lead to scrolling problems

After implementing the CSS code below, I have encountered some unexpected behavior: body, html{height:100%; overflow-x:hidden} Despite vertical scrollbars appearing as intended when the page exceeds screen height, detecting the scroll event on the body e ...

What could be causing npm to fail to launch?

Whenever I execute node app.js, my server functions perfectly. However, when attempting to utilize nodemon for running the server, it fails to start. The error displayed by npm start is as follows: npm ERR! code ELIFECYCLE npm ERR! errno 9009 npm ERR! < ...

Display a modal using jQuery, PHP, and Ajax to verify if a user is

Using a combination of jQuery, PHP, and Ajax, I am able to check if a user is logged in or not. JavaScript: jQuery(document).ready(function() { setInterval(function() { jQuery.ajax({ url: 'chkLoggedin.php', type: 'POST', ...

What steps can be taken to ensure the random generator continues to function multiple times?

My little generator can choose a random item from an array and show it as text in a div. However, it seems to only work once. I'm looking for a way to make it refresh the text every time you click on it. var items = Array(523,3452,334,31,5346); var r ...

Can someone guide me on incorporating values from an external server into the app.post function?

After successfully completing the registration process for my app, where users can register and log in to a shop, I encountered a hurdle with the login functionality. Let me walk you through the issue. The function below checks my mongoDB collection to se ...

Parsing the CSV file contents according to the specified columns

Currently, I'm involved in a project using AngularJS where I need to extract data from a CSV file column by column using JavaScript. So far, I've successfully retrieved the CSV data and displayed it in the console. While I've managed to sepa ...

Having trouble connecting a JavaScript file from my local directory to an HTML document. However, when I try to access it in the browser, I keep getting

Currently, I am attempting to connect a javascript file to my html document. Following the directions at this link, I am trying to enable the selection of multiple dates from a calendar as input in a form. The instructions mention that I need to include ...

I'm encountering an issue with my API Key being undefined, despite having it saved in both an .env file and as a global variable

While attempting to retrieve information from an API, I encountered an issue where the key I was using was labeled as "undefined". However, after manually replacing {key=undefined} with the correct string in the network console, I was able to successfull ...

Difficulty encountered when trying to use Bootstrap tooltip with Bootstrap icon

Attempting to implement bootstrap tooltips on bootstrap icons with the following code: <body> <script> const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]') ...

javascript loop that runs on every second element only

After completing an ajax query, the following JavaScript code is executed. All of my images are named "pic". <script type="text/javascript> function done() { var e = document.getElementsByName("pic"); alert(e.length); for (var i = 0; ...

Exploring recommendations using AngularJS

I am currently working on replicating the search suggestion feature found at: where certain words are displayed as you type in the search box. Here is my HTML setup: <form ng-controller="SearchCtrl"> <input name="q" ng-model="query" ng-keyp ...

Is it possible for my JQueryUI draggable items to smoothly transition into a different overflowing element?

On my iPad, I have two scrollable areas where I kept the overflow to auto, scroll, or hidden to allow scrolling. One section contains unenrolled students, and using JQueryUI with touchPunch, I can drag a student from the unenrolled bin into their appropria ...