Search code examples
phparrayscrossword

php marking grid intersections x/y coords


I am trying to take an array of data containing x/y coords and directional info (across or down) and linking shared cells with a incrementing number. This is for a crossword puzzle. Here is the original array:

Array
(
[0] => Array
    (
        [id] => 1
        [puzzle_id] => 1
        [word] => hello
        [hint] => 
        [direction] => across
        [grid_x] => 3
        [grid_y] => 1
    )

[1] => Array
    (
        [id] => 2
        [puzzle_id] => 1
        [word] => loot
        [hint] => 
        [direction] => down
        [grid_x] => 5
        [grid_y] => 1
    )

[2] => Array
    (
        [id] => 3
        [puzzle_id] => 1
        [word] => hellotest
        [hint] => 
        [direction] => down
        [grid_x] => 3
        [grid_y] => 1
    )

[3] => Array
    (
        [id] => 4
        [puzzle_id] => 1
        [word] => looking
        [hint] => 
        [direction] => across
        [grid_x] => 3
        [grid_y] => 3
    )

)

I want to add a new key to each entry called "num" that will start at 1 and increment by 1 but the tricky part is I need across AND down to share the same number if they share a starting cell (share a grid_x and grid_y). This is the code I have now but it doesn't produce the correct numbers I am looking for.

$puzzle_data2 = $puzzle_data;


$across_counter = 1;
foreach($puzzle_data as $rkey=>$row)
{
    if($row['direction'] == 'across')
    {
        $puzzle_data[$rkey]['num'] = $across_counter++;

        foreach($puzzle_data2 as $rkey2=>$row2)
        {
            if($row['direction'] == 'down')
            {
                if($row['grid_x'] == $row2['grid_x'] && $row['grid_y'] == $row2['grid_y'])
                {
                    $puzzle_data[$rkey2]['num'] = $across_counter;
                    break;
                }
            }
        }
    }
}
foreach($puzzle_data as $rkey=>$row)
{
    if(!isset($row['num']))
    {
        $puzzle_data[$rkey]['num'] = $across_counter++;
    }
}

I end up getting this result:

Array
(
[0] => Array
    (
        [id] => 1
        [puzzle_id] => 1
        [word] => hello
        [hint] => 
        [direction] => across
        [grid_x] => 3
        [grid_y] => 1
        [num] => 1
    )

[1] => Array
    (
        [id] => 2
        [puzzle_id] => 1
        [word] => loot
        [hint] => 
        [direction] => down
        [grid_x] => 5
        [grid_y] => 1
        [num] => 3
    )

[2] => Array
    (
        [id] => 3
        [puzzle_id] => 1
        [word] => hellotest
        [hint] => 
        [direction] => down
        [grid_x] => 3
        [grid_y] => 1
        [num] => 4
    )

[3] => Array
    (
        [id] => 4
        [puzzle_id] => 1
        [word] => looking
        [hint] => 
        [direction] => across
        [grid_x] => 3
        [grid_y] => 3
        [num] => 2
    )

)

I am looking for ID 1 and 3 to both be "1". If you think of a crossword puzzle where a down and across share the same starting cell its labeled with the same number in the across and down key, that is what I am trying to accomplish with my data set.

Thanks for your time.

enter image description here


Solution

  • You should sort the data first, so that entries on the top left are first, going across the line, before moving down to the next line. IE the way we read.

    We can take grid_x and grid_y and calculate which is first.

    Then we can use these to sort the data.

    function cmp($a, $b)
    {
        $a_index=($a['grid_y']*100)+$a['grid_x'];
        $b_index=($b['grid_y']*100)+$b['grid_x'];
        if ($a_index == $b_index)
        {
            return 0;
        }
        return ($a_index < $b_index) ? -1 : 1;
    }
    usort($puzzle_data, "cmp");
    

    I've used 100 here to make things easier, but you should use the width of the grid for more accuracy.

    x1,y1 would give 101
    x3,y1 would give 103
    x1,y3 would give 301
    y3,y3 would give 303

    so the order would be 101, 103, 301, 303

    Then apply the numbers to the data using grid_x and grid_y to test if already done.

    $number=1;
    $grid_numbers=array();
    foreach($puzzle_data as $rkey=>$row)
    {
        if(isset($grid_numbers[$row['grid_x']][$row['grid_y']]))
        {
            $puzzle_data[$rkey]['num'] = $grid_numbers[$row['grid_x']][$row['grid_y']];
        }
        else
        {
            $grid_numbers[$row['grid_x']][$row['grid_y']]=$number;
            $puzzle_data[$rkey]['num']=$number;
            $number++;
        }
    }
    

    That should be everything