计算错误 - 需要帮助!

时间:2009-09-21 22:25:32

标签: php zend-framework math

我需要向某人求助。您在下面的代码中看到的是我正在编写的火车游戏的列车运动计算。计算有问题,但我似乎无法找到它。问题似乎位于此代码中:

      if($trainRow['direction'] == '-') {
        $trackUnitCount = $routeData['track_unit_count'] - $trackUnitCount;
      }

我稍后会更详细地解释确切的问题,但是现在,我想解释一下列车运动逻辑(游戏可以在http://apps.facebook.com/rails_across_europe找到):

游戏板包含一个包含城市的欧洲地图。城市通过路线连接。路线有一个起始城市和一个结束城市。路线通过轨道连接,轨道分为轨道单元。每条路线都有一定数量的轨道单元。火车可以以正(+)或负( - )方向行驶。如果火车开始的城市是路线的起始城市,那么火车正朝着积极的方向行驶。如果列车的起始城市是路线的结束城市,则方向为负。

火车在一个城市开始,用户选择一个目的地城市前往。火车具有一定数量的轨道单元,它可以在一个回合中行进。如果列车没有足够的轨道单元一次到达目的地城市,则列车的状态设置为“ENROUTE”,列车的当前轨道单元设置为列车停靠的轨道单元。列车的剩余轨道单位为零(因为列车使用了所有轨道单元)。如果火车有足够的轨道单元到达目的地,那么火车在目的地停靠,火车的状态设置为“到达”。列车的剩余轨道单元设置为列车起始轨道单元减去用于到达目的地的轨道单元的数量。

在他的火车剩余赛道单位达到零之前,玩家的回合不会结束,所以一旦玩家在当前城市完成了他的生意,他将选择另一个城市目的地并且火车将其剩余的轨道单元移动到该城市。如果火车有足够的轨道单元到达该城市,那么它将在城市停靠,并且从其剩余的轨道单元中减去行进的轨道单元。这一直持续到剩余的轨道单元达到零。

问题在于此代码将$ trackUnitCount设置为零,然后将列车的当前轨道单位设置为零,这表示列车已到达目的地城市(这是不正确的)。这导致火车从一个城市跳到另一个城市,而没有剩余的轨道单元,这应该结束玩家的回合(在他到达目的地城市之前)

如果你可以帮助我解决这个问题,你真的是一个网络圣人:)

  public function moveTrain($destCityId) {
    require_once 'Train.php';
    $trainModel = new Train();

    require_once 'Route.php';
    $routeModel = new Route();

    $userNamespace = new Zend_Session_Namespace('User');
    $gamePlayerId = $userNamespace->gamePlayerId;

    $trainData = $trainModel->getTrain($gamePlayerId);

    if($destCityId == $trainData['dest_city_id']) {
      $originCityId = $trainData['origin_city_id'];
    } else {
      $originCityId = $trainData['dest_city_id'];
    }
    $routeId = $routeModel->getRouteIdByCityIds($originCityId, $destCityId);
    $trainRow = array();
    if($routeId !== null) {
      $routeData = $routeModel->getRouteByCityIds($originCityId, $destCityId);
      $trainRow['direction'] = $routeModel->getRouteTravelDirection($originCityId, $destCityId); //+
      //$routeData['track_unit_count'] are the total number of track units in this route
      //$trainData['track_unit'] is the track unit the train is currently stopped on
      $trackUnitCount = $routeData['track_unit_count'] - $trainData['track_unit']; //6-3=3
      //$trainData['track_units_remaining'] are the number of track units the train has left to move
      $trackUnitsRemaining = $trainData['track_units_remaining'] - $trackUnitCount; //5-3=2
      if($trackUnitsRemaining > 0) {
        $trackUnitsTraveled = $trackUnitCount; //2
      } else {
        $trackUnitsTraveled = $trainData['track_units_remaining'];
        $trackUnitsRemaining = 0;
      }
      //$trainRow = $trainData;

      $trainRow['route_id'] = $routeId;
      $trainRow['origin_city_id'] = $originCityId;
      $trainRow['dest_city_id'] = $destCityId;

      if($trainRow['direction'] == '+') {
        $trainRowTrackUnit = $trackUnitsTraveled + $trainData['track_unit']; //2+3=5
      } else {
        $trainRowTrackUnit = $routeData['track_unit_count'] - $trainData['track_units_remaining'];
        if($trainRowTrackUnit < 0) $trainRowTrackUnit = 0;
      }
      $trainRow['track_unit'] = $trainRowTrackUnit; //5
      $trainRow['track_units_remaining'] = $trackUnitsRemaining; //2
      $trainArrived = ($trainRowTrackUnit == 0 || $trainRowTrackUnit == $routeData['track_unit_count']);
      $trainRow['status'] = ($trainArrived == true) ? 'ARRIVED' : 'ENROUTE';

      $trainId = $trainModel->getTrainId($gamePlayerId);
      $where = $trainModel->getAdapter()->quoteInto('id = ?', $trainId);
      $trainModel->update($trainRow, $where);
    }
    return $trainRow;
  }

