ポケモンの弱点のアレのコード

ひとまず完成.

#define Sint8 signed char
#define Uint8 unsigned char

#include <iostream>
#include <vector>
#include <stack>
//#include <set>

using namespace std;

enum
{
  ATTR_NORMAL,
  ATTR_FIRE,
  ATTR_WATER,
  ATTR_THUNDER,
  ATTR_GLASS,
  ATTR_ICE,
  ATTR_FIGHT,
  ATTR_POISON,
  ATTR_GROUND,
  ATTR_FLY,
  ATTR_PSY,
  ATTR_INSECT,
  ATTR_ROCK,
  ATTR_GHOST,
  ATTR_DRAGON,
  ATTR_EVIL,
  ATTR_STEEL,

  ATTR_NUM
};

static const char* ATTR_NAME[] = 
{//上のやつをマクロで処理
  "ATTR_NORMAL",
  "ATTR_FIRE",
  "ATTR_WATER",
  "ATTR_THUNDER",
  "ATTR_GLASS",
  "ATTR_ICE",
  "ATTR_FIGHT",
  "ATTR_POISON",
  "ATTR_GROUND",
  "ATTR_FLY",
  "ATTR_PSY",
  "ATTR_INSECT",
  "ATTR_ROCK",
  "ATTR_GHOST",
  "ATTR_DRAGON",
  "ATTR_EVIL",
  "ATTR_STEEL",
};

enum
{
	EFF_XXXX,//×
	EFF_DULL,//△
	EFF_GOOD,//
	EFF_COOL,//◎

	EFF_NUM
};

static const Sint8 ATTR_PAIR[ATTR_NUM][ATTR_NUM] =
{//マクロでやったほうが良かっただろ。。。常識的に考えて。。。
	//ATTR_NORMAL,
	{EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD,
	 EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_DULL, EFF_XXXX, EFF_GOOD, EFF_GOOD, EFF_DULL},
	//ATTR_FIRE,
	{EFF_GOOD, EFF_DULL, EFF_DULL, EFF_GOOD, EFF_COOL, EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_GOOD,
	 EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_DULL, EFF_GOOD, EFF_DULL, EFF_GOOD, EFF_COOL},
	//ATTR_WATER,
	{EFF_GOOD, EFF_COOL, EFF_DULL, EFF_GOOD, EFF_DULL, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_COOL,
	 EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_DULL, EFF_GOOD, EFF_GOOD},
	//ATTR_THUNDER,
	{EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_DULL, EFF_DULL, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_XXXX,
	 EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_DULL, EFF_GOOD, EFF_GOOD},
	//ATTR_GLASS,
	{EFF_GOOD, EFF_DULL, EFF_COOL, EFF_GOOD, EFF_DULL, EFF_GOOD, EFF_GOOD, EFF_DULL, EFF_COOL,
	 EFF_DULL, EFF_GOOD, EFF_DULL, EFF_COOL, EFF_GOOD, EFF_DULL, EFF_GOOD, EFF_DULL},
	//ATTR_ICE,
	{EFF_GOOD, EFF_DULL, EFF_DULL, EFF_GOOD, EFF_COOL, EFF_DULL, EFF_GOOD, EFF_GOOD, EFF_COOL,
	 EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_DULL},
	//ATTR_FIGHT,
	{EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_DULL, EFF_GOOD,
	 EFF_DULL, EFF_DULL, EFF_DULL, EFF_COOL, EFF_XXXX, EFF_GOOD, EFF_COOL, EFF_COOL},
	//ATTR_POISON,
	{EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_DULL, EFF_DULL,
	 EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_DULL, EFF_DULL, EFF_GOOD, EFF_GOOD, EFF_XXXX},
	//ATTR_GROUND,
	{EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_COOL, EFF_DULL, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_GOOD,
	 EFF_XXXX, EFF_GOOD, EFF_DULL, EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_COOL},
	//ATTR_FLY,
	{EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_DULL, EFF_COOL, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_GOOD,
	 EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_DULL, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_DULL},
	//ATTR_PSY,
	{EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_COOL, EFF_GOOD,
	 EFF_GOOD, EFF_DULL, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_XXXX, EFF_DULL},
	//ATTR_INSECT,
	{EFF_GOOD, EFF_DULL, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_DULL, EFF_DULL, EFF_GOOD,
	 EFF_DULL, EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_DULL, EFF_GOOD, EFF_COOL, EFF_DULL},
	//ATTR_ROCK,
	{EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_DULL, EFF_GOOD, EFF_DULL,
	 EFF_COOL, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_DULL},
	//ATTR_GHOST,
	{EFF_XXXX, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD,
	 EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_DULL, EFF_DULL},
	//ATTR_DRAGON,
	{EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD,
	 EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_DULL},
	//ATTR_EVIL,
	{EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_DULL, EFF_GOOD, EFF_GOOD,
	 EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_DULL, EFF_DULL},
	//ATTR_STEEL,
	{EFF_GOOD, EFF_DULL, EFF_DULL, EFF_DULL, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_GOOD,
	 EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_COOL, EFF_GOOD, EFF_GOOD, EFF_GOOD, EFF_DULL},
};

