ページ 1 / 1
構造体ポインタの共有
Posted: 2012年9月11日(火) 21:12
by カフェ・ブルー
どうも。
現在C++でRPGを作ろうと試行錯誤しているプログラミング初心者です。
今回、アイテムの処理を作ろうとしているのですが、疑問に思ったことがあったのでトピックを立てました。
コード:
struct TEST{
int heal;char name[50];char detail[150];int gazo;
TEST *next;TEST *prev;
};
struct AtkItem{
int power;char name[50];char detail[150];int gazo;int *gazop;
AtkItem *next;AtkItem *prev;
};
この場合、二つの構造体のポインタに互換性を持たせる方法はあるでしょうか?
現在TEST構造体のみで双方向ノードを製作していたため(メイン文にTEST型のポインタを宣言し、リストを追加、削除していました)、新しい構造体の型の出現に頭を悩ませています。
何か良い方法はあるでしょうか。
Re: 構造体ポインタの共有
Posted: 2012年9月11日(火) 21:53
by nil
C++で、というのなら継承とオーバーライドを使えば解決できますが、
void*と列挙体を組み合わせて列挙体の値によって処理を変えるなどはどうでしょう。
あと、構造体の命名規則を揃えたほうが良いです。
Re: 構造体ポインタの共有
Posted: 2012年9月11日(火) 22:17
by カフェ・ブルー
はじめまして、涼雅さん。質問にお答えしていただきありがとうございます。
>>C++で、というのなら継承とオーバーライドを使えば解決できますが、
継承を使う方法がありましたか。
実を言うと、最初はクラスでアイテムを作ろうとして断念したのですが、失念していました;;
>>void*と列挙体を組み合わせて列挙体の値によって処理を変えるなどはどうでしょう。
なるほどvoid*というものがあるのですか!
調べてみるとちょっと手ごわそうな;;
ありがとうございます、その方法でトライしてみます。
>>あと、構造体の命名規則を揃えたほうが良いです。
そうですね(汗
トピック投稿してから気がつきました、以後気をつけます。
Re: 構造体ポインタの共有
Posted: 2012年9月11日(火) 22:57
by softya(ソフト屋)
void*を使うぐらいなら回復でも装備でもメンバ名を統一して1つの構造体で情報を持てるようにするほうが良いでしょう。
その場合でも涼雅さんの言われる列挙体はアイテムの種別を表すメンバとして必要です。
最終的にRPGだと構造体メンバはもっと増える気がします。所持数とか価格とか。
なので横に並べる見づらい書き方は止めたほうが良いでしょう。
それとchar name[50];char detail[150];ってstringを使わない理由は?
Re: 構造体ポインタの共有
Posted: 2012年9月11日(火) 23:17
by カフェ・ブルー
softya(ソフト屋) さんが書きました:void*を使うぐらいなら回復でも装備でもメンバ名を統一して1つの構造体で情報を持てるようにするほうが良いでしょう。
その場合でも涼雅さんの言われる列挙体はアイテムの種別を表すメンバとして必要です。
それはつまり、薬草でも「威力」を持ち、武器でも「回復量」を持たせるということですか?
そして列挙体によってアイテムの分類を判別して適宜追加していくということですか?
softya(ソフト屋) さんが書きました:最終的にRPGだと構造体メンバはもっと増える気がします。所持数とか価格とか。
なので横に並べる見づらい書き方は止めたほうが良いでしょう。
確かに上記の方法(自分の解釈が正しければ)メンバ数は非常に増えますね・・。
そういったことを見越して、見やすいプログラミングの書き方を心得ていきたいです。
softya(ソフト屋) さんが書きました:それとchar name[50];char detail[150];ってstringを使わない理由は?
特にありませんね・・。
ただstringを知らなかった頃の名残ですw
見づらかったので修正しました。 by softya(ソフト屋)
Re: 構造体ポインタの共有
Posted: 2012年9月12日(水) 07:32
by beatle
構造体の中にnext, prevを持っているということは、きっと双方向リストにするつもりなのだと思います。
そうだとすると、C++には std::vector や std::list がありますので、それらを使うほうが簡単だと思います。
自分でリストの処理を書かなくていいですからね。
コード:
struct AtkItem {
int power;
std::string name;
std::string detail;
int gazo;
int *gazop;
};
std::vector<AtkItem> atkItems;
Re: 構造体ポインタの共有
Posted: 2012年9月12日(水) 11:56
by softya(ソフト屋)
>薬草でも「威力」を持ち、武器でも「回復量」を持たせるということですか?
両方共、効果値ではあるわけですよね? そう考えれば名称は統一できませんか。
ただし、防御力が増える武器とか回復力がある鎧とかがあるのであれば別メンバにしたほうが良いでしょう。
つまり、ゲーム設定上でアイテムの持つ特殊効果もあわせて考えないとアイテム情報は決められないってことですね。
それとアイテム所持は別のリストになりますね。なのでアイテム所持数は撤回します。失礼しました。
これは単にアイテム情報のリストって考えてよいでしょうか? そうであれば、リストでは無く配列のほうが扱いやすいと思います。
Re: 構造体ポインタの共有
Posted: 2012年9月12日(水) 14:56
by カフェ・ブルー
beatleさん。
>>構造体の中にnext, prevを持っているということは、きっと双方向リストにするつもりなのだと思います。
そうだとすると、C++には std::vector や std::list がありますので、それらを使うほうが簡単だと思います。
自分でリストの処理を書かなくていいですからね。
コードまで貼り付けていただきありがとうございます。
そうです。双方向ノードにするつもりです。
std::vector や std::list の方法があるとは今まで知らなかったです。
ただ、もうリストの処理自体は出来上がっているのですが、こちらも参考にさせていただきます。
softya(ソフト屋)さん
>>つまり、ゲーム設定上でアイテムの持つ特殊効果もあわせて考えないとアイテム情報は決められないってことですね。
特殊なものも含めるとなると相当増えそうですね・・・。
>>それとアイテム所持は別のリストになりますね。なのでアイテム所持数は撤回します。失礼しました。
これは単にアイテム情報のリストって考えてよいでしょうか? そうであれば、リストでは無く配列のほうが扱いやすいと思います。
いえ、所持におけるリストを作っています。
アイテム入手関数を呼び出す毎に、リストに要素を追加していく処理を作っています。
別のリストになる、ということは、複数リストを作る必要がある、ということなのでしょうか?
何分ペーペーなもので、初歩的な質問でしたらすみません。。。
Re: 構造体ポインタの共有
Posted: 2012年9月12日(水) 15:00
by カフェ・ブルー
それと、前々回の自分の文章が見づらかったこと、失礼しました。
sotfya(ソフト屋)さん
修正していただきありがとうございました。
Re: 構造体ポインタの共有
Posted: 2012年9月12日(水) 15:16
by softya(ソフト屋)
カフェ・ブルー さんが書きました:
softya(ソフト屋)さん
>>つまり、ゲーム設定上でアイテムの持つ特殊効果もあわせて考えないとアイテム情報は決められないってことですね。
特殊なものも含めるとなると相当増えそうですね・・・。
>>それとアイテム所持は別のリストになりますね。なのでアイテム所持数は撤回します。失礼しました。
これは単にアイテム情報のリストって考えてよいでしょうか? そうであれば、リストでは無く配列のほうが扱いやすいと思います。
いえ、所持におけるリストを作っています。
アイテム入手関数を呼び出す毎に、リストに要素を追加していく処理を作っています。
別のリストになる、ということは、複数リストを作る必要がある、ということなのでしょうか?
何分ペーペーなもので、初歩的な質問でしたらすみません。。。
所持アイテムは、所持数やソートを前提とした情報の持ち方をする必要がありますよね。あと所持者情報も必要でしょう。
その他に使用回数とかダメージポイントとか使用することで変動する情報も必要となるでしょう。 ※ゲームデザインで変わります。
これら所持アイテムの情報はセーブされますよね?
となると問題がありましてゲーム作成途中のバランス調整でアイテムのパラメータを調整したいとしましょう。
セーブされているとなるとセーブデータも変更しますか? 面倒ですよね。
と言うことでバランス調整の対象となる情報はセーブしないで別のテーブル(配列)に持っていたほうが便利なんです。
セーブされる所持アイテム情報は可変要素のみで構成されるべきなんですね。
例えば所持アイテム情報とアイテム情報はアイテムのテーブル番号で結びつけることが可能です。
Re: 構造体ポインタの共有
Posted: 2012年9月12日(水) 16:43
by beatle
softyaさんのいう、所持リストとアイテム情報テーブルを分けようというのはこういうイメージだと思います
アイテム情報テーブル
...
アイテム番号120: 剣
属性値a: xxx, 属性値b: yyy, ...
アイテム番号121: 薬草
属性値a: zzz, 属性値b: vvv, ...
...
所持リスト
所持アイテム0: 120
個数: X
所持アイテム1: 121
残耐久力: Y
...
所持リストはアイテム情報テーブルの添字(120, 121)と、アイテム情報テーブルには載っていない属性値だけを記録します。
以上はsoftyaさんの補足。次から僕の意見です。
アイテムの種類(剣、薬草)によって属性値が大幅に異なり、それらをいちいち構造体のメンバーにするとメンバーが増えすぎて大変です。
そこで、std::mapを用いるのは如何でしょうか。
std::map は連想配列とか辞書とか呼ばれるもので、配列の添字が整数にかぎらず何でもOKなのが特徴です。
これを使ってAtkItemを定義し直すとこうなります。(ところで、gazopってなんでしょうか)
コード:
struct AtkItem {
std::string name;
std::string detail;
int *gazop;
std::map<std::string, int> attr;
};
attrというのが std::map のインスタンスです。型が std::map<std::string, int> ですから、添字が文字列で値がintですね。
こうやって使います。
コード:
attr["power"] = 10;
int val = attr["power"];
std::mapは、指定された添字がまだ存在しないなら自動で新しい値を追加してくれますので、何も考えず attr["power"] = 10; と書けば attr の中に「power = 10」という情報が記録されます。
こうすれば、新しい属性を追加したくなったときにAtkItemの定義を修正せずに属性を追加できます。
コード:
attr["sabi"] = 0; // サビ具合を表す属性を追加
std::map を使う案、いかがでしょうか。
Re: 構造体ポインタの共有
Posted: 2012年9月13日(木) 00:12
by カフェ・ブルー
なるほど、お二人のお陰でなんとなくつかめてきました。
つまりいつでも変更したい値はセーブデータにそのまま保存しないで、
あくまで参照先を保存しておくことによって、セーブデータを変更せずに済むというわけですね。
beatleさん、
丁重に教えていただきありがとうございます。
全体的に自分の処理を見直して、std::mapを取り入れた記述を目指してみます。
(gazopのことはすみません、忘れてください;;)
なんども質問で返してしまい失礼しました。
自分はどうやら処理方法以前に、全体的な設計図が頭に思い浮かんでなかったようです。
とても参考になりました。回答してくださった方々、本当にありがとうござました。