北郵2019春計導下 [project] 外賣訂單模擬 3.總體思路

寫在前面

1.這是我的個人博客,我寫的內容僅針對我自己的開發經歷。而且寫博客僅是愛好,不是義務。
2.受能力所限,我的方法並不是最優解。
3.我會放出自己的代碼供大家參考,我相信各位是純潔的。但防小人不防君子,禁止大片剽竊代碼
4.由於大作業並沒有顯著的性能需求,所以代碼中可能存在的內存泄漏的問題沒有完全修復。

(Created by XMind Zen)
在這裏插入圖片描述
初拿到這個項目可能沒有主意,這很正常。
先不要把課題想那麼複雜,僅選取最基本的模塊,文件輸入->文件輸出,就是一個OJ題,之後的命令行動畫、窗口動畫都只是陪襯。
當我拿到訂單的時候,我會想些什麼
訂單讀入後,總能夠按照時間遞增排好序。而對於同一時刻,算法要做的無非就是

1.遍歷騎手,如果騎手抵達食客位置,則執行結算。
2.把訂單派出去(將餐館、食客兩個點按序插入到騎手路徑的合適位置)。
3.將騎手移動到下一個位置。
4.將當前狀態按要求寫入文件。
5.(可選)更新畫面內容,無論是命令行還是窗口動畫。

這便是最粗淺的步驟安排。
數據結構
其實如果是OOP,用類肯定是簡單直接,可惜主代碼鎖死了只讓用C。
單個騎手和單個訂單都可以用結構體來實現自定義。
而存儲騎手總表和訂單總表時,鏈表的自由度肯定會高一些,但是操作和debug的難度更大。我選擇了使用鏈表。
文件組織
總體來說,將公用的結構體定義放在頭文件中,然後在所有的.c源程序中#include該頭文件,.c源程序之間使用extern溝通變量和函數。
總體文件分佈爲

  1. define.h 存儲公用結構體
  2. main.c 主控程序
  3. strategy.c 算法部分
  4. file.c 文件IO部分
  5. display.c 命令行動畫部分
  6. animate.c 窗口動畫部分

我會在隨後的幾篇文章裏逐步放出所有的文件。你可以將他們複製下來,保存成對應的文件名,放在同一個文件夾內,加入一個devcpp的工程,即可編譯。
這樣會比較麻煩,所以我也會將代碼託管到Github上,你將可以Clone一份完全一樣的。

數據結構示例
我設置的最基本的座標單位叫錨點(Anchor),Stopby用於存儲騎手停靠時的信息。
status數組的每個元素有

enum STOPBYSTATUS{
	NOSTOPPING,RESTRAURANT,CUSTOMER
};

這些狀態。
具體定義如下:

define.h

typedef struct _anchor
{
	int x;
	int y;
	struct _order *from;//指向錨點來自訂單及結構體
	struct _anchor *nextPtr;//節點域,用於將錨點串成鏈表
}Anchor;
//錨點:存儲單個座標,根據from可以找出其隸屬的訂單,用指針域可以串成鏈表

typedef struct _order
{
	int id;//訂單id
	int time;//起始時間
	int state;//0表示未被派出可以派單,1表示已經被派出還未送達,2表示已送達 
	Anchor *src;//餐館處的錨點
	Anchor *dst;//食客處的錨點
	struct _order *nextPtr;
}Order;
//訂單:存儲單個訂單,藉助指針域可以串成鏈表

typedef struct _rider
{
	int nodeCnt;//記錄path中含有的錨點數,用於在評估插入新錨點位置時創建數組
	Anchor *pos;//騎手當前位置錨點
	Anchor *path;//path爲帶頭結點的鏈表的哨兵頭結點
	Anchor *stopbyNodes;//騎手停靠的記錄鏈表
	Anchor *lastStopby;//騎手停靠的記錄鏈表的尾結點,方便插入
	struct _rider *nextPtr;
}Rider;
//騎手

typedef struct _node
{
	int num;
	struct _node* nextPtr;
}Node;
//數據鏈表:存儲完成和超時的訂單

typedef struct _qnode
{
	Node *front,*rear;
}QNode;
//數據隊列:儲存超時單號和完成單號

typedef QNode* Queue;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章