No.3ベストアンサー
- 回答日時:
ANo.2=Interestです。
コードを見てピンと来ました。それ持ってます。谷口さんという方が書かれたマイクロマウスシミュレータ(シェアウエア)ですよね。私もそのシミュレータを使ってマイクロマウスの迷路探索アルゴリズムの動作検証をしています。
昨年そのシミュレータで、左手法、拡張左手法、ポテンシャル法の3通りのアルゴリズムを実装して、3通りとも正しく動作することを確認しました。ソースコードの量がここで紹介するにはちょっと多すぎるので、考え方を示すためにソースコードの一部だけ紹介します。
// ----------------------------------------------------------------------------
// << private >>
// 関数simpleLeftHandMethod
// 概要単純な左手法で迷路解くためのマウスの動作を作る。
//
// 引数*thisナビゲータのオブジェクト
//*cart台車オブジェクトへのポインタ
// 戻り値なし
//
//[ 左手法の簡単な説明 ]
//左、前、右、後ろの順に優先順位をつけて壁をチェックして移動する。
// ----------------------------------------------------------------------------
void simpleLeftHandMethod(Navigator *this, Cart *cart){
CartCommand command;
CartCommand command2;
//前方、左側、右側は、マウスの進行方向に向かってみた場合
if( FALSE == Cart_getLeftWall() ){ // 左側に壁がなければ左を向く。
command.action = CART_TURN_LEFT;
command.volume = 90;
Cart_setCommand( cart, command );
Navigator_updateDir( this, 90 );
}
else if( FALSE == Cart_getFrontWall() ){// 前方に壁がなければそのまま。
}
else if( FALSE == Cart_getRightWall() ){// 右側に壁がなければ右を向く。
command.action = CART_TURN_RIGHT;
command.volume = 90;
Cart_setCommand( cart, command );
Navigator_updateDir( this, -90);
}
else{// 三方向に(左側,前方,右側)に壁があるのでUターンする。
command.action = CART_TURN_180;
command.volume = 0;
Cart_setCommand( cart, command );
Navigator_updateDir( this, 180 );
}
// 何はともあれ、前に進む。
command2.action = CART_MOVE_BLOCK;
command2.volume = 1;
Cart_setCommand( cart, command2 );
Navigator_updatePos( this, command2.volume );
}
// ----------------------------------------------------------------------------
// << private >>
// 関数extendLeftHandMethod
// 概要拡張左手法で迷路解くためのマウスの動作を作る。
//
// 引数*thisナビゲータのオブジェクト
//*cart台車オブジェクトへのポインタ
// 戻り値なし
//
//[ 拡張左手法の簡単な説明 ]
//基本的な考え方は単純左手法と同じだが、初めてきた区画の周囲に来たことが
//ある区画がある場合は”仮想壁”を設ける。
//
// ----------------------------------------------------------------------------
void extendLeftHandMethod(Navigator *this, Cart *cart){
ucharx, y;
MouseDirdir;
ucharwallData;
CartCommand command;
CartCommand command2;
x = Navigator_getPosX(this);
y = Navigator_getPosY(this);
dir = Navigator_getDir(this);
wallData = 0;
Navigator_updateVirtualWall( this, cart);// 仮想壁を記録する。
// 以降の処理は仮想壁を利用して単純左手法と同じアルゴリズムでよい。
wallData = Map_getVirtualWall(this->map, x, y);
// 左側に壁がなければ左を向く。
if( ((NORTH == dir) && !(WEST_WALL_MASK & wallData)) ||
((EAST == dir) && !(NORTH_WALL_MASK & wallData)) ||
((SOUTH == dir) && !(EAST_WALL_MASK & wallData)) ||
((WEST == dir) && !(SOUTH_WALL_MASK & wallData)) ){
command.action = CART_TURN_LEFT;
command.volume = 90;
Cart_setCommand( cart, command );
Navigator_updateDir( this, 90 );
}
else if(// 前方に壁がなければそのまま。
((NORTH == dir) && !(NORTH_WALL_MASK & wallData)) ||
((EAST == dir) && !(EAST_WALL_MASK & wallData)) ||
((SOUTH == dir) && !(SOUTH_WALL_MASK & wallData)) ||
((WEST == dir) && !(WEST_WALL_MASK & wallData)) ){
}
else if(// 右側に壁がなければ右を向く。
((NORTH == dir) && !(EAST_WALL_MASK & wallData)) ||
((EAST == dir) && !(SOUTH_WALL_MASK & wallData)) ||
((SOUTH == dir) && !(WEST_WALL_MASK & wallData)) ||
((WEST == dir) && !(NORTH_WALL_MASK & wallData)) ){
command.action = CART_TURN_RIGHT;
command.volume = 90;
Cart_setCommand( cart, command );
Navigator_updateDir( this, -90);
}
else{// 三方向に(左側,前方,右側)に壁があるのでUターンする。
command.action = CART_TURN_180;
command.volume = 0;
Cart_setCommand( cart, command );
Navigator_updateDir( this, 180 );
}
// 何はともあれ、前に進む。
command2.action = CART_MOVE_BLOCK;
command2.volume = 1;
Cart_setCommand( cart, command2 );
Navigator_updatePos( this, command2.volume );
}
設計はオブジェクト指向ですが、実装はCです。
Navigatorの責務
迷路の壁情報と通過回数を保持・更新します。
迷路内でのマウスの位置、方向を保持・更新します。
Cartの責務
前進、ターンなど与えられた走行コマンドを実行します。
この回答への補足
お返事がおそくなってすみません(汗)
書いてあるプログラムがなんなのか調べてみました。書いてある意味はわかったのですが、このままコンパイルすると未定義のシンボルNavigatorがエラーとでてうまくいきません。どうしたらいんでしょうか?
No.4
- 回答日時:
> このままコンパイルすると未定義のシンボルNavigatorがエラーとでてうまくいきません。
そうでしょうね。なにせ、『ソースコードの量がここで紹介するにはちょっと多すぎるので、考え方を示すためにソースコードの一部だけ紹介します。』という前提で公開したコードの一部なのですから。
機械的に数えてみたところ、私がシミュレーション用に書いたソースコードは(コメント文を差し引いた実行可能な)コード行数で1300行程度ありました。ここで公開できる大きさで無いことは分かっていただけると思います。
> どうしたらいんでしょうか?
(単純な)左手法、拡張左手法がどのようなものか、ソースコードから読み取っていただけたことと思います。概念さえ分かってしまえば、それを実装できるかどうかは設計・実装する人の技量にかかってきます。
どうしても実装したコードを見たいということでしたら、(このサイトでは個人が特定できるような情報は載せるなと言うことになっているので)mixiのマイクロマウスコミュニティで相談してもらえれば、こっそりソースコード差し上げます。
・・・と思ったら、今日マイクロマウスコミュニティでそういう質問している方すでにいらっしゃいますね。
この回答への補足
親切にしてくださってありがとうございます。
実を言うとmixiのマイクロマウスコミュニティで質問しているのも私です(汗)mixiでソースコードをもらえないでしょうか?
大変迷惑をかけてすみません(汗)
No.2
- 回答日時:
丸投げっぽい質問の仕方すると、削除されちゃいますよ~
> 左手拡張法と求心法とトレモー法のどれかを作って
こういう言い方をするのは大体マイクロマウス系の人なので
まずはここの過去ログ見てください。
QNo.2633652 経路探索について
http://okwave.jp/qa2633652.html
QNo.1553632 迷路を脱出する経路探索プログラムをC言語で作成するには?
http://okwave.jp/qa1553632.html
> C言語がまったくわからないので困っています。
C言語そのものが分からないと、説明を受けても何のことだか理解できないですよね。教科書読むより作りながら実戦で覚えたほうがはるかに記憶に残りますが・・・
> ネットにあった迷路のソフトを使って走らせるんですが
具体的にどのソフトですか? URL出せますか?
ちなみに私はマイクロマウス作ってます。
No.1
- 回答日時:
#include <stdio.h>
#define Y 20
#define X 16
typedef struct maze{
int map[Y][X];
int maxy, maxx;
int starty, startx;
int goaly, goalx;
} MAZE;
void Direction(MAZE *maze)
{
int y = maze->starty, x = maze->startx;
while(y != maze->goaly || x != maze->goalx){
if(maze->map[y][x + 1] == 2) maze->map[y][x ++] += 1;
else if(maze->map[y + 1][x] == 2) maze->map[y ++][x] += 2;
else if(maze->map[y][x - 1] == 2) maze->map[y][x --] += 3;
else if(maze->map[y - 1][x] == 2) maze->map[y --][x] += 4;
else break;
}
return;
}
void Print(MAZE *maze)
{
char *marks[] = {"■", " ",}, *arrows[] = {"→", "↓", "←", "↑",};
int y, x, arrow;
if(maze->map[maze->starty][maze->startx] == 2) Direction(maze);
for(y = 0; y < maze->maxy; y ++){
for(x = 0; x < maze->maxx; x ++){
if(maze->map[y][x] == -1) maze->map[y][x] = 1;
if((y == maze->starty && x == maze->startx) ||
(y == maze->goaly && x == maze->goalx)){
arrow = 2 * (y == maze->goaly);
if(y == 0) arrow += 1;
else if(x == maze->maxx - 1) arrow += 2;
else if(y == maze->maxy - 1) arrow += 3;
printf("%s", arrows[arrow & 3]);
}
else if(maze->map[y][x] > 2) printf("%s", arrows[maze->map[y][x] - 3]);
else printf("%s", marks[maze->map[y][x]]);
}
putchar('\n');
}
return;
}
void Route(MAZE *maze)
{
int y = maze->starty, x = maze->startx;
while(!(y == maze->goaly && x == maze->goalx)){
if(maze->map[y][x + 1] == 1 && x + 1 < maze->maxx) maze->map[y][x ++] = 2;
else if(maze->map[y + 1][x] == 1 && y + 1 < maze->maxy) maze->map[y ++][x] = 2;
else if(maze->map[y][x - 1] == 1 && x - 1 >= 0) maze->map[y][x --] = 2;
else if(maze->map[y - 1][x] == 1 && y - 1 >= 0) maze->map[y --][x] = 2;
else if(maze->map[y][x + 1] == 2 && x + 1 < maze->maxx) maze->map[y][x ++] = -1;
else if(maze->map[y + 1][x] == 2 && y + 1 < maze->maxy) maze->map[y ++][x] = -1;
else if(maze->map[y][x - 1] == 2 && x - 1 >= 0) maze->map[y][x --] = -1;
else if(maze->map[y - 1][x] == 2 && y - 1 >= 0) maze->map[y --][x] = -1;
else return;
}
maze->map[y][x] = 2;
return;
}
int main(void)
{
MAZE maze = {{
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,},
{0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0,},
{0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0,},
{0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0,},
{0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0,},
{0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0,},
{0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,},
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,},
{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,},
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,},
{0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0,},
{0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0,},
{0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0,},
{0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,},
{0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0,},
{0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,},},
Y, X, 0, 1, Y - 1, X - 2,};
Print(&maze);
putchar('\n');
Route(&maze);
Print(&maze);
return 0;
}
この回答への補足
実際にコンパイルしてみて実行してみましたが、動作しませんでした(;_;)自分でもかなり考えてはいるんですが、よくわかりません・・・。一応、サンプルの一部みたいなのがあったんですが・・・。この意味もよくわからなくて(汗)
#include <conio.h>
#include <stdio.h>
#include "mms.h"
void main()
{
if(SimInit()==0) {//マイクロマウスシミュレーターを初期化する
puts("先にマイクロマウスシミュレーターを実行してください。\n");
puts("-----------------何かキーを押してください。\n");
while(kbhit()==0)//何かキーが押されたら終了
;
return;//終了
}
puts("Enterを押すとスタートします。\n");
while(getch()!=Enter)
;
puts("--------------------------------------------------------");
puts("途中で止まってしまったり、同じところをループしている場合");
puts("何かキーを押すと終了します。\n");
MouseInit(); //マウスを初期化する(マウスをスタート位置に戻す)
while(kbhit()==0) {//何かキーが押されたら終了
//前方、左側、右側は、マウスの進行方向に向かってみた場合
if(InputLW()==0) //左側に壁がなければ
TurnLeft(90); //左90度回転
else if(InputFW()==0) //前方に壁がなければ
;//そのまま
else if(InputRW()==0)//右側に壁がなければ
TurnRight(90);//右90度回転
else
Turn180();//三方向に(左側,前方,右側)に壁が
//あるので、Uターンする
MoveBlock(1);//1ブロック進む
if(InputGL()==1) {//ゴールエリアに到達したら
puts("ゴール!\n");
puts("何かキーを押してください。\n");
while(kbhit()==0)//何かキーが押されるのを待つ
;
break;//迷路探索終了
}
}
MouseInit(); //マウスを初期化する(マウスをスタート位置に戻す)
}
どうすればいいでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) プログラムの勉強のおすすめは 7 2022/12/09 20:09
- インターネット広告・アフィリエイト アフェリエイトサイト 作成について 5 2022/05/13 21:31
- C言語・C++・C# c言語 コマンドライン引数 4 2023/02/09 18:47
- その他(プログラミング・Web制作) ドローのソフト 薦めてください 6 2023/07/21 09:03
- その他(趣味・アウトドア・車) Arudino nanoが正常に動作しない原因 1 2022/10/30 18:29
- C言語・C++・C# exeファイルが作れない(windows10) 6 2022/08/13 08:47
- その他(プログラミング・Web制作) Windows上のプログラム。「予め決められた時刻に自分で起動して処理して自分で終了する」って可能? 3 2023/01/04 14:29
- C言語・C++・C# c言語で自然数nを入力、2以上n以下の偶数の累積sumを求めるプログラムをfor文を使って作りたいで 4 2022/11/09 14:10
- アプリ パソコンやスマホで、「ソフト」と「アプリ」ってどんな違いがあるの? 9 2022/11/02 07:44
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語の 配列の中 出力について
-
二つのbxsliderをレスポンシブ...
-
Googleマップに複数のピンを立...
-
カンマ区切りのデータを配列に...
-
JavascriptからPHPへのAjax通信...
-
要素内を常に一番下を表示させたい
-
jQueryを使いformでsubmitした...
-
変数にドットをいれることはか...
-
.txtファイルの読み込み
-
<input>のvalue値をプルダウン...
-
Selenium4でボタンをクリックで...
-
フレーム内の要素へのXPATHはど...
-
リンク付きの画像をクリックす...
-
Javascriptを使ってQRコード読...
-
プルダウン内容に応じてラジオ...
-
AjaxでSJISファイル読み込みす...
-
Ajaxでフォームデータを連続登...
-
IndexedDB を使ってファイルア...
-
bxsliderで画像毎に表示時間を...
-
タブをフリックでスライドでき...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
カンマ区切りのデータを配列に...
-
二つのbxsliderをレスポンシブ...
-
迷路探索プログラムを作るには...
-
google maps api v3のルート検索
-
how's whether today in yufuin?
-
Google Maps:同マップ内でそれ...
-
Python: TypeError
-
Selenium4でボタンをクリックで...
-
Javascriptを使ってQRコード読...
-
JavascriptからPHPへのAjax通信...
-
IndexedDB を使ってファイルア...
-
同一ページ移動時ハンバーガー...
-
JavaScriptでtabindexの変更っ...
-
jQueryを使いformでsubmitした...
-
SQLのmaxで求めた値を変数に代...
-
インラインフレームを自動更新...
-
階層別の組織図の自動作成について
-
ドラッグ & ドロップでのド...
-
jQuery toggle() 戻るで開いた...
-
AjaxでJSONを受信すると、文字...
おすすめ情報