Parking Spot
设计一个停车场
这道题让我们实现一个停车位的数据结构,由于题目没给任何多余的信息,所>以自由度很大,比如能停放什么种类的车,或是否是多层的等等。根据书中描>述,这里我们做如下假设:
- 停车场有多层,每层有多行停车位
- 停车场可以停摩托车,小轿车和公交车
- 停车场有摩托车位,紧凑型车位,和大型车位
- 摩托车可以停在任何位置
- 小轿车可以停在紧凑型车位和大型车位
- 公交车只能停在同一行中连续的五个大型车位上,不能停在小位置上
- 停车位ParkingSpot类,一个停车场ParkLot由多个停车层Level组成,一个Level由多个ParkingSpot组成
- 基类Vehicle,机动车,可以被继承,具体实例化为motocycle,car,truck
大小,需要的停车位,停车入库,是否合适这个spot - 停车层Level类,ParkingSpot类的集合
还剩多少停车位,停车入库function(包括判断车位是否充足,找到应该停在哪个车位,停进去三部曲)
参考链接:https://blog.csdn.net/xjwun/article/details/43484327
<?php
class ParkingSpot {
private $vehicle;
private $spotSize;
private $row;
private $spotNum;
private $level;
/**
* ParkingSpot constructor.
* @param Level $lvl 层数
* @param $r 第几列
* @param $n spot numer,一个标示
* @param $size spot的大小
*/
public function __construct(Level $lvl, $r, $n, $size) {
$this->level = $lvl;
$this->row = $r;
$this->spotNum = $n;
$this->spotSize = $size;
//vehicle初始为null,因为没停车
}
/**
* isAvailable
* @return bool
* @brief 判断当前spot是否可用
*/
public function isAvailable() {
return $this->vehicle == null;
}
/**
* canFitVehicle
* @param Vehicle $vehicle
* @return bool
*/
public function canFitVehicle(Vehicle $vehicle) {
return $this->isAvailable() && $vehicle->canFitInSpot($this);
}
/**
* park
* @param Vehicle $v
* @return bool
* @brief 停车入库
*/
public function park(Vehicle $v) {
if (!$this->canFitVehicle()) {
return false;
}
$v->parkInSpot($this);
return true;
}
/**
* removeVehicle
* @return void
* @brief 出库
*/
public function removeVehicle() {
//todo
$this->level->spotFreed();
$this->vehicle = null;
}
public function getRow() {
return $this->spotNum;
}
public function getSize() {
return $this->spotSize;
}
}
class Level {
private $floor;
private $spots;//parkingpot 的集合
private $availableSpots = 0;
const SPOTS_PER_ROW = 10;
public function __construct($floor, $spotsnum) {
$this->floor = $floor;
$this->spots = [];//理论上这里的array要申明长度为spotsnum
}
/**
* parkVehicle
* @param Vehicle $vehicle
* @return bool
* @brief 停车入位
*/
public function parkVehicle(Vehicle $vehicle) {
// 车位不足
if ($this->availableSpots < $vehicle->getSpotsNeeded()) {
return false;
}
//这里的spotNum是spots这个array的索引,并不是spots类里面的spotNum
$spotNum = $this->findAvailableSpots($vehicle);
if ($spotNum < 0) {
return false;
}
return $this->parkStartingAtSpot($spotNum, $vehicle);
}
/**
* findAvailableSpots
* @param Vehicle $vehicle
* @return int spots的索引$i
* @brief 查找是否有车位能符合这辆车
*
*/
public function findAvailableSpots(Vehicle $vehicle) {
$spotNeeded = $vehicle->getSpotsNeeded();
$lastRow = -1;
$spotsFound = 0;
for ($i = 0; $i < count($this->spots); $i++) {
$spot = $this->spots[$i];//spot 为一个Parking Spot
//换行则重新计算
if ($lastRow != $spot->getRow()) {
$spotsFound = 0;
$lastRow = $spot->getRow();
}
//canFitVehicle 只判断size是否合适,(类似一个truck需要5个spot,所以需要循环)
if ($spot->canFitVehicle(vehicle)) {
$spotsFound++;
} else {
$spotsFound = 0;
}
if ($spotsFound == $spotNeeded) {
return $i - ($spotNeeded - 1);//index of spot
}
}
return -1;
}
/**
* parkStartingAtSpot
* @param $spotNum
* @param Vehicle $vehicle
* @return bool
*/
private function parkStartingAtSpot($spotNum, Vehicle $vehicle) {
$vehicle->clearSpots();
$success = true;
for ($i = $spotNum; $i < $spotNum + $vehicle->getSpotsNeeded(); $i++) {
$success &= $this->spots[$i]->park($vehicle);
}
$this->availableSpots -= $vehicle->getSpotsNeeded();
return $success;
}
public function spotFreed() {
$this->availableSpots++;
}
/**
* availableSpots
* @return int
* @brief 返回当前可用spot的数量
*/
public function availableSpots() {
return $this->availableSpots;
}
}
class Vehicle {
protected $size;
protected $license;//car license id
protected $spotNeed;
protected $parkingSpots = [];//一个车可能停在多个spot上面,所以是array
protected $vehicleSize = [
"motocycle" => 1,
"car" => 2,
"truck" => 3,
];
public function __construct() {
}
public function getSize() {
return $this->size;
}
public function getSpotsNeeded() {
return $this->spotNeed;
}
/**
* parkInSpot
* @param ParkingSpot $spot
* @return void
* @brief 停车入库
*/
public function parkInSpot(ParkingSpot $spot) {
$this->parkingSpots[] = $spot;
}
/**
* clearSpots
* @return void
*/
public function clearSpots() {
$this->parkingSpots = [];
}
public function canFitInSpot(ParkingSpot $spot) {
}
}
class Motocycle extends Vehicle {
public function __construct() {
$this->spotNeed = 1;
$this->size = $this->vehicleSize['motocycle'];
}
/**
* canFitInSpot
* @param ParkingSpot $spot
* @return bool|void
*/
public function canFitInSpot(ParkingSpot $spot) {
return true;
}
}
class Car extends Vehicle {
/**
* Car constructor.
*/
public function __construct() {
$this->spotNeed = 1;
$this->size = $this->vehicleSize['car'];
}
/**
* canFitInSpot
* @param ParkingSpot $spot
* @return bool|void
* @brief
*/
public function canFitInSpot(ParkingSpot $spot) {
return ($spot->getSize() == $this->vehicleSize['car']) || ($spot->getSize() == $this->vehicleSize['truck']);
}
}
class Truck extends Vehicle {
public function __construct() {
$this->spotNeed = 5;
$this->size = $this->vehicleSize['truck'];
}
/**
* canFitInSpot
* @param ParkingSpot $spot
* @return bool|void
* @biref 只判断能不能停,
*/
public function canFitInSpot(ParkingSpot $spot) {
return $spot->getSize() == $this->vehicleSize['truck'];
}
}
class ParkingLot {
private $levels;
const NUM_LEVELS = 5;
/**
* ParkingLot constructor.
*
*/
public function __construct() {
$this->levels = [];
for ($i = 0; $i < self::NUM_LEVELS; $i++) {
$this->levels[$i] = new Level($i, 30);
}
}
public function parkVehicle(Vehicle $vehicle){
for($i = 0;$i<count($this->levels);$i++){
if($this->levels[$i]->parkVehicle[$vehicle]){
return true;
}
}
return false;
}
}