//階層のループ化をどうするか。再帰関数で上手くいくか?
//enum{LOOP_COUNT = 2};
/*
for(Uint8 l = 0; l < LOOP_COUNT; l++)
{
  for(Uint8 atk = 0; atk < ATTR_NUM; atk++)
  {
    Uint8 GoodCount_local = 0;
    for(Uint8 def = 0; def < ATTR_NUM; def++)
    {
      if(GoodAttr[def] >= 0) continue;

      if(AttrPair[atk][def] >= EFF_GOOD){
        ++GoodCount_local;
        GoodAttr[i] = 
      }
  }
}
//*/
/*
//1ループだととこうなる
for(Uint8 atk = 0; atk < ATTR_NUM; atk++)
{
  for(Uint8 def = 0; def < ATTR_NUM; def++)
  {//そういやSTL使っていいんじゃねえか。忘れてた
    if(AttrPair[atk][def] < EFF_GOOD) continue;

    ++GoodCount_local;
    GoodAttr_local.add(ATTR_NAME[def]);
  }

  if(GoodCount_local >== GoodCount){
    if(GoodCount_local > GoodCount){
      GoodCount = GoodCount_local;
      BestAttrName.clear();
      GoodAttr.clear();
    }
    BestAttrName.add(ATTR_NAME[atk]);
    GoodAttr.add(GoodAttr_local);
  }
}
//*/
/*
//2ループだととこうなる
for(Uint8 atk = 0; atk < ATTR_NUM; atk++)
{
  for(Uint8 def = 0; def < ATTR_NUM; def++)
  {//
    if(AttrPair[atk][def] < EFF_GOOD) continue;

    ++GoodCount_local;
    GoodAttr_local.add(ATTR_NAME[def]);
  }

  //再帰でいけそうな気がしてきた。
  for(Uint8 atk2 = 0; atk2 < ATTR_NUM; atk2++)
  {
    Vector<string> GoodAttr_local_local = GoodAttr_local;//stringは後で[index]すればよいから<Uint8>か?
    Uint8 GoodCount_local_local = GoodCount_local;

    for(Uint8 def = 0; def < ATTR_NUM; def++)
    {//
      if(AttrPair[atk2][def] < EFF_GOOD) continue;
      if(GoodAttr_local_local.exist(ATTR_NAME[def])) continue;

      ++GoodCount_local_local;
      GoodAttr_local_local.add(ATTR_NAME[def]);
    }

    if(GoodCount_local_local >== GoodCount){
      if(GoodCount_local_local > GoodCount){
        GoodCount = GoodCount_local_local;
        BestAttrName.clear();
        GoodAttr.clear();
      }
      BestAttrName.add(Pair(ATTR_NAME[atk], ATTR_NAME[atk2]));//ここの要素をリストで
      GoodAttr.add(GoodAttr_local_local);
    }
  }
}
//*/

//こうだな
//PokemonWeaknessChecker().Check(2);で行けるんだっけ?
class PokemonWeaknessChecker
{//弱点はweaknessで良いのか?
protected:
	//最も多くの種類の弱点をつける属性の組(COMBS)と、実際の弱点の種類(Attrs)
	vector<vector<Uint8> > m_Combs;
	vector<vector<Uint8> > m_Attrs;
	//再帰で受け渡すパラメータをメンバ化
	stack<vector<Uint8> > m_CombsStack;
	stack<vector<Uint8> > m_AttrsStack;

	Sint8 m_DepthMax;//まあ、一応sizeと比較するのでSintで
public:
	PokemonWeaknessChecker()
	{//STLって何か初期化しなきゃいけなかったっけ?
		m_DepthMax = 0;//一応初期化
        vector<Uint8> empty;
        m_CombsStack.push(empty);
        m_AttrsStack.push(empty);
	}

	void Check(Sint8 depth)
	{
		m_DepthMax = depth;//引数で渡すのが面倒なのでメンバで持つ

		Search();

		PrintResult();
	}

	void Search()
	{
		Uint8 NextAttack = 0;
		if(m_CombsStack.top().size() > 0) NextAttack = m_CombsStack.top()[m_CombsStack.top().size()-1] + 1;
		for(Uint8 atk = NextAttack; atk < ATTR_NUM; atk++)
		{
			//atkの組み合わせ。
			vector<Uint8> Comb = m_CombsStack.top();//copy
			Comb.push_back(atk);

			//上のatkの組み合わせにおいて有効なdefはどれかを表す
			vector<Uint8> Attr = m_AttrsStack.top();//copy

			for(Uint8 def = 0; def < ATTR_NUM; def++)
			{//
				if(ATTR_PAIR[atk][def] < EFF_COOL) continue;
//				if(Attr.exist(def)) continue;
                Sint8 d;
                for(d = 0; d < Attr.size(); d++)
                  if(Attr[d] == def) break;
                if(d < Attr.size()) continue;

                Attr.push_back(def);
			}

			if(m_CombsStack.size() >= m_DepthMax){
				//最下層まで来たので以前の結果と比べて、優れていれば追加
				if(m_Attrs.size() == 0 || m_Attrs[0].size() <= Attr.size()){
					if(m_Attrs.size() != 0 && m_Attrs[0].size() < Attr.size()){
						m_Combs.clear();
						m_Attrs.clear();
					}
					m_Combs.push_back(Comb);
					m_Attrs.push_back(Attr);
				}
			}else{
				//最下層まで再帰で行く
				m_CombsStack.push(Comb);
				m_AttrsStack.push(Attr);
				Search();
				m_CombsStack.pop();
				m_AttrsStack.pop();
			}
		}
	}

	void PrintResult()
	{
		for(Sint8 i = 0; i < m_Combs.size(); i++){
			cout << "COMBO " << (int)i << endl;

			cout << "atk:";
			for(Sint8 j = 0; j < m_Combs[i].size(); j++){
				cout << ATTR_NAME[m_Combs[i][j]];
				if(j < m_Combs[i].size()-1)
					cout << ", ";
			}
			cout << endl;

			cout << "def:";
			for(Sint8 j = 0; j < m_Attrs[i].size(); j++){
				cout << ATTR_NAME[m_Attrs[i][j]];
				if(j < m_Attrs[i].size()-1)
					cout << ", ";
			}
			cout << endl;

			cout << endl;
		}
	}
};

int main(int argc, char *argv[])
{
  PokemonWeaknessChecker().Check(4);
}

pre表記だと]が上手く表示できてなかった.
シンタックス・ハイライトだと上手くいくけど目が痛いなこりゃ.また後でいじってみる.
スーパーpre記法で良い様子


////////////////////


トップに置く理由もないのでこちらに移動.


弱点を網羅する属性の組み合わせを探すプログラム.
ちなみに結果は以下の通り.


4つの組み合わせ
・氷,闘,地,飛
・氷,闘,地,霊
・氷,闘,地,悪


3つの組み合わせ
・氷,闘,地


2つの組み合わせ
・氷,闘
・氷,地


1つのみ
・闘
・地


参考資料ぐらいにはなるか.実戦ではなくてCPU相手に限る感じだが.