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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Q&A

3回答

3175閲覧

Java 無限ループになる理由

nikkucc

総合スコア14

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

1グッド

2クリップ

投稿2019/06/18 04:50

編集2019/06/18 05:01

とあるサイトを使って、勉強のために少しプログラムを書いてみました。

こちらがサイトになります。→リンク
コンストラクタや、引数、戻り値などの勉強のためにやっております。基本的なことからあまり理解ができておらず、簡単なことかもしれませんが、よろしくお願い致します。

Java

1class Actor extends Thread{ 2 private int hitpoint; 3 private int offence; 4 private int deffence; 5 private String name; 6 private Actor target; 7 private int deley = 1; 8 9 public int getHitPoint() { 10 return hitpoint; 11 } 12 13 public int getOffence() { 14 return offence; 15 } 16 17 public int getDeffence() { 18 return deffence; 19 } 20 public Actor getTarget() { 21 return target; 22 } 23 24 public void setHitPoint(int hitpoint) { 25 this.hitpoint = hitpoint; 26 } 27 public void setAttack(int offence) { 28 this.offence = offence; 29 } 30 public void setDeffence(int deffence) { 31 this.deffence = deffence; 32 } 33 34 public void setTarget(Actor target) { 35 this.target = target; 36 } 37 public boolean isDead() { 38 return hitpoint<=0; 39 } 40 41 public Actor(String name,int hitpoint,int offence,int deffence) { 42 this.name = name; 43 this.hitpoint = hitpoint; 44 this.offence = offence; 45 this.deffence = deffence; 46 } 47 48 public void attack(Actor pActor) { 49 int damage = offence - pActor.getDeffence(); 50 if(damage >= 0) { 51 pActor.setHitPoint(pActor.getHitPoint()-damage); 52 System.out.println(name+"は"+pActor.getName()+"に"+damage+"のダメージを与えた!"); 53 54 }else if(damage<=0) { 55 System.out.println("ダメージを受けない"); 56 } 57 58 59 } 60 61 public void run() { 62 while(true) { 63 try { 64 sleep(1 * deley); 65 66 }catch(InterruptedException e) { 67 } 68 if(isDead()) 69 break; 70 attack(target); 71 } 72 } 73 }

Java2

1public class MyMain { 2 3 4 public static void main(String[] args) { 5 6 Actor Hero = new Actor("主人公",100,25,15); 7 8 Actor Enemy1 = new Actor("敵1",60,30,5); 9 10 Hero.setTarget(Enemy1); 11 Enemy1.setTarget(Hero); 12          Hero.start(); 13 Enemy1.start(); 14 15 } 16}

こちらを実行すると、無限ループになってしまいます。ひとつ前に行った、

Java3

1while(true) { 2 3 Hero.attack(Enemy1); 4 if(Enemy1.getHitPoint() <= 0) { 5 System.out.println(Enemy1.getName() +"を倒した!"); 6 break; 7 } 8 Enemy1.attack(Hero); 9 if(Hero.getHitPoint() <= 0) { 10 System.out.println(Hero.getName() + "は倒されてしまった。"); 11 break; 12} 13} 14

こちらはしっかりと動作しました。
attack(target);という表記がありますが、サイトではattack();のみでした。
このままではコンパイルが通らなかったので、勝手にtargetと入れました。これのせいでしょうか?
よろしくお願い致します。

現在、一度試したところ、実行する度に結果が変わるという現象が起きています。
実行の結果です。
敵1はThread-0に15のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
敵1はThread-0に15のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
敵1はThread-0に15のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
以下無限ループ

二回目
主人公はThread-1に20のダメージを与えた!
敵1はThread-0に15のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
敵1はThread-0に15のダメージを与えた!
敵1はThread-0に15のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
以下無限ループ

デバッグ一回目
敵1はThread-0に15のダメージを与えた!
敵1はThread-0に15のダメージを与えた!
以下無限ループ

デバッグ二回目
主人公はThread-1に20のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
主人公はThread-1に20のダメージを与えた!
どういうことでしょうか。。。

DrqYuto👍を押しています

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

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

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

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

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

stdio

2019/06/18 04:53

hitpointにどんな値が入っているかlogで確かめましょう。
nikkucc

2019/06/18 05:03

>>stdio様 hitpointには、主人公の100が入っておりました。 >>Orlofsky様 ご指摘ありがとうございます。 リンク変更いたしましたので、よろしくお願い致します。
miyabi_takatsuk

2019/06/18 09:23 編集

すみません、無知識で申し訳ございませんが、 while(true) { って、Javaでは一般的な書き方なのでしょうか? そもそも無限ループ乱発しそうな書き方だと思うのですが・・・。 中で、条件によってbreak;させているようですが、()の条件の中にも、カウンターなりで、ループの限界回数を定めた方がいいかと思いますが・・・。
yukkuri

2019/06/18 11:27 編集

> miyabi_takatsukさん 結構一般的で、スレッドとかだとよく使います。人によっては、変数に入れたりしてコントトールしていますが。ただし、気をつけないと無限ループになるのは事実です。
miyabi_takatsuk

2019/06/18 13:59

yukkuriさん>そうだったのですね・・・!勉強になりました。 ありがとうございます!
stdio

2019/06/19 00:50

isDead()がwhileを無限ループさせている原因なので、100が入っているようなら、抜けるのは無理です。 あと、attack関数の中で、hitpointの値を減らしていないように見えます。 貴方の発言から察するに常に同じ値が入っているのが原因ではないでしょうか? ちゃんと減っているかデバックしているか確認した方が良さそうです。 またしっかりとSystem.out.println(Enemy1.getName() +"を倒した!");又はSystem.out.println(Hero.getName() + "は倒されてしまった。");のメッセージは出ていますか? もし出ていないなら明らか、hitpointが減っていないか、逆に増えて行っている証拠です。
nikkucc

2019/06/19 05:12

たくさんの回答ありがとうございます! 色々修正してみた結果、次の質問のようになっております。。 皆さんの回答をもとにもう少し手を加えてみたいと思います。 よろしければ、次の質問も回答いただけるとありがたいです。 手を加えるうちに様々な問題が発生しております。。
guest

回答3

0

主人公・敵1「相手を攻撃するぞ!」

敵1死亡後
敵1「死んだからループ抜けます」
主人公「生きてる限り相手を攻撃するぞ!」

という状態です。

attackメソッドは、そう使うならフィールド変数にtargetなんていりませんよね?

投稿2019/06/18 13:11

swordone

総合スコア20651

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

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

nikkucc

2019/06/19 05:14

回答ありがとうございます。 サイトを確認し、attackメソッドを実装したのですが、targetか何かを入れないとコンパイルエラーとなってしまい、実行をすることもできませんでした。 原因が分からず、targetを入れることでコンパイルが通ったので、大丈夫だと思いました。
swordone

2019/06/20 01:35 編集

そもそも、attackメソッドをあなたは正しく実装しているのですか? 少なくとも私はそれはありえないと考えています。
guest

0

とりあえず原因がわかりました。

// if(isDead()) これはだめ if(isDead() || target.isDead()) break;

解説:
追加した || は右、左どちらかがtrueになれば実行される、という印(?)です。
右のtarget.isDead()は、相手が倒れたらtrueになります。
要するに、相手は倒れたが自分が倒れていないから繰り返し、というふうになっていたわけです。

sample

1if(isDead()) System.out.println( "やられてしまった" ); 2if(target.isDead()) System.out.println( "敵を倒した" );

みたいに、処理を分ければそれぞれ違うこともできます。

投稿2019/06/18 11:35

yukkuri

総合スコア624

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

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

nikkucc

2019/06/19 05:16

回答ありがとうございます! もしよろしければ、次の質問にも回答していただけるとありがたいです。 次は、どっちも倒してしまうという現象が起きています。 ループにはとりあえずならないようになったのですが。。
guest

0

attack関数内にあるpActor.getName()なのですが、Actorの中にgetName関数が記載されていませんね。そのせいで、Thread-1とかいう意味の分からない名前になってしまっていますね。もしかしたらそこが原因かも...

それと残りhitpointを表示できるようにしましょう。

主人公は敵1に20のダメージを与えた! 敵1のHPは残り45だ!

このようにすれば非常にデバックしやすく、原因になっているところも分かると思います。
Javaの勉強頑張ってくださいね。

あと、もはや意味がないと予想されるリンクサイトに書かれていた、run関数は消してもらっても構いませんよ。

投稿2019/06/20 01:25

stdio

総合スコア3307

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

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

swordone

2019/06/20 01:34

いや、runって少なくともこのプログラムにおいては肝だと思うんですが…
stdio

2019/06/20 01:43 編集

なんか肝心な部分が2つ書かれていてどちらが通っているのか実は判断できません。 肝かと言われれば、かつては肝だったですね。肝の部分がJava3に変わっている様に思ったので、消してもいいと言ったんですが... あくまで予想で書いただけですので、肝だと主張するなら消しますが...
swordone

2019/06/20 02:28

Java3? いやだって、runを消したらこのプログラムは何もしなくなりますよ?
stdio

2019/06/20 03:08 編集

Java3は質問者が書いている上から3番目のcodeです。 > こちらを実行すると、無限ループになってしまいます。 って書いてますよね。多分魔改造しようとしてひとまずrunを変えたのでしょう。 貴方の主張通り、その場合Actorクラスが継承しているThreadももはや意味がなくなくなるのは確かです。 しかし質問の内容からして、きっと投稿されていないmain関数があるのだと予想できます。 しっかりとmainを書かず投稿してしまった質問自体に問題がありますが、質問文からそうではないかと予想して私はこのような発言をしました。説明が少なくて申し訳ないですがご了承いただきたい。 貴方はもう少し質問の内容を丁寧に読んだ方がいいと思いますよ。
swordone

2019/06/20 03:16

ああそうか、Java3の書き方だと、それまでとは別のmainがないと機能しないか
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問