问题
edit: Diagonal movement is allowed
I have a 5x5 Grid (just temp. to make it easier on myself though will grow to 30x30 and larger) and I'm trying to determine a grid count between 2 grids, however, it's doing my head in and I was hoping maybe someone can point me in the right direction. What I'm trying to achieve is basically a user chooses 2 grids i.e. 3004
and 3017
it should then find the shortest route and count the grids. For instance, the grid count between 3004
and 3017
should be 4
, the grid count between 3001
and 3005
should be 5
, the grid count between 3001
and 3017
should be 4
, the grid count between 3001
and 3002
should be 2
, etc.
The Grid:
------------------------------------
| 3001 | 3002 | 3003 | 3004 | 3005 |
------------------------------------
| 3006 | 3007 | 3008 | 3009 | 3010 |
------------------------------------
| 3011 | 3012 | 3013 | 3014 | 3015 |
------------------------------------
| 3016 | 3017 | 3018 | 3019 | 3020 |
------------------------------------
| 3021 | 3022 | 3023 | 3024 | 3025 |
------------------------------------
My array is structured in the following way:
$grids = array(
1 => array(
1 => 3001,
2 => 3002,
3 => 3003,
4 => 3004,
5 => 3005
),
2 => array(
1 => 3006,
2 => 3007,
3 => 3008,
4 => 3009,
5 => 3010
),
3 => array(
1 => 3011,
2 => 3012,
3 => 3013,
4 => 3014,
5 => 3015
),
4 => array(
1 => 3016,
2 => 3017,
3 => 3018,
4 => 3019,
5 => 3020
),
5 => array(
1 => 3021,
2 => 3022,
3 => 3023,
4 => 3024,
5 => 3025
),
);
What I have tried:
I realized I could use the good old Hypotenuse a2 + b2 = c2
That worked pretty good for a few examples, but, not everytime. For example, if I plugged in 3004
and 3017
the grid count should be 4
, but, it spits out 5
or if I plugged in 3001
and 3025
the grid count would be 7
, which is outside of the grid itself. I do understand why those results are coming up so I wanted to check if there is a way to improve the formula to make it work somehow?
This issue is killing me as I'm so close to to a solution I can taste it.
A big thank you for all the help in advance!
My current code: (please excuse the messiness)
<style>
.grid {
display: inline-block;
line-height: 50px; padding-left: 10px; padding-right: 10px;
border:1px solid black;
}
.grid.active {
background: red;
}
</style>
<?php
/*
3001 3002 3003 3004 3005
3006 3007 3008 3009 3010
3011 3012 3013 3014 3015
3016 3017 3018 3019 3020
3021 3022 3023 3024 3025
*/
$from = 3001;
$to = 3025;
$grids = array(
1 => array(
1 => 3001,
2 => 3002,
3 => 3003,
4 => 3004,
5 => 3005
),
2 => array(
1 => 3006,
2 => 3007,
3 => 3008,
4 => 3009,
5 => 3010
),
3 => array(
1 => 3011,
2 => 3012,
3 => 3013,
4 => 3014,
5 => 3015
),
4 => array(
1 => 3016,
2 => 3017,
3 => 3018,
4 => 3019,
5 => 3020
),
5 => array(
1 => 3021,
2 => 3022,
3 => 3023,
4 => 3024,
5 => 3025
),
);
$from_cells = 1;
$from_rows = 1;
foreach ( $grids as $y => $xs )
{
$from_cells = 1;
foreach ( $xs as $x => $postcode )
{
if ( $postcode == $from )
{
break 2;
}
else
{
$from_cells++;
}
}
$from_rows++;
}
$to_cells = 1;
$to_rows = 1;
foreach ( $grids as $y => $xs )
{
$to_cells = 1;
foreach ( $xs as $x => $postcode )
{
if ( $postcode == $to )
{
break 2;
}
else
{
$to_cells++;
}
}
$to_rows++;
}
echo "From<hr/>X: $from_cells | Y: $from_rows<br/><hr/>To<hr/>X: $to_cells | Y: $to_rows";
$leg1 = 0;
$leg2 = 0;
$cell_short = ($from_cells < $to_cells) ? $from_cells : $to_cells;
$cell_long = ($from_cells > $to_cells) ? $from_cells : $to_cells;
for ( $i=$cell_short; $i <= $cell_long; $i++ )
{
$leg1 = $i;
}
$row_short = ($from_rows < $to_rows) ? $from_rows : $to_rows;
$row_long = ($from_rows > $to_rows) ? $from_rows : $to_rows;
for ( $i=$row_short; $i <= $row_long; $i++ )
{
$leg2 = $i;
}
echo "<hr/>Length: $leg1<br/>Height: $leg2";
$grid_count = pow($leg1,2) + pow($leg2,2);
$grid_count = floor(sqrt($grid_count));
echo "<hr/>Grids: $grid_count<hr/>";
foreach ( $grids as $y => $xs )
{
foreach ( $xs as $x => $postcode )
{
if ( $postcode == $from or $postcode == $to )
{
echo '<div class="grid active">'.$postcode.'</div>';
}
else
{
echo '<div class="grid">'.$postcode.'</div>';
}
}
echo '<br/>';
}
If any other information is needed please let me know and I'll throw it in.
回答1:
The number of diagonal moves you can make is limited to the number of either rows or columns you have to traverse to get to your destination. All other moves can be left/right or up/down and will preserve the shortest distance.
That said, and assuming you know the row and col numbers for your cells, I believe this will give you your shortest distance:
$startCol = [column of starting cell];
$startRow = [row of starting cell];
$endCol = [column of end cell];
$endRow = [row of end cell];
$numMoves = 0;
$moveCol = 0;
$moveRow = 0;
/*
* figure out which direction the end cell is, in relation to the
* start cell.
*/
// end is to the right, so we need to add columns to the start
if( $startCol < $endCol ) {
$moveCol = 1;
}
// end is to the left (or in the same column), so we need to subtract
// column from the start
else {
$moveCol = -1;
}
// end is below the start, so we need to add rows
if( $startRow < $endRow ) {
$moveRow = 1;
}
// end is above (or in the same row), so we need to subtract rows to the start
else {
$moveRow = -1;
}
/*
* now go diagnoal until you hit either the row or the column
* that the end cell is in
*/
while( $startCol != $endCol && $startRow != $endRow ) {
$startCol += $moveCol;
$startRow += $moveRow;
$numMoves++;
}
/* at this point, we're either in the same row or the same column
* as our destination, so just move down that row or col until we
* reach the destination
*/
// already at the destination, don't do anything
if( $startCol == $endCol && $startRow == $endRow ) {
}
// in the same column, so move up/down rows
else if( $startCol == $endCol ) {
while( $startRow != $endRow ) {
$startRow += $moveRow;
$numMoves++;
}
}
// in the same row, so move left/right cols
else {
while( $startCol != $endCol ) {
$startCol += $moveCol;
$numMoves++;
}
}
echo "min moves: $numMoves";
In this example, you don't need any knowledge of the grid, as long as you assume the start and end co-ordinates are actually within the grid.
回答2:
Perhaps not the most elegant, and could surely be simplified. But it works:
Given:
$from = 3001;
$to = 3025;
$grids = array(
1 => array(
1 => 3001,
2 => 3002,
3 => 3003,
4 => 3004,
5 => 3005
),
2 => array(
1 => 3006,
2 => 3007,
3 => 3008,
4 => 3009,
5 => 3010
),
3 => array(
1 => 3011,
2 => 3012,
3 => 3013,
4 => 3014,
5 => 3015
),
4 => array(
1 => 3016,
2 => 3017,
3 => 3018,
4 => 3019,
5 => 3020
),
5 => array(
1 => 3021,
2 => 3022,
3 => 3023,
4 => 3024,
5 => 3025
),
);
Algorithm:
// Determine the (x,y) coordinates of $from and $to
foreach($grids as $row=>$g) {
if (in_array($from, $g)) {
$from_row = $row;
foreach ($g as $col=>$val) {
if ($val==$from)
$from_col = $col;
}
}
if (in_array($to, $g)) {
$to_row = $row;
foreach ($g as $col=>$val) {
if ($val==$to)
$to_col = $col;
}
}
}
// Difference between $from cols, $to cols and $from rows, $to rows
$col_diff = abs($from_col-$to_col);
$row_diff = abs($from_row-$to_row);
if ($col_diff==4) {
$d = 5;
}
elseif ($col_diff==3) {
if ($row_diff==4)
$d = 5;
else
$d = 4;
}
elseif ($col_diff==2) {
if ($row_diff==4)
$d = 5;
elseif ($row_diff==3)
$d = 4;
else
$d = 3;
}
elseif ($col_diff==1) {
if ($row_diff==4)
$d = 5;
elseif ($row_diff==3)
$d = 4;
elseif ($row_diff==2)
$d = 3;
else
$d = 2;
}
elseif ($col_diff==0) {
if ($row_diff==4)
$d = 5;
elseif ($row_diff==3)
$d = 4;
elseif ($row_diff==2)
$d = 3;
elseif ($row_diff==1)
$d = 2;
else
$d = 1;
}
echo $from . ' -> ' . $to . ' = ' . $d;
来源:https://stackoverflow.com/questions/23533223/php-determining-grid-count-between-2-grids