忍者ブログ
なんとなくだらだらと。方向性はまだ決まってない。 当方のプログラムでは、山田巧さん作成のDXライブラリを利用させていただいてます。 本サイト http://homepage2.nifty.com/natupaji/DxLib/index.html DX Library Copyright (C) 2001-2008 Takumi Yamada.
[29] [28] [27] [26] [25] [24] [23] [22] [21] [20] [19]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

前回の修正がかなりの「やっつけ仕事」だったんで、そのへんの整理とか。
この手の修正は、軽い気持ちでそこらじゅう手をつけるから、ブログに書くのが大変。

CRPG017.png


ダウンロード  Entry017.zip (2009.08.01)




まずは、前回いじった Traning系のメソッドをまとめてみる。

Unit.h


class Unit
{



    void Stay(int price);               // 宿に泊まる
    void AddMoney(int gd);              // 金額加算
    int GetMoney(){return(Money);}
    void ShowMoney();
    //void TraningHP();                   // 体力強化
    //void TraningAtp();                  // 攻撃訓練
    //void TraningDfp();                  // 防御訓練
    void Traning(TraningMenu tM);       // 強化訓練(3種)
    int  TraningCost(TraningMenu tM);   // 強化コスト


};

// 初期化
void Unit::Init(string Name, int HP, int Atp, int Dfp, int Money)
{
//  cout << "Init:"<< Name << "\n";
    this->Name = Name;
    this->MaxHP = this->HP = HP;


さっき作ったTraning○○ 系は全部カットして、Traning(強化ナンバー) で作ってみることに。
TraningCost() を最初から分けてるのは、街での行動一覧表示のときにも、コスト表示
しておきたいと思ったから。
ついでに、全く関係ないところだけど、「初期化出来たよ!」表示を消しておく。
そろそろうっとおしい。


Unit.h

#pragma once

enum TraningMenu
{
    THP,            // 体力強化
    TAtk,           // 攻撃力強化
    TDef            // 防御力強化
};
const char *tMenu[] = {
    "体力",
    "攻撃力",
    "防御力"
};

class Unit
{
    string Name;    // 名前




void Unit::Traning(TraningMenu tM)
{
    int cost = TraningCost(tM);
    int imp = 0;
    if(Money >= cost){
        Money -= cost;
        switch(tM){
            case THP:
                imp = MaxHP/12 + 1;
                MaxHP += imp;
                break;
            case TAtk:
                imp = 1;
                Atp ++;
                break;
            case TDef:
                imp = 1;
                Dfp++;
                break;
        }
        cout << tMenu[tM] << "が " << imp << "上がった。\n";
    } else {
        cout << "お金がたりませんよ!\n";
    }
}

int Unit::TraningCost(TraningMenu tM)
{
    int cost = 0;
    switch(tM){
        case THP:
            cost = (MaxHP/10)*5;
            break;
        case TAtk:
            cost = Atp*5;
            break;
        case TDef:
            cost = Dfp*5;
            break;
    }
    return cost;
}


トレーニングメニューで使いそうな一覧を enum で宣言しておく。
対応する名前も、一応用意しておく。使うかわからないけど、うまく使えたらスッキリ。

トレーニング内容は、switch~caseで内容を分岐させる。
パラメーターを配列で用意してたら、それはそれでうまいこと書けそうなものだけど、
過剰なソース圧縮は読みにくくなるだけだからな。
それに、そのレベルでのパラメーター管理は最初から想定してないと、今さらだと
ソースの変更が全プログラムに及ぶ。

この、「ソースの変更が全プログラムに及ぶ」ってのはオブジェクト指向的には落第点。
危険な兆候。こうならないように設計するのがOOPであり、世に溢れるOOP指南書。


話が脱線したかな。
前バージョンでは、「訓練しますか(Y/N)」を聞いてたんだけど、正直うっとおしい。
訓練一覧のところで値段表示を入れるつもりだし、いちいち聞かないことにした。

それでも、同じような switch~case がふたつ並ぶか、同じような処理を訓練別に3回書くか、
なんとなくイヤな予感してたんだけど、見た目うまくごまかせた。
実際は、TraningCost() 部分を外に追い出しただけなんだけど、この部分がTraning() の
中に入ってると想像してみると・・・、なんとなくイヤだろ?



さて、Unit クラスに追加するメソッドはこんなもんでいいかな?
実際にはデバグ済みだけど。

main のほうにのせてみる。
main.cpp


    cout << "\n\n街にいます。\n";

    while(1){
        cmd = 0;
        res = NONE;
        player.ShowStatus();
        player.ShowMoney();
        cout << "\n1:出撃\n"
             << "2:宿屋(" << stayPrice << "G)      体力 " << player.getShowHP() << "\n"
             << "3:体力強化(" << player.TraningCost(THP) <<"G)\n"
             << "4:攻撃訓練(" << player.TraningCost(TAtk) <<"G)\n"
             << "5:防御訓練(" << player.TraningCost(TDef) <<"G)\n"
             << "9:終了\n"
             << "どうする?";

        if(cmdcnt){
            cin.clear();
            cin.ignore();
        }
        cin >> cmd;
        cout << "\n";
        switch(cmd){
            case 1:     // 出撃
                res = DEPARTURE;
                break;
            case 2:     // 宿泊
                player.Stay(stayPrice);
                break;
            case 3:     // 体力強化
                player.Traning(THP);
                break;
            case 4:     // 攻撃訓練
                player.Traning(TAtk);
                break;
            case 5:     // 防御訓練
                player.Traning(TDef);
                break;

            case 9:
                res = ABORT;
                break;
        }
        if(res!=NONE) break;






パラメーター表示をループの中に入れて、入力があるたびに毎回表示することにする。
cout << の一覧表示がごっついことになった。
トレーニングメニューの金額を表示するようにして、各呼び出しを変更する。

宿屋も、泊まるのを忘れたりいろいろあるので、体力の現在値を表示することにした。
体力とかの数字は Unit クラスが隠し持ってるので、メソッドを追加して教えてもらわないと。

できるもんだなあ。
適当に作ってみたけど、stringstream なんて初めて使うわ。

Unit.h


class Unit
{



    int GetMoney(){return(Money);}
    void ShowMoney();
    //void TraningHP();                   // 体力強化
    //void TraningAtp();                  // 攻撃訓練
    //void TraningDfp();                  // 防御訓練
    void Traning(TraningMenu tM);       // 強化訓練(3種)
    int  TraningCost(TraningMenu tM);   // 強化コスト
    string getShowHP();

};



string Unit::getShowHP()
{
    stringstream sstr;
    sstr.str("");

    sstr << HP << "/" << MaxHP;

    return(sstr.str());
}



string型で、getShowHP() って作ってみた。
strimgstream型を使うと、cout と同じ感覚で文字列が作れる。
最初に、sstr.str("") で空の文字列を送って、sstr の中を空にしておく。
cout のように、 << をどんどん重ねて作りたい文字列を作る。
最後 sstr.str() でstring 型として返す。


#include <sstream>の宣言を忘れずに。


main.cpp


#include <iostream>
#include <string>
#include <sstream>
#include <stdlib.h>     // 乱数取得に必要
#include <time.h>       // rand()の初期化に必要
#include <windows.h>    // 表示のウェイトのためだけに。

using namespace std;





細かいところ。
宿に連続して泊まるのは意味が無いので、体力満タンだったら追い返す。


Unit.h


void Unit::Stay(int price)
{
    if(HP == MaxHP){
        cout << "体力満タンです。   " << getShowHP() << "\n"
             << "泊まる必要ありませんよ。\n";
    } else if(Money >= price){

        cout << Name << "は、宿に泊まった・・・\n体力が全快した。\n";
        HP = MaxHP;
        Money -= price;
    } else {
        cout << "お金がたりませんよ!\n";
    }
}





だいぶ遊びやすくなったと思うがどうか。
セーブロード完備したら、ちょっと低レベルのコミュニティに捨ててもいいぐらいの出来だと思う。



ダウンロード  Entry017.zip (2009.08.01)
PR


忍者ブログ [PR]
カレンダー
12 2025/01 02
S M T W T F S
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 31
フリーエリア
バーコード
ブログ内検索
P R
アクセス解析
カウンター