Hesaplama hatası - need help!

2 Cevap php

Ben büyük bir iyilik için bir başkasına sormak gerekir. Ne aşağıda kodda gördüğünüz ben yazıyorum bir tren oyunu için tren hareket için benim hesaplamalar. Orada hesaplamalar ile bir sorun, ama ben sadece onu bulmak için görünmüyor olabilir. Sorun bu kodda yer gibi görünüyor:

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

Ben daha sonra derinlemesine tam sorunu anlatacağım, ama şimdi, ben tren hareket mantığı (oyun http://apps.facebook.com/rails%5Facross%5Feurope adresinde bulunabilir) açıklamak istiyorum:

Oyun tahtası şehirleri içeren bir Avrupa haritası oluşur. Şehirler yolları ile birbirine bağlanmıştır. Rotalar bir başlangıç ​​şehir ve bir bitiş şehir var. Rotalar parça birimlere ayrılmıştır parçaya göre bağlanır. Her yol, parça birimleri, belirli bir sayıda vardır. (-) Yönde bir tren ya bir (+) pozitif veya negatif bir rota seyahat edebilirler. Tren rotanın başlangıç ​​kentidir başladı kent, daha sonra tren olumlu yönde seyahat ediyor. Trenin başlayarak şehir rotanın bitiş şehir ise, o yönü negatiftir.

Bir tren bir şehirde başlar ve kullanıcı seyahat için bir hedef şehir seçer. Tren tek bir sırayla hareket edebilir parça birimler belirli bir sayıda vardır. Tren bir tek sırayla hedef şehir ulaşmak için yeterli parça birimleri yoksa, o trenin durumunu 'ENROUTE' ayarlanır ve trenin geçerli parça birimi tren durdu iz birimine ayarlanır. Trenin kalan parça birimleri (tren tüm bu 'iz birimlerini beri) sıfırdır. Tren hedefe ulaşmak için yeterli parça birimleri daha fazla varsa, o tren hedefe durur ve tren durumunu 'GELDİ' ayarlanır. Trenin kalan parça birimleri trenler başlangıç ​​parça birimleri eksi hedef var ulaşmak için kullanılan parça birimlerinin sayısına ayarlanır.

Onun Trenin kalan parça birimleri sıfıra gelinceye kadar oyuncuların dönüş sona ermeyecek, bu yüzden oyuncu geçerli şehir onun iş bittikten sonra, o başka bir şehir hedef seçecek ve tren bu şehre doğru iz birimleri kalan oluyor hareket edecektir. Tren bu şehir ulaşmak için kalan yeterli parça birimleri daha fazla varsa, o kentin durur ve pist birimleri kalan Neler gitti iz birimler çıkarılır. Kalan parça birimleri sıfıra ulaşana kadar bu devam ediyor.

Sorun bu kod, sıfıra $ trackUnitCount setleri sonra sırayla tren (yanlış), hedef kente geldiğini gösterir ki, sıfıra trenin geçerli parça birimini belirleyen olmasıdır. (O hedef şehir geldi önce) bu oyuncunun dönüş bitirmesi gereken kalan parça birimlerinin tükeniyor olmadan başka bir şehirden diğerine atlamalı tren sonuçları

Bu konuda bana yardımcı olabilir eğer, gerçekten bir siber-aziz vardır :)

  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 Cevap

Veri Benim yorumum:

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

BURADAN HER ŞEY AÇIK düzenlendi:

Let's clarify the source/destination switching, otherwise the code is hard to understand. The idea is not to instantiate a variable in two mutually exclusive branches. Better have a default value and change it if needed. At least that works better if there is a clear default value.

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

Ben kod kalanı doğru olduğundan emin olamaz, bu yüzden biz yeniden bir kod ayıklamak ve bunu test öneririm:

Copy this in a separate file and try to run. I'm sorry I don't have a PHP machine now, can't test myself. This code is independent from your framework and everything else.

Bu test edilebilir birini kullanır, böylece aslında orijinal işlevini değiştirebilirsiniz. Sadece bunun için gerekli bilgi kalanını geçirmek.

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']);
}

Zilupe:

Bu moveTrain en son sürümü (). O zaman% 90 iş gibi görünüyor, ama yine de tuhaflıklar var. Senin yardımın olmadan bunu yapamazdım. Teşekkürler!

  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;
  }