Ошибка расчета - нужна помощь! - PullRequest
0 голосов
/ 22 сентября 2009

Мне нужно попросить кого-то оказать большую услугу. В приведенном ниже коде вы видите мои расчеты движения поездов для игры в поездах, которую я пишу. Есть проблема с расчетами, но я просто не могу ее найти. Проблема, кажется, находится в этом коде:

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

Я объясню точную проблему позже, но сейчас я хотел бы объяснить логику движения поезда (игру можно найти по адресу http://apps.facebook.com/rails_across_europe):

Игровое поле состоит из карты Европы, содержащей города. Города связаны маршрутами. Маршруты имеют начальный город и конечный город. Маршруты соединены путем, который разделен на элементы пути. Каждый маршрут имеет заданное количество единиц пути. Поезд может следовать по маршруту в положительном (+) или отрицательном (-) направлении. Если город, из которого отправился поезд, является начальным городом маршрута, то поезд движется в положительном направлении. Если начальный город поезда является конечным городом маршрута, то направление отрицательное.

В городе начинается поезд, и пользователь выбирает город назначения для поездки. У поезда есть определенное количество путевых единиц, которые он может проехать за один оборот. Если поезд не имеет достаточного количества единиц пути, чтобы добраться до города назначения за один оборот, то статус поезда устанавливается на «ВХОД», а текущая единица пути поезда устанавливается на единицу пути, на которой остановился поезд. Оставшиеся единицы пути поезда равны нулю (поскольку поезд использовал все свои единицы пути). Если поезд имеет более чем достаточно единиц пути, чтобы добраться до пункта назначения, то поезд останавливается в пункте назначения и статус поезда устанавливается на «ПРИБЫТ». Оставшиеся единицы пути поезда устанавливаются на единицы начального пути поезда минус количество единиц пути, используемых для достижения пункта назначения.

Ход игрока не закончится до тех пор, пока оставшиеся единицы пути его поезда не достигнут нуля, поэтому, как только игрок завершит свои дела в текущем городе, он выберет пункт назначения другого города, и поезд переместит оставшиеся единицы пути в этот город. Если в поезде осталось более чем достаточно единиц пути, чтобы добраться до этого города, он останавливается в городе, и пройденные единицы пути вычитаются из оставшихся единиц пути. Это продолжается до тех пор, пока оставшиеся единицы пути не достигнут нуля.

Проблема заключается в том, что этот код устанавливает $ 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 голосов
/ 22 сентября 2009

Зилупе:

Это последняя версия 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;
  }
0 голосов
/ 22 сентября 2009

Моя интерпретация ваших данных:

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']);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...