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?

kopaty4
  • 2,236
  • 4
  • 26
  • 39

6 Answers6

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.

netcoder
  • 66,435
  • 19
  • 125
  • 142
  • and he tried 'Y'? Is it translated to ASCII values or is it always 0? – 11684 Apr 05 '12 at 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 Apr 06 '12 at 14:49
  • Thank you! I didn't know yet! – 11684 Apr 06 '12 at 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

Andrew T Finnell
  • 13,417
  • 3
  • 33
  • 49
KRichardson
  • 990
  • 7
  • 12
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.

Udi Cohen
  • 1,259
  • 9
  • 12
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

Community
  • 1
  • 1
Tadeck
  • 132,510
  • 28
  • 152
  • 198
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.

rene
  • 156
  • 1
  • 2
  • 11
  • 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 Apr 05 '12 at 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 Apr 05 '12 at 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 Apr 05 '12 at 20:36
  • @JustinSatyr maybe you are right, but the approved answer shows that the problem is on something else... – rene Apr 05 '12 at 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

Grims
  • 777
  • 5
  • 6
  • my bad, skipped the $mines = 10... at some point the loop will end but that will depend on how random your rand() is – Grims Apr 05 '12 at 20:32