Why code goes to infinite loop? (

Go To StackoverFlow.com

2

<?php
$mines = 10;

####
for($x=1; $x<=9; $x++) {
    for($y=1; $y<=9; $y++) {
        $minefield[$x][$y] = 0;
    }
}       

for($i=0; $i<$mines; $i++) {
    $randx = rand(1, 9);
    $randy = rand(1, 9);

    if($minefield[$randx][$randy] == 'X') {
        $i--;
    } else {
        $minefield[$randx][$randy] = 'X';
    }
}

What's i doing wrong?

2012-04-05 20:15
by Anton
Can you do a print_r on $minefield - c1pherB1t 2012-04-05 20:17
What's the $i-- supposed to be accomplishing? Is that like a "try again, there's already a mine here? - Alex Howansky 2012-04-05 20:18
@AlexHowansky He wants to set 10 unique locations for mines. The i-- causes the loop to "try again" when it already picks a location that has a mine - Andrew T Finnell 2012-04-05 20:19
@Andrew -- heh, just realized that.. - Alex Howansky 2012-04-05 20:20
I feel like this would be a good question to ask on an exam of some kind - Devin Burke 2012-04-05 20:32


8

When comparing strings (or resources) with integers, strings are translated to numbers first, as per the documentation, then compared.

As such, this:

if ($minefield[$randx][$randy] == 'X')

... where $minefield[$randx][$randy] = 0 is equivalent to:

if (0 == 0) // 0 == (int)'X'

... which is always true. Therefore, you are incrementing and decrementing $i at each iteration.

2012-04-05 20:23
by netcoder
and he tried 'Y'? Is it translated to ASCII values or is it always 0 - 11684 2012-04-05 20:40
@11684: There is no ASCII translation involded either. PHP's rule for converting strings to numbers is to discard everything after the first non-numeric character. Per example, (int)"Hello 1234" gives 0, while (int)"1234 Hello" gives 1234 - netcoder 2012-04-06 14:49
Thank you! I didn't know yet - 11684 2012-04-06 14:55


7

I would try to set the $minefield[$x][$y] = '0'; with the quotes, so that both types are string. Might be an issue with that.

Check out the PHP Manual on this subject Comparing Strings to Numbers

2012-04-05 20:20
by KRichardson


1

as a guideline I would not do $i-- inside the loop, as this is a classic infinite-loop generator. instead do another loop inside that keep on generating random mines until it doesn't hit an existing one.

2012-04-05 20:20
by Udi Cohen


1

There is another solution to your problem. You can set it like that and be sure you pick only 10 positions in limited set of coordinates:

<?php

// build minefield
$minefield = array();
for($x=1; $x<=9; $x++) {
    $minefield[$x] = array();
    for($y=1; $y<=9; $y++) {
        $minefield[$x][$y] = 0;
    }
}

// prepare cartesian func
function array_cartesian() {
    $_ = func_get_args();
    if(count($_) == 0)
        return array(array());
    $a = array_shift($_);
    $c = call_user_func_array(__FUNCTION__, $_);
    $r = array();
    foreach($a as $v)
        foreach($c as $p)
            $r[] = array_merge(array($v), $p);
    return $r;
}

// get coordinates
$coords = array_cartesian(range(1,9), range(1,9));
// pick random coordinates' keys
$chosen_coords = array_rand($coords, 10);

foreach ($chosen_coords as $key) {
    $minefield[$coords[$key][0]][$coords[$key][1]] = 'X';
}

I know, it is lengthy, but I could write it in 2-3 lines in Python.

Ps. The code for cartesian product is from here: https://stackoverflow.com/a/2516779/548696

2012-04-05 20:42
by Tadeck


0

the problem is in your second loop. as the indexes are random numbers, so maybe array value of these indexes has been set to X in the else statement, and by a random chance, same indexes will be checked again and again so it will goes to if statement and here is where you minus i!

It is not a good practice to change the value of loop variable i in the body of the loop.

2012-04-05 20:27
by rene
I'm sure he knows how his own code works, but what you're explaining wouldn't produce an infinite loop. It would just take longer than desirable potentially - Devin Burke 2012-04-05 20:30
@JustinSatyr it makes an infinite loop! because he sets all the values of array to X by random, and then if they were equal to X he minuses the loop var - rene 2012-04-05 20:34
No, it's not an infinite loop because he has 81 positions and 10 mines. Thus, eventually, he would reach a mine-free position and increase his variable and continue. Worst case scenerio, it takes a couple seconds - Devin Burke 2012-04-05 20:36
@JustinSatyr maybe you are right, but the approved answer shows that the problem is on something else.. - rene 2012-04-05 20:39


-1

obviously because you decrement the loop counter :

if($minefield[$randx][$randy] == 'X') {
    $i--;
} else {
    $minefield[$randx][$randy] = 'X';
}

at one point all fields will equal 'X' and you'll have an infinite loop.

it is a very bad habit to play with the index in a for loop

2012-04-05 20:20
by Grims
81 points, 10 mines -- all fields can't be equal 'X - Anton 2012-04-05 20:21
my bad, skipped the $mines = 10... at some point the loop will end but that will depend on how random your rand() i - Grims 2012-04-05 20:32
Ads