-1

I'm currently writing a simple Battleships game in PHP. At the start of the game, I generate three ship positions on a 5 x 5 board, with each ship occupying one square:

function generate_three_battleships($ships){
    for ($n=0; $n<3; $n++){

        // Generate new position, returned from function as string
        $ship_position = generate_new_position();

        // Check to ensure that the position is not already occupied - if so, recast 
        if (in_array($ship_position, $ships)){
            $ship_position = generate_new_position();
        }//if

        // Assign position to array
        array_push($ships, $ship_position);
    }//for
}//generate_three_battleships

Each position is represented as a two-digit string, which represent cartesian coordinates (so for example, "32" represents y = 3, x = 2). This task is handled by the generate_new_position function:

When the game starts, the user will enter in their guesses for rows and columns:

function generate_new_position(){
    // Generate x and y coordinates - cast to string for storage
    $ship_row = (string)random_pos();
    $ship_col = (string)random_pos();
    $ship_position = $ship_row.$ship_col;

    return $ship_position;
}//generate_new_position

The user then enters their guesses for rows and columns, and the game will check to see if there is a ship there:

// Generate battleships
generate_three_battleships($ships);

for($turn=1; $turn <= GUESSES; $turn++){
    // First check to see if all ships have been sunk. If not, proceed with the game
    if ($ships_sunk < 3){
        $guess_row = (string)readline("Guess a row: ");
        $guess_col = (string)readline("Guess a column: ");
        $guess = $guess_row.$guess_col; // format guesses as strings

        if(($guess_row=="") || ($guess_col=="") || ($guess_row < 0) || ($guess_col < 0) || ($guess_row >= BOARDSIZE) || ($guess_col >= BOARDSIZE)){
            print("Oops, that's not even in the ocean. \n");
        }
        else if(array_search($guess, $ships) != false){
            print("Congratulations! You sunk one of my battleships!\n");
            $board[$guess_row][$guess_col] = "X";
            $ships_sunk++;
        }
    }

However, the in_array function is consistently returning false for every guess, even if that guess is actually in the $ships array. I can't see where I am going wrong, as I have explicitly cast everything to string. Am I missing something obvious?

As some people have asked, the output of var_dump on $ships after generate_three_battleships has executed is as follows:

array(3) {
  [0]=>
  string(2) "12"
  [1]=>
  string(2) "30"
  [2]=>
  string(2) "03"
}
AgentNo
  • 231
  • 5
  • 20
  • ```generate_three_battleships``` is called immediately before the last for loop. I'll edit my question to add that in, apologies. – AgentNo Feb 01 '20 at 15:21
  • My apologies, $ships is passed as a parameter. I'll edit my post, that's an oversight on my part. I figured that the odds of generate_new_position returning the same position twice was so low that, for this project at least, it wasn't worth thinking about. – AgentNo Feb 01 '20 at 15:29
  • 1
    Does this answer your question? [Are arrays in PHP passed by value or by reference?](https://stackoverflow.com/questions/2030906/are-arrays-in-php-passed-by-value-or-by-reference) In short: right now, your function isn't altering the `$ships` array that you passed to it, but a local copy of it. You need to pass-by-reference, or return the array and assign the result back. – Jeto Feb 01 '20 at 15:32
  • Thank you for the link Jeto. I updated my local script with your suggestion, but the error still persists. I also put the output from var_dump in my original question, if that is any help. That is how I expect the array to look. – AgentNo Feb 01 '20 at 15:42
  • [What's wrong here, exactly?](https://3v4l.org/TLVX8) (this is your code, using pass-by-reference and a dummy `random_pos`). – Jeto Feb 01 '20 at 15:48
  • "However, the in_array function is consistently returning false for every guess" <- wait, did you mean `array_search`...? The only `in_array` in your code is in the first function. – Jeto Feb 01 '20 at 15:51

1 Answers1

1

Unfortunately I don't have a complete answer because I am missing some information to understand what the problem is.

You can debug what's going on by printing the contents of the array using var_dump to see the actual contents of $ships and maybe forcing generate_new_position to always return the same value.

If you can't solve this problem yourself, could you post the contents of $ships (using var_dump) before and after the for loop?

lax9999
  • 103
  • 6
  • 1
    Welcome to SO. This should be in the comments section, instead of an answer. – Jeto Feb 01 '20 at 15:39
  • I have used var_dump - I put it in immediately before the validatiion check, and it returned the sort of output I expected. I'll update my original question with the output. – AgentNo Feb 01 '20 at 15:39
  • @Jeto I know, but for now I can post comments only under my posts – lax9999 Feb 01 '20 at 15:43
  • @AgentNo The array looks ok and for me `in_array` works correctly [here](https://repl.it/repls/QuirkyLawfulSemicolon). – lax9999 Feb 01 '20 at 15:53
  • Try to uncomment the definition of `random_pos` and write `function random_pos()` `{` `return "1";` `}` and in `generate_three_battleships` write `if(in_array($ship_position, $ships))` `{` `echo "In array; ship $ship_position\n";` `$ship_position = generate_new_position();` `}` `else` `{` `echo "Not in array: ship $ship_position\n";` `}` – lax9999 Feb 01 '20 at 16:03