2 个答案:

答案 0 :(得分:0)

我对您的数据的解释:

trainData['track_units_remaining'] -- number of units the player can move
trainData['track_unit'] -- the unit on which the train is now
trainData['direction'] -- the direction of train movement
routeData['track_unit_count'] -- route length

此处的所有内容都已编辑:

让我们澄清源/目的地切换,否则代码很难理解。 这个想法不是在两个互斥的分支中实例化一个变量。 最好有一个默认值,并在需要时更改它。 如果有明确的默认值,至少可以更好地工作。

$originCityId = $trainData['origin_city_id'];
if ( $destCityId != $trainData['dest_city_id'] ) {
    $originCityId = $trainData['dest_city_id'];
}

我无法确定您的其余代码是否正确,因此我建议您提取我们重新编写的代码并进行测试:

将其复制到单独的文件中并尝试运行。 对不起,我现在没有PHP机器,无法测试自己。 此代码独立于您的框架和其他所有内容。

您实际上可以更改原始功能,以便使用此可测试功能。只需将剩下的所需信息传递给它。

function testableMoveTrains($trainData, $routeData) {

    $unitsToDestination = 0;
    switch ( $trainRow['direction'] ) {
        case '+':
            $unitsToDestination = $routeData['track_unit_count'] - $trainData['track_unit'];
            break;
        case '-':
            $unitsToDestination = $trainData['track_unit'];
            break;
         default:
            break;
    }

    $unitsToDestination = $unitsToDestination - $trainData['track_units_remaining'];

    $trackUnitsRemaining = 0;
    $trainArrived = false;

    // Note that I changed from < to <=
    if ( $unitsToDestination <= 0) {
        // Went too far or arrived. 
        $trackUnitsRemaining = abs($unitsToDestination);
        $trackUnit = $routeData['track_unit_count'];
        $trainArrived = true;
    } else {
        // Did not reach destination
        $trackUnitsRemaining = 0;
        switch ( $trainRow['direction'] ) {
            case '+':
                $trackUnit = $routeData['track_unit_count'] - $unitsToDestination;
                break;
            case '-':
                $trackUnit = $unitsToDestination;
                break;
            default:
                break;
        }
    }

    $trainRow = array();
    $trainRow['direction'] = $trainData['direction'];
    $trainRow['track_unit'] = $trackUnit;
    $trainRow['track_units_remaining'] = $trackUnitsRemaining;
    $trainRow['status'] = ($trainArrived) ? 'ARRIVED' : 'ENROUTE';

    return $trainRow;
}

// *******************************************

$trainData = array(
    'track_units_remaining' => 5,
    'track_unit' => 0,
    'direction' => '+',
    'status' => ''
);

$routeData = array(
    'track_units_count' => 8
);

$newTrainData = testableMoveTrains($trainData, $routeData);

