合計 昨日 今日

C++ パラメータの異なった敵の複製

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: 誤字ラ
[URL]
Date: 2017年8月08日(火) 21:22
No: 1
(OFFLINE)

 C++ パラメータの異なった敵の複製

DXライブラリでゲームを制作中で、Enemyクラスの”敵”を量産しようとしたときに、敵のパラメータがすべて同じで、どうやったら楽に変えれるのだろうと思い質問させていただきました。

コンストラクターに引数を持たせて外で定義してあげたらいいし、さらにはshared_ptr<>を使えばわかりやすくなるくらいの知識はあります。ですが、コンストラクターに引数を持たせずにしばらくやってきたし、とても分かりやすいと感じてます。なのでこの方法で敵のパラメータを変える方法があるのならぜひ知りたいです。

また、そのような方法があったとした場合に、それを使うメリットとデメリットも教えていただけたら幸いです。

Name: Dixq (管理人)
(管理人)
[URL]
ウィザード(1,480,869 ポイント)
Date: 2017年8月09日(水) 01:13
No: 2
(OFFLINE)

 Re: C++ パラメータの異なった敵の複製

質問の内容が読んでてよく理解できないです。
読み直してから投稿されましたか?

> Enemyクラスの”敵”を量産しようとしたときに、敵のパラメータがすべて同じで、どうやったら楽に変えれるのだろうと思い

「どうやったら全て同じに出来るのだろう」ではなく「どうやったら楽に変えられるのだろう」という疑問なのですか?
それとも共通のパラメータを設定するようになっていて、一か所を変更したらその内容がすべてに適用されるようにしたいのでしょうか。

> コンストラクターに引数を持たせて外で定義してあげたらいいし、さらにはshared_ptr<>を使えばわかりやすくなるくらいの知識はあります

敵のパラメータとshared_ptrってどう関係あるのでしょうか?

> ですが、コンストラクターに引数を持たせずにしばらくやってきたし、とても分かりやすいと感じてます。なのでこの方法で敵のパラメータを変える方法があるのならぜひ知りたいです。

とても分かりやすいのは何がですか?要するにコンストラクタに引数を持たせないやり方を知りたいのでしょうか?

とりあえず私なりに解釈したのが
・敵のパラメータを同一にしたい
・簡単な変更で敵のパラメータを一括で変更したい
・コンストラクタの引数は利用したくない
・コンストラクタの引数で指定する場合とそうでない場合のメリットデメリットを知りたい

解決策の一つとして、まず敵クラスのオブジェクトが持つメンバ変数を全部同じにしたいのなら、コピーコンストラクタを定義して、オブジェクトをコピー可能にします。
https://goo.gl/RNsZEA

もし特定のパラメータだけ同じ物を指定したいのであればEnemyParamとでも名前を付けたパラメータクラスを定義し、それをセットすればよいでしょう。
イメージ的にはこんな感じです
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class EnemyParam {
public:
    int a;
    int b;
    int c;
};
 
class Enemy {
private:
    int a;
    int b;
    int c;
public:
    void setParam(const EnemyParam& prm){
        a = prm.a;
        b = prm.b;
        c = prm.c;
    }
};
 
int main(){
    Enemy enemy[100];
    EnemyParam prm;
    prm.a = 1;
    prm.b = 2;
    prm.c = 3;
    for(int i=0; i<100; i++){
        enemy[i].setParam(prm);
    }
}

この時、prmの値を変えてあげればセットするパラメータは全部変わります。
コンストラクタの引数を使うメリットデメリットを聞く前に、まず何故コンストラクタに引数を与えてはいけないのですか?

Name: Dixq (管理人)
(管理人)
[URL]
ウィザード(1,480,869 ポイント)
Date: 2017年8月09日(水) 01:22
No: 3
(OFFLINE)

 Re: C++ パラメータの異なった敵の複製

もしもっと賢くセットしたいなら、パラメータのセットにはデザインパターンBuilderパターンを利用したりメソッドチェーンを実装して設定する方法もあります。
メソッドチェーンはC#でよく使われる流行の方法で、C++でも似たような実装は可能です。
https://goo.gl/gPa83W
Builderパターンをメソッドチェーンで実装する方法はEffectiveJAVAに乗っていて、それをC++で実装する方法もあります。
https://goo.gl/tGaWjR

Name: 誤字ラ
[URL]
Date: 2017年8月09日(水) 02:09
No: 4
(OFFLINE)

 Re: C++ パラメータの異なった敵の複製

「異なった」パラメータを持つ敵の複製です。

慣れている方にはもうわからないのかもしれないし、私だけなのかもしれませんが、コンストラクタに引数を持たせるこのような書き方だと、ここだけで完結(ほかで定義しない)ので非常にわかりや憂く感じます。
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma once
 
#include<string>
 
class Enemy {
public:
    std::string name;
    int hp;
    int atk;
 
    Enemy() {
        name = "案山子";
        hp = 20;
        atk = 10;
    }
};


