質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Q&A

解決済

2回答

2994閲覧

迷路の最短経路を求めるアルゴリズムのソースがうまくいきません。

KentaroT

総合スコア5

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

0グッド

1クリップ

投稿2020/02/28 10:43

編集2020/02/28 11:30

迷路のアルゴリズムのコード

最終的に出てくる数列が、迷路の最短経路になるはずなのですが、うまくいきませんでした。
自分でも検証してみましたが、間違っているところのご指摘お願いします。
※課題の答え合わせをしているのではないかというご指摘がありましたので説明しますと、
この問題は平成31年度の筑波大学の編入試験の問題で、
答えが公開されていないため、以下のソースコードに誤りがあるところをお聞きできればと質問させていただいた次第です。

発生している問題

3503535353535 35353535353535 35353535353535 35353535353535 35353535353535 と表示されてしまう。 (目的の数列は以下) 3503535353535 3513578935 352356351035 353456735 3535353535835

該当のソースコード

C

1#include<stdio.h> 2#define X_size 7 3#define Y_size 5 4int maze[X_size][Y_size] = { 5 {1,1,1,1,1}, 6 {0,0,0,0,1},{1,1,1,0,1}, 7 {1,0,0,0,1},{1,0,1,0,1}, 8 {1,0,0,0,0},{1,1,1,1,1} 9}; 10int ok(int x, int y){ 11 if (maze[x][y]==0) 12 { 13 return 1; 14 }else{ 15 return 0; 16 } 17} 18int dist[X_size][Y_size]; 19void init_dist(void){ 20 int x,y; 21 for(int x=0; x < X_size; x++){ 22 for(int y =0; y < Y_size; y++){ 23 dist[x][y]= X_size * Y_size; 24 } 25 } 26} 27int update_dist(int x1,int y1,int x2,int y2){ 28 if(ok(x1,y1) == 1 && ok(x2,y2) == 1){ 29 if (dist[x2][y2] > dist[x1][y2] + 1){ 30 dist[x2][y2] = dist[x1][y1] + 1; 31 return 1; 32 } 33 } 34 return 0; 35} 36 37int main(void) { 38 int changed,x,y; 39 init_dist(); 40 dist[1][0]= 0; 41 do{ 42 changed=0; 43 for(y=0;y<Y_size;y++){ 44 for(x=0;x<X_size;x++){ 45 update_dist(x,y,x-1,y); 46 changed += update_dist(x,y,x-1,y); 47 update_dist(x,y,x+1,y); 48 changed += update_dist(x,y,x+1,y); 49 update_dist(x,y,x,y-1); 50 changed += update_dist(x,y,x,y-1); 51 update_dist(x,y,x,y+1); 52 changed += update_dist(x,y,x,y+1); 53 } 54 } 55 }while(changed); 56 for(y=0;y<Y_size;y++){ 57 for(x=0;x<X_size;x++){ 58 printf("%d",dist[x][y]); 59 } 60 printf("\n"); 61 } 62 return 0; 63}

試したこと

関数の宣言まではうまくいっていることは確認したので、mainのdo文の中がおかしいのかなとおもいます。
update_dist()がおかしいみたいです

補足情報

イメージ説明
イメージ説明イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/02/28 10:46

課題の答え合わせはここでは不適切
Orlofsky

2020/02/28 10:51

宿題は自力でやりましょう。
guest

回答2

0

ベストアンサー

まぁ、学校の課題を丸投げしているんじゃなくて、「入試の過去問を解いているだけ」だと思うので...
それなりに努力もしてますし。

C

1int update_dist(int x1,int y1,int x2,int y2){ 2 if(ok(x1,y1) == 1 && ok(x2,y2) == 1){ 3 if (dist[x2][y2] > dist[x1][y2] + 1){ 4 dist[x2][y2] = dist[x1][y1] + 1; 5 return 1; 6 } 7 } 8 return 0; 9}

この関数内のif()の判定ですが、添字に与えるべき変数が間違っていますね。
常にx1, x2x2, y2の組み合わせになるべきなのに、間違っている場所があります。

しかし、それ以外にも修正すべき点が8ヶ所(修正方法によっては5ヶ所かな?)ありますが、そこはヒントに留めておきたいと思います。

  1. update_dist()の呼び出しを余計にしています(4ヶ所)。これだと、同じ箇所を二回判定していることになりませんか?
  2. fanaさんもご指摘のように、ok()関数か、もしくはfor()ループ内で、xyが配列の定義で指定された添字内であるか判定の判定をする必要があります。そのままだと迷路の範囲外まで読みに行ってしまい、想定外の結果になる可能性があります。

がんばってください。


でも、入試の問題ってもっとシンプルな答えになりそうな気がするんですけど...
もしかして私は落ちてる?

###追伸
上記1. の「余計な呼び出し」ですが、よく考えたら(考えなくても)答えそのものは変わりませんね。でも、どのように採点されるのかわかりませんから、余計な記述は消した方が良いとは思います。

投稿2020/02/28 11:50

編集2020/02/28 12:23
TsukubaDepot

総合スコア5086

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KentaroT

2020/02/28 12:31

添字見落としてるとは思いませんでした。 ヒントいただいたところですが、1つめは問題に上下左右を参照するよう指示がありました。(tsukubadepotさんのおっしゃられているのは幅優先探索のことかと思います) 2つめはok()関数の方で解決しました。 ありがとうございます。
TsukubaDepot

2020/02/28 12:37 編集

1. について。 以下の処理 update_dist(x,y,x-1,y); /* (1) */ changed += update_dist(x,y,x-1,y); /* (2) */ ですが、(1)の呼び出しは不要ですよね。結果には影響しませんが、意味のない処理です。 update_dist()関数に関係する他の3つの処理でも、同じように意味のない処理をやっていますね。
KentaroT

2020/02/28 12:38

質問投稿した後にこの部分は直してたのですが、反映するのを忘れてました。お手数おかけしました。ご丁寧なご指摘ありがとうございました。
TsukubaDepot

2020/02/28 12:39

いえいえ。良い体操になりました。 あとは、過去問の引用元は記述しておいた方がいいですね。
guest

0

面倒そうなので全部見てませんけども,
とりあえずぱっと見で,関数ok()の実装がやばそう.範囲外チェックが無い的な意味で.

投稿2020/02/28 11:31

fana

総合スコア11654

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問