C++でリンクドリストのクラス
vectorとか怖いので作り、なんとかうまくいったぽい。
多分全く同じ機能がすでにあるだろうけどね……
キモは、新しく追加したオブジェクトがリストの"head"になるところと、(!m->k) を掃除するルーチン内でのみリストからの削除処理がある、というそれを私が今までのものを再利用しやすいところ。そしてそれがクラスとしていくつも作れるようになるところ。
これにより
obj_type *m;
for(m=TitleEffs.GetHead();m;m=m->next)
{
...
}
のとき、そのループの途中で新しく追加されたオブジェクトが参照されずにすむ。
つかいかた:
まずこういうようなstructを用意する。
typedef struct tag_obj_type { int is_used; int k; int mstatnadonado; ... struct tag_obj_type *next; } obj_type;
それでループとかの書きかたは以下のようになる。
// たとえばタイトル画面の // エフェクトにつかうオブジェクト CMonList TitleEffs; ... obj_type *m = TitleEffs.GetNNewMonstAdd(); if (nm) { m->mstat = HOGEHOGE; ... } ... obj_type *m; for(m=TitleEffs.GetHead();m;m=m->next) { if (!m->k) continue; ... //ここで m をつかう //m->k = 0 とするとmが死体としてマークされる } TitleEffs.CleanUpDead();//m->kがゼロのオブジェクトをリストから消す
クラスのコード
//CMonList.h #ifndef __CMONLIST_H_INCED__ #define __CMONLIST_H_INCED__ // "MonObj.h"とかを用意すべきかもしれない。 #include "gmain.h" #include <stdlib.h> #include <string.h> class CMonList { private: int N_MONBUFMAX; obj_type pobjpool[512]; obj_type *head; int objcnt; obj_type * CMonList::PopNewMonst(); public: CMonList() { N_MONBUFMAX = 512; head = NULL; memset(pobjpool,0,sizeof(pobjpool)); objcnt = 0; } int CMonList::GetObjCount() { return objcnt; } obj_type * CMonList::GetHead() { return head; } obj_type * CMonList::GetNNewMonstAdd(); void CMonList::DeleteAll(); void CMonList::CleanUpDead(); }; #endif //__CMONLIST_H_INCED__
//CMonList.cpp #include "CMonList.h" void CMonList::DeleteAll() { head = NULL; memset(pobjpool,0,sizeof(pobjpool)); objcnt = 0; } obj_type * CMonList::PopNewMonst() { int i; obj_type *m = 0; for(i = 0; i < N_MONBUFMAX; i++) { m = &pobjpool[i]; if (!m->is_used) { memset(m,0,sizeof(obj_type)); return m; } } return 0; } obj_type * CMonList::GetNNewMonstAdd() { obj_type *m = PopNewMonst(); if (!m) { return 0; } m->is_used = 1; m->k = 1; m->next = head; head = m; objcnt++; return m; } void CMonList::CleanUpDead() { obj_type *m = head, *mprev = 0, *mnext; if (!m) { //長さゼロ return; } mprev = 0; while(1) { if (!m) break; mnext = m->next; if (!m->k) { if (mprev) { mprev->next = mnext; } else { //首すげ替え head = mnext; } m->is_used = 0; objcnt--; } else { mprev = m; } m = mnext; } }