[code=Cpp]
#pragma once
class Enemy {
public:
std::string Name;
int Hp;
int Atk;

Enemy(std::string setname, int sethp, int setatk) {
Name = setname;
Hp = sethp;
Atk = setatk;
}

//↓Enemyクラスのcpp
#include"Enemy.h"
#include<iostream>

void Battle::EnemyStatus() {
std::shared_ptr<Enemy> Slime(new Enemy("スライム", 50, 10));

  std::cout << slime->name << "が現れた" << std::endl;
[/code]
と書いてもわかりやすいと言えばわかりやすいのですが、現状では前者の書き方の方が慣れているので、その書き方をしてもエネミー1体ずつ別のステータスを設定することは可能なのかなと思いました。

ステータスの設定にshared_ptrというワードについてあまりピンと来ていないようですが、もしかしてあまり乱用しないほうが良かったりなどありますか?
便利だと思って使うことがしばしばあります。

Name: 誤字ラ
[URL]
Date: 2017年8月09日(水) 02:15
No: 5
(OFFLINE)

 Re: C++ パラメータの異なった敵の複製

「異なった」パラメータを持つ敵の複製です。

慣れている方にはもうわからないのかもしれないし、私だけなのかもしれませんが、コンストラクタに引数を持たせない書き方だと、ここだけで完結する(ほかで定義しない)ので非常にわかりやすく感じます。
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma once
 
#include<string>
 
class Enemy {
public:
    std::string name;
    int hp;
    int atk;
 
    Enemy() {
        name = "案山子";
        hp = 20;
        atk = 10;
    }
};


コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#pragma once
class Enemy {
public:
std::string Name;
int Hp;
int Atk;
 
Enemy(std::string setname, int sethp, int setatk) {
Name = setname;
Hp = sethp;
Atk = setatk;
}
 
//↓Enemyクラスのcpp
#include"Enemy.h"
#include<iostream>
 
void Battle::EnemyStatus() {
std::shared_ptr<Enemy> Slime(new Enemy("スライム", 50, 10));
 
  std::cout << slime->name << "が現れた" << std::endl;

と書いてもわかりやすいと言えばわかりやすいのですが、現状では前者の書き方の方が慣れているので、その書き方をしてもエネミー1体ずつ別のステータスを設定することは可能なのかなと思いました。

ステータスの設定にshared_ptrというワードについてあまりピンと来ていないようですが、もしかしてあまり乱用しないほうが良かったりなどありますか?
便利だと思って使うことがしばしばあります。

プレビューする前に急いで送ってしまっていろいろと間違えて送ってしまったので再掲します。><

Name: たいちう
[URL]
ハッカー(140,756 ポイント)
Date: 2017年8月09日(水) 06:39
No: 6
(OFFLINE)

 Re: C++ パラメータの異なった敵の複製

呼び出し元から考えてみましょう。

std::shared_ptr<Enemy> Slime(new Enemy("スライム", 50, 10));
std::shared_ptr<Enemy> Drakee(new Enemy("ドラキー", 40, 15));

↑のようにすると別のステータスを設定できます。

std::shared_ptr<Enemy> Slime(new Enemy());
std::shared_ptr<Enemy> Drakee(new Enemy());

↑のようにすると同じステータスのEnemyになってしまいます。
ここまでは既にご承知でしょう。


誤字ラさんはどのように呼び出したいのですか?

Name: Dixq (管理人)
(管理人)
[URL]
ウィザード(1,480,869 ポイント)
Date: 2017年8月09日(水) 08:47
No: 7
(OFFLINE)

 Re: C++ パラメータの異なった敵の複製

たいちうさんの質問と並行してご回答頂けると幸いです。

コンストラクタで直に代入していたら、それは確かに変更が効きませんよね。
パラメータの定義を内部に持ちたいということであれば、このような実装はどうですか?

Enemyクラスの中にパラメータクラスを定義し、そのパラメータIDをセットするような実装です。

コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Enemy {
public:
    class Param {
    public:
        int a, b, c;
    };
    Enemy(int id) {
        _prm = _param[id];
    }
private:
    const static Param _param[10];
    Param _prm;
};
 
Enemy::Param _param[10] = {
    { 1,2,3 },
    { 2,2,3 },//←これがセットされる
    { 3,2,3 },
    { 4,2,3 },
    { 5,2,3 },
    { 6,2,3 },
    { 7,2,3 },
    { 8,2,3 },
    { 9,2,3 },
    { 0,2,3 },
};
 
int main() {
    Enemy enemy(1);
}


もし全てのパラメータをバラバラに設定したいのであれば、
Builderパターンを適用するか、それぞれのパラメータをセットするセッターを実装するしかないでしょう。

> ステータスの設定にshared_ptrというワードについてあまりピンと来ていないようですが

shared_ptrというのはメモリの解放を自動でやってくれるガベージコレクションのような機能であり、パラメータの設定とは話している次元が違うものです。
なお、shared_ptrにはnewではなくmake_sharedキーワードを利用します。

Name: usao
[URL]
ハッカー(133,707 ポイント)
Date: 2017年8月09日(水) 09:53
No: 8
(OFFLINE)

 Re: C++ パラメータの異なった敵の複製

誤字ラ さんが書きました:
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma once
 
#include<string>
 
class Enemy {
public:
    std::string name;
    int hp;
    int atk;
 
    Enemy() {
        name = "案山子";
        hp = 20;
        atk = 10;
    }
};



メンバがわざわざpublicなのだから,変更手段は自明なわけで…
好きなタイミングで好きな値にすればよいだけでは?

「このコードは例示しただけで,本当はpublicではないのです」ということなのだとしても
【setterを書く】で終わる話なのでは?
趣向を凝らした書き方ではありませんが,最も
> 楽に
実現できると思いますが.

Name: 誤字ラ
[URL]
Date: 2017年8月09日(水) 16:26
No: 9
(OFFLINE)

 Re: C++ パラメータの異なった敵の複製

[解決!]

色々な回答ありがとうございました!
異なったパラーメータというところがどうにも伝わりづらいようで申し訳ございませんでした。

結果的には変に一つにまとめようとするよりは、素直に引数で与えてあげた方が分かりやすい。ということがわかりました。

またshared_ptrのの認識も甘かったようなので、適当なタイミングで勉強しようと思います。


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[21人]