まよねーず工場

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

--/--/-- --:-- |スポンサー広告  

う~ん浮かびません!

最近は音楽を聴く時間がめっきり減ってしまったような気がします。
以前ほど楽曲分析をあまりしていなかったり「こういう曲を作ろう!」
というジャンルがあまり固定されないのか、浮かびませんねぇ^^;

そういうときはのんびり好きな曲を流しながら街を歩きたい今日この頃、
せんちゃです。


でもね聞いてくださいよ、ここ1,2週間は学校のグループ制作などがあったりしまして
それはもうヒャッホーな感じだったわけでありまして、
まぁ要するに頭を抱え込みながら苦悩していたりしたのですよ!


グループ制作のお題は「迷路探索」
1チーム1個迷路を作成します、そして解きます。


みんなのプログラムで迷路探索をして、少ない歩数でゴールしたチームが勝ちです。


プログラム的には先生が書いた最初に用意されているのはこんな感じ



#include "stdio.h"
#include "conio.h"
#include "windows.h"



インクルードファイルはお約束のアレです。



#if !defined __MAZE_H__
#define __MAZE_H__

こちらが二度読み防止の処理。



// キーボード情報
#define KeyEscape (0x1b) // エスケープキー

// マップ情報
#define MazeStart 'S' // スタート地点
#define MazeGoal 'G' // ゴール
#define MazeAisle ' ' // 通路

// 自分の進行方向
#define DirUp (0) // 上
#define DirDown (1) // 下
#define DirLeft (2) // 左
#define DirRight (3) // 右
#define DirMax (4) // 方向の種類数


この辺はいわゆるプリプロセッサによる置換マクロ
DirUpは0という数値に置き換わり、
DirDownは1に置き換わる
って感じ。




// mapの状況
typedef enum { MapWall = 0, MapStart = 1, MapAisle = 2, MapGoal = 3 } MapStatus;

Mapの状況を定義している列挙型
しかしなぜここで列挙型を使っているかは不明
#define MapWall ( 0 )とかでも同じ気がしますが、
この辺は生徒に混乱させようという先生の企みなのかも?



// 現在位置と方向
typedef struct {
int x; // 位置
int y;
int dir; // 進行方向
MapStatus status; // 現在地の状況
} CurrentState;


「カレントステイト」と読むらしい。
現在のプレイヤーのx座標、y座標、進む方向、マップの状態がどうなっているか
を扱ったプレイヤー構造体です。




typedef struct {
char* name;
void ( *init ) ( int, int, CurrentState );
CurrentState ( *find ) ( CurrentState );
CurrentState ( *getCurrent ) ( void );
} PlayerInfo;


プレイヤー情報を扱っている構造体。
あくまでプレイヤー識別なのでほとんどいじる必要がない(いじってもゲームに差し支えはない)





#if !defined ( __MAZE_C__ )
// 論理値
typedef enum { true = 1, false = 0 } Bool;
// 進むことができるかを調べる
extern MapStatus canPassThrough ( CurrentState );
#endif


プログラムをCで書く場合はここが通っても大丈夫だけど、
CPPで書く場合は__MAZE_C__をdefineしないとエラーになる。

単純にbool型がサポートされているかされていないか程度の問題なので
まぁcppで書きたい方は…って感じなのかな?



#endif ( __MAZE_H__ )




以上がヘッダーファイルの中身


次に最初から用意されている読み込み用のCファイル


#define __MAZE_C__
#include "maze.h"
#pragma warning( disable:4996 )

#define StatusOffset (2) // 進行状況の表示位置
#define MsgRow (24) // システムメッセージを表示する行
#define PlayerMax (10) // 最大参加可能プレーヤー数
#define Wait (100) // プレイヤーを動かす間隔
#define QuestContinue '\0' // 探索継続
#define QuestAbort KeyEscape // 探索中断
#define QuestGoal 'G' // 探索終了(ゴールイン)
#define QuestSkip -1 // 探索スキップ(すでにゴールインしている)
#define MapMaxCol (80) // MAPの1行の最大長



とりあえずこの定数値は気にする必要なし





static int playerCount = 0; // 参加しているプレイヤー数
static int currentPlayer = -1; // 現在、迷路探索しているプレーヤー
static PlayerInfo* player [ PlayerMax ]; // プレーヤの情報
static int step [ PlayerMax ]; // 現在までの探索歩数
static CurrentState pos [ PlayerMax ]; // 現在地

static char** maze; // 迷路マップ
static int mazeHeight = 0; // 迷路のサイズ
static int mazeWidth = 0;
static CurrentState start = { 0, 0, DirDown, MapStart };// 開始位置



この辺がプログラムで使われているグローバル変数。
ただしほとんどstaticで宣言された内部リンケージなので僕らが書いているプログラムファイルからは
externで引っ張ってくることはできない



//
// 関数プロトタイプ
//
static char** loadMap ( void ); // MAPの読み込み
static void init ( void ); // 全体の初期化
static void showMaze ( char**, int ); // 迷路の表示
static int questMaze ( ); // 次の位置の取得

static void showMessage ( char* ); // システムメッセージ表示
static char* getFileName ( void ); // ファイル名入力
static void cutout ( char* ); // 文字列末の改行コード除去

void locate ( int, int ); // ここから下は、画面制御関係
void setColor ( WORD );
void setCursor ( int );
void clearScreen ( );


こちらがグローバル関数。個人的にはGetFileNameの戻り値がMapファイルの名前なので
これを持ってきて改ざんすれば常に自分のマップを表示!とかできそうな感じがしたのですが、
staticなのでこれも不可能。orz



// 各プレーヤーの思考ルーチンを持つ構造体を返す関数
//
extern PlayerInfo* getPlayerNameInfo ( void );

// 迷路の状態を表示する文字列
char* dirString[] = { "A", "V", "<", ">" };
char* mapString[] = { "壁", "スタート", "通路", "ゴール" };


このあたりは単なるデータでしかないので持ってきてもせいぜいデバッグ用ぐらい
しかもGetPlayerNameInfoはこっちのファイルの中身なのでいじっても仕方ない。


そしてこちらが僕らのいじるプログラム



//次に進む場所を計算する関数
//次に進む場所を返すようになっていれば、変更可
static CurrentState findNext ( CurrentState pos )
{
CurrentState next = pos; //次に進むコマの候補を求める

Render( NextDir ); //デバッグ用
next.dir = DirInput[NextDir]; //次の方向

switch ( next.dir ){
case DirUp : next.y--; break;
case DirDown : next.y++; break;
case DirLeft : next.x--; break;
case DirRight : next.x++; break;
}

// 次に進もうとしているセルの状態をチェックする
if ( next.status = canPassThrough ( next ) ){
pos = next;
}
NextDir++; //次の処理へ

return pos;
}


この中にプログラムを書いていき、どうやってコマを動かすかを決めますが、
実質いじれる情報量が限られています。


僕らにできるのは
・次移動する場所に壁があるのか、通れる道なのかをチェックすること
・どういうタイミングでどの方向に移動させるか


くらいです
まぁどうにかなるでしょう。




ちなみに上のは僕の書いた処理の中身です。
デフォルトは違います。


明日は結合テスト一回目!
どうなるかなぁ~

スポンサーサイト

2011/01/30 23:13 |未分類COMMENT(0)TRACKBACK(0)  

コメント

コメントの投稿



管理者にだけ表示を許可する

 | BLOG TOP | 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。