Skip to content
Advertisement

PHP OO – Associative array of object instances, resetting on each click

My first ever question on here as I’m completely stuck, so apologies if I leave out any key information – please let me know!

I am creating a PHP Battleships game and trying to use full OO. I’m really close, however, an array for one of my classes does not hold any updates I make to it.

First off, I dynamically created a HTML table with an onclick event – which passes the coordinates to a JS function.

I then make an AJAX call in jQuery:

        function shotFired(row, column) {
        var coords = {
            x: row,
            y: column
        };

        $.post("data/game_controller.php", {
            jsonCoords: JSON.stringify(coords)
        }, function(results) {
            console.log(results)
            console.log(results[4])

            var playerShotResult = results[0];
            var computerShotX = results[1] + 1;
            var computerShotY = results[2] + 1;
            var computerShotResult = results[3];

            var positionsClicked = document.getElementById("computer_" + row + "," + column)
            switch (playerShotResult) {
                case "MISS":
                    positionsClicked.classList.add("miss");
                    break;
                case "HIT":
                    positionsClicked.classList.add("hit");
                    break;
                case "Already Hit":
                    document.getElementById("outputMessage").innerHTML = result
                    break;
                default:
                    console.log("Player shot defaulted");
            }
        }, "json")

I then use game_controller.php to handle the request and call shotFired:

<?php
session_start();
require("../classes/Game.class.php");

if (isset($_POST['jsonCoords'])) {
    if (isset($_SESSION['newGame'])) {
        $game = unserialize($_SESSION['newGame']);

        $coords = json_decode($_POST['jsonCoords']);
        $results = $game->shotFired($coords->x, $coords->y);

        echo json_encode($results);
    }
}

shotFired from the Game.php Class file, gets an instance of the Fleet class called computer, and runs the checkPosition function:

public function shotFired($x, $y)
{
    $computer = $this->getComputer();

    $playerHit = $computer->checkPosition(($x - 1), ($y - 1));
    $computerGrid = $computer->getBattleshipsGrid();
    $computerHit = $this->simulateComputerShot();

    return [$playerHit, $computerHit[0], $computerHit[1], $computerHit[2], $computerGrid];
}

checksPosition checks the State of the Position instance in the BattleshipGrid array, and then attempts to update the array with a H or M – using a standard setter method:

public function checkPosition($x, $y): string
{
    $positionObj = $this->battleshipsGrid["(" . $x . "," . $y . ")"];
    $positionState = $positionObj->getState();

    if ($positionState == "#") {
        $positionObj->setState("M");
        return "MISS";
    } elseif ($positionState == "M" || $positionState == "H") {
        return "Already Fired";
    } else {
        $positionObj->setState("H");
        return "HIT";
    }
}

For reference, I set the Battleships board in the constructor for Fleet.php:

    // Populate associative array with instances of position
    for ($y = 0; $y < $gridSize; $y++) {
        for ($x = 0; $x < $gridSize; $x++) {
            $coordinates = "(" . $x . "," . $y . ")";
            $this->battleshipsGrid[$coordinates] = new Position($x, $y);
        }
    }

It works directly after it has been set – however, on the next onclick event, the H or M value is reset to it’s previous value? Seen here in console output

After a couple of hours, the closest I’ve come to is passing byRef in the setState function (didn’t make a difference). I’ve seen some notes on array_map, but I’m not sure this is what I’m looking for?

For ref, this is how I output the battleshipGrid to the console:

    public function getBattleshipsGrid()
{
    $readableGrid = "";
    $grid = $this->battleshipsGrid;
    foreach ($grid as $coordsID => $positionObj) {
        $readableGrid .= "n" . $coordsID . ": " . $positionObj->getState();
    }

    return $readableGrid;
}

Apologies for the long post, but I didn’t want to leave anything out. Any and all help would be extremely appreciated!

Many thanks

Advertisement

Answer

It looks like you’re not saving the state of the coordinates of the hits. If you are using the eloquent model, and setState is changing the attribute’s value, make sure that you call $positionObj->save() as php does not save state on each ajax request. You will need to use a database or some sort of storage to have the server ‘remember’ that you clicked a specific location.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement