如何将信息从外部源提取到游戏中

时间:2011-12-23 04:12:55

标签: c++ csv

我正试图找到一种方法将统计数据导入到正在进行的游戏中通过电子表格?这是我正在使用的内容:

现在就是例如..法术,为了命名它们,设置统计数据,并且能够通过数字I调用它们在实际代码中有这样的事情:

    void spell(int & eMoney, int eSpell[10])
{
    using namespace std;
    char spellname[10][25] = {"Minor Heal", "Fire Shard", "Lightening Shard", "Ice Shard", "Magic Barrier", "Essence Of Life", 
"Earth Shard", "Wind Shard", "Insigma", "Weaken"};
    int spellcost[10] = {50, 80, 80, 80, 100, 100, 80, 80, 120, 80};

这一切都很好,花花公子,它有效...但现在和以后都是一个问题..我希望能够使用电子表格,如CSV文件,所以我可以像咒语,只是剑,只是俱乐部......我打算选择一个非常大的选项,能够在列和行中编辑单个文件并让实际游戏在需要时从外部文件中提取信息更为理想。 ..但我无法弄清楚如何解决这个问题?我对任何想法持开放态度。

以下是我现在如何调用咒语信息的示例:

case 2:
            do
            {
                cout << "Which spell would you like to cast?\n\n";
                for(x=0;x<10;x++)
                    cout << x+1 << ". " << spellname[x] << ": " << eSpell[x] << " left" << endl;
                cout << "11. Leave\n\n>> ";
                cin >> decision;
                system("cls");
            }
            while((decision<1)&&(decision>11)||(eSpell[decision-1]==0));
            switch(decision)

这是我基本上想到的电子表格的一个例子吗?从A1开始:

Type        sName   mDmg    sPrice
Spell   1   Minor Heal  10  100
Spell   2   Fire Shard  12  100
Spell   3   Lightening Shard    12  200
Spell   4   Ice Shard   12  150
Spell   5   Magic Barrier   10  130
Spell   6   Essence Of Life 15  10
Spell   7   Earth Shard 12  120
Spell   8   Wind Shard  12  230
Spell   9   Insigma 12  90
Spell   10  Weaken  12  100

另一个例子:

当前代码:

char monsters[16][25] = {"Wolf", "Bear", "Bandit", "Traveler", "Gargoyle", "Knight", "Warlock", "Mammoth", "Cyclops", "Unicorn", "Dragon", "Your Mother", "Demon", "Jesus", "Satan", "God"};
    //monster strengths
    int monsterdamagemax[16] = {32, 42, 53, 53, 65, 65, 75, 75, 85, 85, 90, 90, 95, 95, 110, 110};
    int monsterdamagemin[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    int monsterdefensemax[16] = {2, 7, 13, 13, 20, 20, 25, 25, 35, 35, 40, 40, 45, 45, 55, 55};
    int monsterdefensemin[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    int monsterhealth[16] = {32, 52, 73, 73, 95, 95, 118, 118, 142, 142, 167, 167, 193, 193, 220, 220};
    int monsterspeed[16] = {7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15};
    int monstergold[16] = {20, 30, 41, 41, 53, 53, 66, 66, 80, 80, 95, 95, 110, 110, 125, 125};

理想情况下,我希望能够从以下CSV文件中获取所有内容:

mID mName   mDmgMax mDmgMin mDefMax mDefMin mHp mSpeed  mGold
1   Wolf    32  0   2   0   32  7   20
2   Bear    42  0   7   0   52  8   30
3   Bandit  53  0   13  0   73  9   41
4   Traveler    53  0   13  0   73  9   41
5   Gargoyle    65  0   20  0   95  10  53
6   Knight  65  0   20  0   95  10  53
7   Warlock 75  0   25  0   118 11  66
8   Mammoth 75  0   25  0   118 11  66
9   Cyclops 85  0   35  0   142 12  80
10  Unicorn 85  0   35  0   142 12  80
11  Dragon  90  0   40  0   167 13  95
12  Your Mother 90  0   40  0   167 13  95
13  Demon   95  0   45  0   193 14  110
14  Jesus   95  0   45  0   193 14  110
15  Statan  110 0   55  0   220 15  125
16  God 110 0   55  0   220 15  125

4 个答案:

答案 0 :(得分:1)

如何编写一个基于命令的小应用程序为您创建记录,在您的“主要”程序即游戏中,您只需阅读这些记录。

样本结构 -

struct monster
{
  int mID;
  char mName[25]; //from your code
  int mDmgMax;
  //and these as well mDmgMin mDefMax mDefMin mHp mSpeed  mGold
};

在这个“帮助程序”程序中逐个读取记录中的每个数据项(如mName),并插入此结构中。将结构写入monsters.dat文件

std::ofstream fout;
fout.open("monsters.dat", std::ios::app | std::ios::binary);    
fout.write( (char*) &monsterInstance, sizeof(monsterInstance) );
fout.close();

这只会附加记录。 (我跳过了错误检查和读取数据。) 为了更加轻松,这个程序应该能够显示当前的怪物,添加怪物,删除怪物(通过输入mID)。

在主程序中阅读这些记录应该是一件容易的事。

答案 1 :(得分:0)

如果要保留大量基于表格的数据,可以考虑使用SQLite。它有一些有趣的成本和好处。

在不利方面(也许),它是SQL。它可能会更复杂,取决于您的搜索算法,可能会更慢。它也不能手工编辑,你需要一些东西来打开数据库(有免费的工具可用)。

从好的方面来说,你获得了数据库的所有排序和过滤能力(你需要的任何东西,比如spell='fireball' AND damage < 5),而SQLite是 fast (很容易存储)游戏数据,并且很可能比你自己的代码更快)。您可以将所有数据存储在一个文件中以便于部署或修改,每种类型都有唯一的表(武器,法术,字符等),并且不涉及任何服务器(SQLite是单个DLL)。

关系数据库擅长处理一致形成的数据表,这正是您在游戏环境中所拥有的(每个对象类型都有一些字段,没有太多变化,可能是一些空白,具有各种数据类型)。 SQLite尽管是最小的数据库,但可以在极好的时间内处理数千行,因此您不必担心您的游戏数据变得笨拙(纯文本表文件会很快发生,例如NWN(2)的2DA格式)。

它有一个学习曲线,但你将来会获得一些简单性(添加一个新的对象类型是一个新表和查询,而不是一大堆代码)和一个非常稳定的数据格式和加载/保存图书馆。根据您的需要,可能值得一试。

答案 2 :(得分:0)

正如问题评论中所指出的,如果你 想要处理CSV文件,你应该去<fstream>。使用这种方法,getline应该足以满足您的需求。

This threadC++.com中的

this question应该为您指明如何处理CSV。

答案 3 :(得分:0)

我使用Boost来解析我使用的CSV文件。这是一个简单的例子。

我同意peachykeen,但SQLite可能更适合你,但也许这会帮助你开始。

#include <iostream>
#include <fstream>
#include <vector>

#include <boost/tokenizer.hpp>
#include <boost/token_functions.hpp>

typedef std::vector<std::string> csvLine;
typedef std::vector<csvLine> csvLines;
typedef boost::tokenizer<boost::escaped_list_separator<char> > csvTokenizer;

csvLines ReadCSVFile(const std::string& fileName)
{
    csvLines retVec;
    std::ifstream inFile(fileName.c_str());
    if(inFile)
    {
        std::string fileLine;
        while(std::getline(inFile, fileLine))
        {
            csvTokenizer lineTokens(fileLine);
            retVec.push_back(csvLine(lineTokens.begin(), lineTokens.end()));
        }
        inFile.close();
    }
    return retVec;
}

int main(int argc, char** argv) 
{
    csvLines lines(ReadCSVFile(argv[1]));
    for(csvLines::iterator lineIt = lines.begin(); lineIt != lines.end(); ++lineIt)
    {
        for(csvLine::iterator tokenIt = (*lineIt).begin(); tokenIt != (*lineIt).end(); ++tokenIt)
        {
            std::cout << *tokenIt << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}