>>この記事には書き直した新しいページがあります。<<
<<前 [TOP] 次>>
Visual Studioで新規プロジェクトを作り、以下の2つのcppファイル、1つのヘッダーファイルを作成して下さい。
【Game_head.h】
/* header file : Game_head.h */ int yesno(); void current_point(); void enemy_create(); void hero_create(); int escape(); void calc_parameter(int suit, int strong); void hero_die(); void show_status(); void map_create(); void get_drug(int exist, int strong); int pos_compare(int a_x, int a_y, int b_x, int b_y); void walk_arround(char move); void use_drug(); void get_enemyitem(); void fight(); void command(); #ifdef MAIN /* enemy */ int enemy_x; int enemy_y; int enemy_life; int enemy_offence; int enemy_defence; int enemy_item_suit; int enemy_item_strong; /* map */ int map_wide_x; int map_wide_y; int map_ent_x; int map_ent_y; int map_floor = 0; int map_item_exist; int map_item_strong; int map_item_x; int map_item_y; /* hero */ int hero_point; int hero_x; int hero_y; int hero_life; int hero_life_upper; int hero_offence; int hero_defence; int hero_drug; int hero_sword; int hero_buckler; int hero_armer; #else /* enemy */ extern int enemy_x; extern int enemy_y; extern int enemy_life; extern int enemy_offence; extern int enemy_defence; extern int enemy_item_suit; extern int enemy_item_strong; /* map */ extern int map_wide_x; extern int map_wide_y; extern int map_ent_x; extern int map_ent_y; extern int map_item_exist; extern int map_item_strong; extern int map_item_x; extern int map_item_y; extern int map_floor; /* hero */ extern int hero_point; extern int hero_x; extern int hero_y; extern int hero_life; extern int hero_life_upper; extern int hero_offence; extern int hero_defence; extern int hero_drug; extern int hero_sword; extern int hero_buckler; extern int hero_armer; #endif
【Game_main.cpp】
#include <iostream> #include <stdlib.h> #define MAIN #include "Game_head.h" void main() { int input; hero_create(); map_create(); current_point(); std::cout << "Input senario Number => "; std::cin >> input; std::cin.clear(); std::cin.ignore(); srand(input); while(true) { if(enemy_life <= 0) { enemy_create( ); } std::cout << "現在位置 (" << hero_x << "," << hero_y << "):地下 " << map_floor << "階" << std::endl << std::endl; command(); if( pos_compare(map_item_x,map_item_y,hero_x,hero_y)){ get_drug(map_item_exist, map_item_strong); map_item_exist=0; } if( pos_compare(map_ent_x,map_ent_y, hero_x,hero_y)) { std::cout << "階段があった。下に降りますか? "; switch(yesno()) { case 1: map_create(); enemy_create(); current_point(); std::cout << std::endl << std::endl << "地下 " << map_floor << "階に降りた。" << std::endl << std::endl; break; } } if (pos_compare(hero_x,hero_y, enemy_x,enemy_y)) { int point=hero_point; fight(); if(point < hero_point) { enemy_create(); } } } } void show_status( ) { std::cout << std::endl << "現在の状況:" << std::endl; std::cout << "体力: " << hero_life << "/" << hero_life_upper << "\t攻撃力:" << hero_offence << "\t守備力:" << hero_defence << std::endl; std::cout << "\t経験値:" << hero_point << std::endl; std::cout << std::endl; std::cout << "持ち物のレベル" << std::endl; std::cout << "剣:" << hero_sword << "\t盾:" << hero_buckler << "\t鎧:" << hero_armer << std::endl << std::endl; std::cout << "薬の回復力:" << hero_drug << std::endl << std::endl << std::endl; return; } void hero_die( ) { std::cout << "Hero is died at floor " << map_floor << "." << std::endl; std::cout << std::endl; std::cout << "status" << std::endl; std::cout << "hero level " << hero_point/10 << std::endl; std::cout << std::endl; std::cout << "Game Over" << std::endl; exit(0); } void calc_parameter( int suit, int strong ) { switch(suit) { case 1: hero_offence = hero_offence - hero_sword + strong; hero_sword = strong; break; case 2: hero_defence = hero_defence - hero_buckler + strong; hero_buckler = strong; break; case 3: hero_defence = hero_defence - hero_armer + strong; hero_armer = strong; break; } return; } void use_drug( ) { if(hero_drug > 0) { hero_life += hero_drug; if(hero_life_upper < hero_life) { hero_life = hero_life_upper; } hero_drug=0; std::cout << std::endl << "\t薬を使った。\b" << std::endl << std::endl; show_status(); } else { std::cout << std::endl << "\t薬は今持ってない。" << std::endl << std::endl; } } void get_enemyitem( ) { if ( enemy_item_suit!=0 ) { show_status(); std::cout << "\t敵はアイテムを持っていた。" << std::endl; switch(enemy_item_suit) { case 1: std::cout << "剣:level " <<enemy_item_strong << std::endl; break; case 2: std::cout << "盾:level " <<enemy_item_strong << std::endl; break; case 3: std::cout << "鎧:level " << enemy_item_strong << std::endl; break; } std::cout << "装備するか?"; if(yesno()) { std::cout << "\tヒーローの状態が変わった。\b" << std::endl<< std::endl; calc_parameter(enemy_item_suit, enemy_item_strong); show_status(); } else { std::cout << "\tアイテムを捨てた!" << std::endl << std::endl; } } else { std::cout << "\t敵はアイテムを持っていなかった。" << std::endl << std::endl; } return; } int escape() { int x, y; x = rand()%10; y = rand()%10; if( x < y ) { return !0; } else { return 0; } } void fight() { int dum; while(true) { show_status( ); std::cout <<"敵と戦いますか?"; if ( yesno()==0 && escape() == 1){ std::cout << "\t敵から逃げました。" << std::endl << std::endl; break; } else { std::cout << "\t敵と戦います。" << std::endl << std::endl; } std::cout << "Heroの攻撃:"; dum = (hero_offence*(rand()%10)) / (enemy_defence+1); enemy_life -= dum; std::cout << "敵に " << dum << "のダメージ" << std::endl << std::endl; if(enemy_life -= dum){ std::cout << "\t敵を倒した!\b" << std::endl << std::endl; hero_point ++; hero_life_upper+=10; std::cout << "\tレベルが上がった。\b" << std::endl << std::endl; get_enemyitem( ); break; } std::cout << "敵の攻撃:"; dum = (enemy_offence*(rand()%10)) / (hero_defence+1); hero_life -= dum; std::cout << dum << "のダメージを受けた!" << std::endl << std::endl; if (hero_life <=0) { hero_die(); } } return; } void command() { char input; std::cout << "Command mode" << std::endl; std::cout << " up: k" << std::endl; std::cout << "left:h status:s right:l" << std::endl; std::cout << " down: j" << std::endl << std::endl; std::cout << "use drug:d Quit:q" << std::endl; for(;;) { std::cout << std::endl << "comand input => "; std::cin.clear(); std::cin.ignore(); std::cin >> input; if(!std::cin) { std::cout << "Error:"; } else { if (input=='d') { use_drug(); break; } else if (input == 's' ) { show_status(); break; } else if (input=='j' || input=='k' || input=='l' || input=='h') { walk_arround(input); break; } else if(input=='q') { exit(0); } } } return; } /* move lower j: left l: right h: upper k */ void walk_arround( char move ) { if(move=='l') { if( hero_x == map_wide_x) { std::cout << "その方向には歩けません!" << std::endl; return; } hero_x++; } else if(move=='k') { if(hero_y == map_wide_y) { std::cout << "その方向には歩けません!" << std::endl; return; } hero_y++; } else if (move=='h'){ if(hero_x == 0) { std::cout << "その方向には歩けません!" << std::endl; return; } hero_x--; } else if (move=='j') { if(hero_y == 0) { std::cout << "その方向には歩けません!" << std::endl; return; } hero_y--; } return; } int pos_compare(int a_x, int a_y, int b_x, int b_y) { if ( a_x == b_x && a_y == b_y ) { return !0; } else { return 0; } } void get_drug(int exist, int strong) { if(exist == 1) { std::cout << std::endl; std::cout << "\t薬(" << strong << ")を拾った!\b" << std::endl << std::endl; hero_drug+=strong; } return; } void current_point() { hero_x = rand()%map_wide_x; hero_y = rand()%map_wide_y; return; } int yesno() { char input; while(true){ std::cout << "yes or no (y/n) => "; std::cin.clear(); std::cin.ignore(); std::cin >> input; if(!std::cin) { std::cout << "Error:" << std::endl << std::endl; } else { switch(input) { case 'y': case 'Y': return !0; break; case 'n': case 'N': return 0; break; } } } }
【Game_create.cpp】
/* file : Game_create.cpp */ #include <iostream> #include <stdlib.h> #include "Game_head.h" void map_create( ) { map_floor++; map_wide_x = rand()%( 2 + map_floor) + 10; map_wide_y = rand()%( 2 + map_floor) + 10; map_ent_x = rand()%map_wide_x; map_ent_y = rand()%map_wide_y; map_item_exist=1; map_item_strong= rand()%( 10+10*map_floor) + 30; map_item_x=rand()%map_wide_x; map_item_y=rand()%map_wide_y; return; } void hero_create() { hero_point = 0; hero_life_upper = 100 + rand()%10; hero_life = hero_life_upper; hero_x = 0; hero_y = 0; hero_offence = rand()%5 + 5; hero_defence = rand()%5 + 5; hero_drug = 0; hero_sword = rand()%3 +1; hero_buckler=rand()%3; hero_armer = rand()%2 +1; return; } void enemy_create() { int i; enemy_x = rand() % map_wide_x; enemy_y = rand() % map_wide_y; enemy_life = rand() % 100 + map_floor*50; enemy_offence=rand() % 10 + map_floor; enemy_defence=rand() % (map_floor+2); if ( rand() % 2 == 1 ) { i=rand()%3+1; enemy_item_suit=i; if(i==1) { enemy_item_strong = rand()%(10 + map_floor); } else if ( i==2) { enemy_item_strong = rand() % (5 + map_floor); } else { enemy_item_strong = rand() % (7 + map_floor); } } else { enemy_item_suit = 0; enemy_item_strong = 0; } return; }
前に作成したダンジョンゲームを、create()関数と、そのほかの関数、ヘッダファイルに分割しました。
外部変数は関数の外側で宣言した変数です。
外部変数はその性質上、プログラムの起動時に生成され、プログラムの終了まで消滅することはありません。
有効範囲は、すべてのモジュールにわたり、extern宣言を行うことで、他のモジュールから外部変数を参照することが可能になります。
他のモジュールで、外部変数として確保された変数は、以下のようにして別のモジュールから参照可能になります。
extern 変数の型 変数名;
extern宣言は、「どこか別の場所でその変数が定義されているものを使う」という宣言ですので、別の場所でexternなしの変数を作成する必要があります。
C言語では、プリプロセッサという機能が用意されています。
プリプロセッサとは、簡単に言うと前処理のことであり、前に出てきた#include機能もその一つです。
#define 記号定数名 値
このように宣言します。
ここで、文の終わりに ; は必要ありません。
この宣言は、コンパイルされる前にプリプロセッサによって処理され、実際にコンパイルされるときにはコンパイラーから見れば存在しない文となります。
この宣言は、標準ヘッダーでも使われています。
例えば、
#define EOF (-1)
と宣言しておけば、プログラムの中で EOF と書くと -1 となります。
define文には、もう一つ別の機能があります。
それがこのマクロ機能です。
マクロ機能は次のようにして使います。
#define マクロ名(引数) 引数を含む文字列
例えば、
#define sq (x) ((x)*(x))
のように宣言すれば、関数と同じようにsq(x)を使うことができます。
引数の型の宣言は必要ありません。
プログラム上でsq(3)とすれば、計算値 9を返してくれます。
プリプロセッサにおける条件文として、「#ifdef文」があります。
これは、以下のように使います。
#define DEBUG ・・・・・ #ifdef DEBUG std::cout << "Debug: hensuu = " << hensuu << std::endl; #endif
つまり、DEBUGというマクロが定義されていたならば、#ifdefと#endifの間の行が有効になります。
もし、最初の行に #define DEBUG がなければ、この#ifdefと#endifの間の行はないものとしてプリプロセッサに処理されます。
この#ifdef文を使って外部変数をうまく使うことができます。
#ifdef THIS_MODULE int common; /* このモジュールで使います */ #else extern int common; /* 他のモジュールから見ます */ #endif
common変数を主に使いたいモジュールの先頭で、#define THIS_MODULEを定義して、このファイルをインクルードしておけば良いわけです。
もし、#define THIS_MODULEの定義がなければ、#elseの後の記述が読み込まれます。
では、サンプルプログラムの説明を少しします。
メイン関数のあるGame_main.cppの最初には define MAIN の記述がありますので、ヘッダファイルの#ifdefから#elseの手前までが処理されます。
create()関数のあるGame_create.cppには define MAIN の記述がありませんので、#elseから#endifまでの記述が処理されます。
Game_create.cppでは、externが用いられますので、Game_main.cppで使われた変数を参照する形になっています。
後の記述は前と同じです。実行結果も前と同じです。
<<前 [TOP] 次>>