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

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
誤字ラ

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

#1

投稿記事 by 誤字ラ » 9ヶ月前

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

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

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

アバター
Dixq (管理人)
管理人
記事: 1609
登録日時: 7年前
住所: 北海道札幌市
連絡を取る:

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

#2

投稿記事 by Dixq (管理人) » 9ヶ月前

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

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

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

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

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

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

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

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

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

もし特定のパラメータだけ同じ物を指定したいのであればEnemyParamとでも名前を付けたパラメータクラスを定義し、それをセットすればよいでしょう。
イメージ的にはこんな感じです

コード:

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

アバター
Dixq (管理人)
管理人
記事: 1609
登録日時: 7年前
住所: 北海道札幌市
連絡を取る:

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

#3

投稿記事 by Dixq (管理人) » 9ヶ月前

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

誤字ラ

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

#4

投稿記事 by 誤字ラ » 9ヶ月前

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

慣れている方にはもうわからないのかもしれないし、私だけなのかもしれませんが、コンストラクタに引数を持たせるこのような書き方だと、ここだけで完結(ほかで定義しない)ので非常にわかりや憂く感じます。

コード:

#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というワードについてあまりピンと来ていないようですが、もしかしてあまり乱用しないほうが良かったりなどありますか?
便利だと思って使うことがしばしばあります。

誤字ラ

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

#5

投稿記事 by 誤字ラ » 9ヶ月前

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

慣れている方にはもうわからないのかもしれないし、私だけなのかもしれませんが、コンストラクタに引数を持たせない書き方だと、ここだけで完結する(ほかで定義しない)ので非常にわかりやすく感じます。

コード:

#pragma once
 
#include<string>
 
class Enemy {
public:
    std::string name;
    int hp;
    int atk;
 
    Enemy() {
        name = "案山子";
        hp = 20;
        atk = 10;
    }
};

コード:

#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というワードについてあまりピンと来ていないようですが、もしかしてあまり乱用しないほうが良かったりなどありますか?
便利だと思って使うことがしばしばあります。

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

たいちう
記事: 415
登録日時: 7年前

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

#6

投稿記事 by たいちう » 9ヶ月前

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

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になってしまいます。
ここまでは既にご承知でしょう。


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

アバター
Dixq (管理人)
管理人
記事: 1609
登録日時: 7年前
住所: 北海道札幌市
連絡を取る:

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

#7

投稿記事 by Dixq (管理人) » 9ヶ月前

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

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

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

コード:

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キーワードを利用します。

アバター
usao
記事: 1374
登録日時: 5年前

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

#8

投稿記事 by usao » 9ヶ月前

誤字ラ さんが書きました:

コード:

#pragma once
 
#include<string>
 
class Enemy {
public:
    std::string name;
    int hp;
    int atk;
 
    Enemy() {
        name = "案山子";
        hp = 20;
        atk = 10;
    }
};
メンバがわざわざpublicなのだから,変更手段は自明なわけで…
好きなタイミングで好きな値にすればよいだけでは?

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

誤字ラ

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

#9

投稿記事 by 誤字ラ » 9ヶ月前

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

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

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

返信

“C言語何でも質問掲示板” へ戻る