If Statement From Array

Hi guys,

I'm creating Naughts and Crosses (aka Tic Tac Toe) and trying to find a way to work out the winner.

I made 2 arrays called posX and posO which puts in the location of the symbols into arrays.

Then I made a results function and I want to check the arrays if they contain combinations of locations added in. I only did 3 here to test it out. Top left & Top middle & Top right seems to work, but when I add in the others with OR nothing happens.

function result() {
    this.x = 300;
    this.y = 325;
    noStroke();
    fill(0);
    textSize(72);
    textAlign(CENTER);

    if (posO.includes("TL" && "TM" && "TR" ||
            "ML" && "MM" && "MR" || "BL" && "BM" && "BR")) {
        text("NAUGHTS WIN!", this.x, this.y);
}

Is it possible to use the IF statement like this to look within an array to find something?

Let me know if you need the rest of the code, it shouldn't be relevant to my question tho, and its quite long because I've inefficiently used a ton of boolean variables and if statements because i'm a newbie :D

Answers

  • I have a feeling you need to group all your &&'s together because of operator precedence, like ("TL" && "TM" && "TR") || ("ML" .... etc.

    Kf

  • Yeah I tried that as well, "Naughts Win!" comes up by default.

  • ??

    Some would probably program this in having a 2D array that represents the board where x and o are placed and check this instead

    Does includes work with && at all????

    Don't you need to check them separately as in ...((includes ("TM") && includes(...) && includes (...) ) || (includes...&& includes && includes) || (includes....

  • Hi, yeah I agree about the 2D array. The thing is I'm just starting out so right now I just want something that works, and then I'll go back to it afterwards once I learn and understand it.

    I just tried with the separate "includes" and that didn't work.

    My first attempt with the code on my first post the top row worked but the others didn't.

  • Answer ✓

    Storing the X and O positions in 2 different lists is not a good way of storing the board information. Chrisir has the solution and that is to store the data in a 2D array (that's 3x3 or 9 elements / positions.

    I suggest an integer array where each element represents a tic-tac-toe position.

    The actual values stored in the array are

    zero for an unused position, (#) 1 if it has an X and 4 if it has a O

    If you add up any three elements that make a row, column or diagonal there are just 12 possible values

    0   ###
    1   ##X
    2   #XX
    3   XXX
    4   ##O
    5   #OX
    6   OXX
    8   #OO
    9   OOX
    12  OOO
    

    Note that the order makes no difference to the row/column/diagonal value

    ##X = #X# AND X##    value = 1
    #OO = O#O AND OO#    value = 8
    

    It means that X wins if the value = 3 and O wins if the value = 12

  • edited March 2017

    @pyan83 --

    For a more general approach -- imagine a grid board of any size = 3x3 (tic-tac-toe), 5x5 (connect four), gomaku (15x15) ... etc.

    After each move you check if someone has won by finding if either side -- 1/2, X/O, red/yellow, black/white, etc. -- has reached the maximum in-a-row count -- 3-in-a-row, or 4, 5 etc.

    This involves checking:

    1. each row
    2. each column
    3. each left and right diagonal

    Here is an incomplete outline of that kind of approach, which could then be modified for other related kinds of games:

    var board = [];
    var boardw = 3;
    var boardh = 3;
    
    function setup() {
      // initialize an empty board
      for (var i = 0; i < boardw; i++) {
        board[i] = []; // create nested array
        for (var j = 0; j < boardh; j++) {
          board[i][j] = 0;
        }
      }
      noLoop();
    }
    
    function draw() {
      // add move logic
      results(3, board);
    }
    
    function results(max, board) {      
      if (checks(1, max, board)) {
      } // X wins
      if (checks(2, max, board)) {
      } // O wins
    }
    
    function checks(side, max, board) {
      if (checkRows(side, max)) {  
        return true;
      }
      if (checkCols(side, max)) {  
        return true;
      }
      if (checkDiags(side, max)) { 
        return true;
      }
    }
    
    function checkRows(side, max, board)  { return false; } // add check logic
    function checkCols(side, max, board)  { return false; } // add check logic
    function checkDiags(side, max, board) { return false; } // add check logic
    
  • edited March 2017

    Here's my preview take on it too. Got fully win check implementation: $-)

    <script async src=http://CDN.JSDelivr.net/p5.js/latest/mainfile></script>
    <script defer src=sketch.js></script>
    
    /**
     * Tic-Tac-Toe (0.2)
     * GoToLoop (2017-Mar-22)
     * forum.Processing.org/two/discussion/21521/if-statement-from-array#Item_7
     */
    
    "use strict";
    
    const board = Object.freeze([new Int8Array(3), new Int8Array(3), new Int8Array(3)]),
          EMPTY = 0, NOUGHT_O = -1, CROSS_X = 1,
          NOUGHT_WIN_SUM = 3*NOUGHT_O, CROSS_WIN_SUM = 3*CROSS_X;
    
    let currentPlayer, spacesLeft;
    
    function setup() {
      createCanvas(400, 300).mousePressed(findClickedPlace);
      noLoop();
      restartGame();
    }
    
    function draw() {
      background('#' + hex(~~random(0x1000), 3));
      console.table(board);
    }
    
    function findClickedPlace() {
      print(checkWinBoard(), --spacesLeft, currentPlayer *= -1);
      redraw();
    }
    
    function restartGame() {
      currentPlayer = currentPlayer == CROSS_X? NOUGHT_O : CROSS_X;
      spacesLeft = 9;
      emptyBoard();
    }
    
    function emptyBoard() {
      for (const row of board)  row.fill(EMPTY);
    }
    
    function checkWinBoard() {
      let gotWinner = checkRows();
      if (gotWinner)  return gotWinner;
    
      gotWinner = checkColumns();
      if (gotWinner)  return gotWinner;
    
      return checkDiagonals();
    }
    
    function getWinner(sum) {
      return sum == NOUGHT_WIN_SUM? NOUGHT_O : sum == CROSS_WIN_SUM? CROSS_X : EMPTY;
    }
    
    function checkRows() {
      for (const row of board) {
        const sum = row[0] + row[1] + row[2], gotWinner = getWinner(sum);
        if (gotWinner)  return gotWinner;
      }
    }
    
    function checkColumns() {
      for (let gotWinner, col = 0; col < 3; ++col) {
        const sum = board[0][col] + board[1][col] + board[2][col];
        if (gotWinner = getWinner(sum))  return gotWinner;
      }
    }
    
    function checkDiagonals() {
      let sum = 0, gotWinner;
      for (let i = 0; i < 3; sum += board[i][i++]);
      if (gotWinner = getWinner(sum))  return gotWinner;
    
      sum = 0;
      for (let i = 0; i < 3; sum += board[i++][3-i]);
      return getWinner(sum);
    }
    
  • edited March 2017

    Firstly I just want to leave some feedback on some of the responses. I started learning from nothing in January and have been following Shiffman's videos on youtube. All in all it has been great but there is a huge difference between taking notes and copying the code, and actually trying your own projects, making me realise I didn't fully understand as much as I had thought.

    I absolutely recognize that my attempt at coding tic tac toe is highly inefficient and terrible. But doing it this way is doing it using the limits of what I currently understand, and that is a hugely helpful process, of which I can improve upon later on.

    Thanks for posting up alternative solutions, but they're not too helpful as its the equivalent of blindly copying the code without understanding it fully.

    I could compare it to an overweight person getting a personal trainer who goes hardcore on him straight from the get go. After a short while, it would be too much and cause him to give up. The trainer should ease him in, let him have small wins and over time he'll have more of a chance at sticking with it.

    So in saying that, I think @quark 's idea is best for me right now, as it works within my current code. I've put the numbers into a 2D array representing their position and symbol on the board and if the rows and diagonals add up to 3 or 12 its a winner.

    I'm having trouble with getting the sum of the values within the arrays to show up. Do you guys know why this works in the console but not in my code?

    function result() {
        this.x = 300;
        this.y = 325;
        noStroke();
        fill(0);
        textSize(72);
        textAlign(CENTER);
    
        var topRow = pos[0][0] + pos[0][1] + pos[0][2];
    
        if (this.topRow == 6) {
            text("NAUGHTS WIN!", this.x, this.y);
        }
    }
    

    https://gyazo.com/cc5d18f8157cbf2911a7eaff8bac6951

    Above is a picture of the topRow working in console. Cant seem to embed this picture.

  • I've managed to finish it, but with a few minor bugs. Gonna post this up for reference for others.

    function result() {
        this.x = 300;
        this.y = 325;
    
        //[Down][Across] Starting from top left
    
        var topRow = pos[0][0] + pos[0][1] + pos[0][2];
        var midRow = pos[1][0] + pos[1][1] + pos[1][2];
        var botRow = pos[2][0] + pos[2][1] + pos[2][2];
    
        var leftCol = pos[0][0] + pos[1][0] + pos[2][0];
        var midCol = pos[0][1] + pos[1][1] + pos[2][1];
        var rightCol = pos[0][2] + pos[1][2] + pos[2][2];
    
        var diagDown = pos[0][0] + pos[1][1] + pos[2][2];
        var diagUp = pos[2][0] + pos[1][1] + pos[0][2];
    
        var sumBoard = topRow + midRow + botRow;
    
        noStroke();
        fill(0);
        textSize(72);
        textAlign(CENTER);
    
        if (topRow == 3 || midRow == 3 || botRow == 3 || leftCol == 3 || midCol == 3 || rightCol == 3 || diagUp == 3 || diagDown == 3) {
            text("NAUGHTS WIN!", this.x, this.y);
    
        } else if (topRow == 12 || midRow == 12 || botRow == 12 || leftCol == 12 || midCol == 12 || rightCol == 12 || diagUp == 12 || diagDown == 12) {
            text("CROSSES WIN!", this.x, this.y);
    
        } else {
            if (sumBoard == 21) {
                text("ITS A DRAW!", this.x, this.y);
            }
        }
    }
    

    Thanks for all your help!

Sign In or Register to comment.