if ( $newTrainData['track_unit']!=5 ) {
    error('Unexpected track_unit value:' . $newTrainData['track_unit']);
}
if ( $newTrainData['track_units_remaining']!=3 ) {
    error('Unexpected track_units_remaining value:' . $newTrainData['track_units_remaining']);
}
if ( $newTrainData['status']!='ENROUTE' ) {
    error('Unexpected status value:' . $newTrainData['status']);
}

答案 1 :(得分:0)

济卢佩:

这是moveTrain()的最新版本。它似乎在90%的时间里工作,但它仍然有它的怪癖。没有你的帮助,我无法做到。谢谢!

  public function moveTrain($destCityId) {
    require_once 'Train.php';
    $trainModel = new Train();

    require_once 'Route.php';
    $routeModel = new Route();

    $userNamespace = new Zend_Session_Namespace('User');
    $gamePlayerId = $userNamespace->gamePlayerId;

    $trainData = $trainModel->getTrain($gamePlayerId);

    $originCityId = $trainData['origin_city_id'];
    $destChanged = false;
    if ( $destCityId != $trainData['dest_city_id'] ) {
        $originCityId = $trainData['dest_city_id'];
        $destChanged = true;
    }
    $routeId = $routeModel->getPlayerRouteIdByCityIds($gamePlayerId, $originCityId, $destCityId);
    $trainRow = array();
    // if route is invalid OR if destination city has not changed and train has arrived,
    // bypass train movement
    if($routeId !== null) {
      if((!$destChanged && $trainData['status'] == 'ENROUTE') ||
        ($destChanged && $trainData['status'] == 'ARRIVED')) {
        $routeData = $routeModel->getRouteByCityIds($originCityId, $destCityId);
        $unitsToDestination = 0;
        $trainRow['direction'] = $routeModel->getRouteTravelDirection($originCityId, $destCityId); //+
        // if traveling to a new city destination and traveling negative then train track unit
        // is equal to route track unit count (because train is at the end of a new route)
        if($destChanged && $trainRow['direction'] == '-' && $trainData['status'] == 'ARRIVED') {
          $trainData['track_unit'] = $routeData['track_unit_count'];
        }
        switch ($trainRow['direction']) {
            case '+':
                $unitsToDestination = $routeData['track_unit_count'] - $trainData['track_unit'];
                break;
            case '-':
                $unitsToDestination = $trainData['track_unit'];
                break;
            default:
                break;
        }
        // 2. Move the train
        $unitsToDestination = $unitsToDestination - $trainData['track_units_remaining'];
        $trackUnitsRemaining = 0;
        $trainArrived = false;

        // Note that I changed from < to <=
        if ( $unitsToDestination <= 0) {
            // Went too far or arrived.
            $trackUnitsRemaining = abs($unitsToDestination);
            $trackUnit = $routeData['track_unit_count'];
            if($trainRow['direction'] == '-') {
              $trackUnit = 0;
            }
            $trainArrived = true;
        } else {
            // Did not reach destination
            $trackUnitsRemaining = 0;
            switch ( $trainRow['direction'] ) {
                    case '+':
                            $trackUnit = $routeData['track_unit_count'] - $unitsToDestination;
                            break;
                    case '-':
                            $trackUnit = $unitsToDestination;
                            break;
                    default:
                            break;
            }
        }
        // 3. Save changes carefully.
        $trainRow['route_id'] = $routeId;
        $trainRow['origin_city_id'] = $originCityId;
        $trainRow['dest_city_id'] = $destCityId;
        $trainRow['track_unit'] = $trackUnit; //5
        $trainRow['track_units_remaining'] = $trackUnitsRemaining; //2
        // $trainArrived = ($trackUnit == 0 || $trackUnit == $routeData['track_unit_count']);
        $trainRow['status'] = ($trainArrived) ? 'ARRIVED' : 'ENROUTE';

        //$trainId = $trainModel->getTrainId($gamePlayerId);
        $where = $trainModel->getAdapter()->quoteInto('id = ?', $trainData['id']);
        $trainModel->update($trainRow, $where);
      } else {
        $trainRow = $trainData;
      }
    }
    return $trainRow;
  }