简体   繁体   中英

Why code goes to infinite loop? (

<?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?

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.

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

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.

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

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM