[分享] 用一個字串處理所有任務標記

看板mud (網路地下城/文字遊戲)作者 (小太保)時間13年前 (2012/06/14 16:17), 編輯推噓1(104)
留言5則, 1人參與, 最新討論串1/1
假設某遊戲有 100 個任務,那可以簡單用一個字串來代表 "111111101110110100010101100100100001010001000......" 為此我們必須先定義一個 array 類似底下 string *quests=({ "與村裡的人們打招呼", "獵殺20隻怪物", . . }); 則上面字串的第一個字元"1"就代表玩家已完成「與村裡的 人們打招呼」的這項任務(或成就)。 則我們需要幾個函數來處理,底下就簡單以 set_quest 為 例,ppl 代表玩家,quest_name 代表任務名稱,quest 為 存在玩家 ppl 身上的標記(ppl->query("quest")) void set_quest(object ppl,string quest_name) { int i,s; string tmp,new_tmp; // 先依 quest_name 找出是第幾個任務 i = member_array(quest_name,quests); if(i==-1) return 0; // 讀取玩家身上的 quest 標記 tmp = ppl->query("quest"); // 1.先判斷該字串的長度, 若長度較小要補 0 // 例如原先字串是 "1001" 而現在所解的是第 8 個任務 // 則 "1001" 要先變成 "10010000" s=strlen(tmp); if(s<i+1) while(s++<=i) tmp+="0"; // 2.再將這個任務標記設進去 if(tmp[i..i]=="0") new_tmp=tmp[0..i-1]+"1"; } 而 check 的方法也很簡單 int check_quest(object ppl,string quest_name) { int i; string tmp; // 一樣是先依 quest_name 找出是第幾個任務 i = member_array(quest_name,quests); if(i == -1) return -1; // 然後一樣讀取玩家身上的 quest 標記 tmp = ppl->query("quest"); // 然後先判斷玩家沒解過這個任務的情況 // 首先字串長度小於 i+1 的情況肯定沒解過 if(strlen(tmp)<i+1) return 0; // 再來就是 tmp[i..i] = 0 的情況也是沒解過 if(tmp[i..i]=="0") return 0; // 能來到這裡自然就是有解過啦 return 1; } 至於 list_quest 則如下.. void list_quest(object ppl) { string tmp,str="任務的已解/未解列表:\==============================\n"; int sp,sq,i; tmp=ppl->query("quest"); sp = strlen(tmp); sq = sizeof(quests); for(i=0;i<sq;i++) { if(i<=sp) { if(tmp[i..i]=="1") str+=sprintf("%-20s 已解\n",quests[i]); else str+=sprintf("%-20s 未解\n",quests[i]); } else str+=sprintf("%-20s 未解\n",quests[i]); } str+="==============================\n"); write(str); } 這麼做有以下幾個好處.. 一、用一個字串就解決所有任務的標記。 二、字串長度 100 看似很長,不過跟玩家 data 檔案大小比起來 其實還好。 三、wiz 可以製作方便的工具 foreach(ppl in users()) write(ppl->query("name")+" "+ppl->query("quest")+"\n"); 馬上能列出線上玩家的 quest 字串,就能做即時的簡易比對 ,如下.. laechan 1110010100101010101010101010 norr 11001010101010101000010010010001010 highelf 10001010100101001000101010 . ^ ^ ^ <- 這三人都有解過的任務 . 四、它一樣可以做前置任務的判斷 例如要解第 i 個任務,需要先解第 x 個任務跟第 y 個任務 ,那只需要判斷 tmp[x..x]==1 && tmp[y..y]==1 即可,在前 置任務的判斷上相當地簡易。 一點心得,分享給各位。 Laechan -- ※ 發信站: 批踢踢實業坊(ptt.cc) ※ 編輯: laechan 來自: 210.61.157.53 (06/14 16:17)

06/14 16:58, , 1F
強烈建議變數命名要有意義且初始化
06/14 16:58, 1F

06/14 16:59, , 2F
其實也可以用兩個字串,一個代表解過一個未解過
06/14 16:59, 2F

06/14 16:59, , 3F
每個任務有唯一的qid,不是讓開發者更容易辨識嗎
06/14 16:59, 3F

06/14 17:00, , 4F
一堆1001010感覺不方便看是哪一個任務
06/14 17:00, 4F

06/14 17:02, , 5F
若是要用一個字串,我會建議用map之類的方式來做而不是array
06/14 17:02, 5F
這是以節省儲存空間為考量,以這種方式要新增新的任務 也方便,quests 多添加一個元素,函數即會自動替玩家的 quest 參數初始化(在呼叫到 set_quest 時)。 基本原則是 1.每個任務的陣列順序是確定的 2.但是每個任務的相對順序是可以自訂的 3.任務標記平常「其實一點用也沒有就只是儲存用而已」 ,因此只需要在用到時(例如在做 list 時)呼叫出來處 理即可. 就算是 111010101010101 只要呼叫專門處理函 數即可馬上處理成為看得懂的資料. ※ 編輯: laechan 來自: 122.117.11.103 (06/14 18:29)
文章代碼(AID): #1FsPuMsU (mud)
文章代碼(AID): #1FsPuMsU (mud)