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

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

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

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

Q&A

解決済

1回答

1315閲覧

javaのswingでオセロを作っています。

maruta12

総合スコア12

Java

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

0グッド

0クリップ

投稿2018/09/13 13:02

編集2018/09/13 14:10

文字数のため一部省略しますがオセロの基本的な動作は出来たのですが、置けないときにパスをしたいのですが一度パスをするとturnPass()が永遠にループされてしまいます。
paintComponentに一部処理を書いてマウスクリック時に動作を起こすような書き方をしているのですが、『ターンが入れ替わった時』とかにturnPassを実行したい場合はどのように書けばいいのでしょうか。

public class Reversi extends JPanel { final int WIDTH = 500; // ウィンドウの横幅 final int HEIGHT = 560; // ウィンドウの縦幅 int wm = 50; // 左右の余白 int hm = 80; // 上下の余白 int square = 50; // 1マスの大きさ static String str = "黒の番です。"; static String sAssist = "ON/OFF"; static int turn = 1; // 手番(1:黒,2:白) static JLabel lturn = new JLabel(str); static JButton bAssist = new JButton(sAssist); static boolean pass = false; static boolean assist = false; static int ban[][] = { // 盤面の状態 【0:配置なし,1:黒,2:白】 { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 2, 1, 0, 0, 0 }, { 0, 0, 0, 1, 2, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 } }; static boolean putStone[][] = { // 盤面に石が置けるか(初期値はすべてfalse)【true:可,false:不可】 { true, true, true, true, true, true, true, true }, { true, true, true, true, true, true, true, true }, { true, true, true, true, true, true, true, true }, { true, true, true, true, true, true, true, true }, { true, true, true, true, true, true, true, true }, { true, true, true, true, true, true, true, true }, { true, true, true, true, true, true, true, true }, { true, true, true, true, true, true, true, true } }; // コンストラクタ(初期化処理) public Reversi() { setPreferredSize(new Dimension(WIDTH, HEIGHT)); addMouseListener(new mouse()); lturn.setForeground(Color.white); this.add(lturn); bAssist.addActionListener(new ButtonClickAction()); this.add(bAssist); } // 画面描画 public void paintComponent(Graphics g) { // 背景 g.setColor(Color.gray); g.fillRect(0, 0, WIDTH, HEIGHT); // 盤面 g.setColor(new Color(0, 170, 0)); g.fillRect(wm, hm, square * 8, square * 8); // 横線 g.setColor(Color.black); for (int y = hm; y <= hm + square * 8; y = y + square) { g.drawLine(wm, y, wm + square * 8, y); } // 縦線 for (int x = wm; x <= wm + square * 8; x = x + square) { g.drawLine(x, hm, x, hm + square * 8); } // 小さい● g.fillOval(wm - 3 + square * 2, hm - 3 + square * 2, 6, 6); g.fillOval(wm - 3 + square * 6, hm - 3 + square * 2, 6, 6); g.fillOval(wm - 3 + square * 2, hm - 3 + square * 6, 6, 6); g.fillOval(wm - 3 + square * 6, hm - 3 + square * 6, 6, 6); // 盤面の石 for (int i = 0; i < ban.length; i++) { for (int j = 0; j < ban.length; j++) { // ban[][]の中身が0以外の場合 if (ban[i][j] != 0) { if (ban[i][j] == 1) { // 1だった場合 g.setColor(Color.black); } else if (ban[i][j] == 2) { // 2だった場合 g.setColor(Color.WHITE); } g.fillOval(wm + 10 + square * i, hm + 10 + square * j, 30, 30); // マス目に石を描画する } } } // 盤面の置ける場所を判定 putStoneJudge(); turnPass(); // 置ける場所に丸を表示 if (assist) { for (int i = 0; i < putStone.length; i++) { for (int j = 0; j < putStone.length; j++) { // putStone[][]の中身がtrueだった場合 if (putStone[i][j]) { if (turn == 1) { // 黒の番だった場合 g.setColor(Color.black); } else if (turn == 2) { // 白の番だった場合 g.setColor(Color.WHITE); } g.drawOval(wm + 10 + square * i, hm + 10 + square * j, 30, 30); // マス目に石を描画する } } } } // cpu(); } class mouse extends MouseAdapter { public void mouseClicked(MouseEvent e) { // クリックされた場所を判定 loop: for (int i = 0; i < ban.length; i++) { // 横列の判定 if ((e.getX() - wm) / square == i) { for (int j = 0; j < ban.length; j++) { // 縦列の判定 if ((e.getY() - hm) / square == j) { // マスに何も置かれてない状態ならば putStone(i, j); break loop; } } } } } } // 石が置けなければ相手にパスをする public static void turnPass() { loop:for(int i = 0; i < putStone.length; i++){ for(int j = 0; j < putStone.length; j++){ if(putStone[i][j]){ break loop; }else if(i == putStone.length - 1 && j == putStone.length - 1){ System.out.println("パス"); pass = true; changeTurn(); System.out.println(str); } } } } //ターンを交代させる public static void changeTurn(){ if (turn == 1) { turn = 2; str = "白の番です。"; } else { turn = 1; str = "黒の番です。"; } lturn.setText(str); }

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

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

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

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

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

umyu

2018/09/13 13:18

changeTurnの内容を質問文に追記していただけませんか。あと質問文のコードはcodeタグで編集してくださいな。
guest

回答1

0

ベストアンサー

質問文の編集ありがとうございました。

永遠にループ

永久ループはループ終了条件を満たさない時に発生します。ループが正しく終わるのかをSystem.out.println()で変数の内容を出力してみたり、デバック実行でステップ実行をしてみてくださいな。

1, paintComponentに描画以外の処理を書かないようにします。
panitComponetが担当することは、現在の盤面表示/手番表示などの画面表示に関わる事のみです。

一定時間後に処理を行いたい場合(例えばCPUの思考ルーチン)は、javax.swing.timerCompletableFutureを使います。

panitComponetで呼び出している、putStoneJudge();turnPass();
マウスクリック時のイベントに移動してクリック時に判定をする方にします。
クリック時にクリック座標を元にしてbanの置き換え処理を行います。

■コマが置けるかの判断条件は
1, 白、黒コマが置かれていない。
2, その位置に置くことで敵ゴマを反転できる。
参考:オセロ(リバーシー)で駒をひっくり返す処理がわからない。

この2つの条件です。

2, 盤面情報はBoardクラスとして管理しcloneを実装するとアシスト機能でも流用できるかと。
3, staticにするとクラス変数となるので、インスタンス間で共有されてしまいます。
これも不具合を発生させやすいので、避けたほうがよいかと。
4, 変数:banと変数:putStoneと同じ盤面情報を2つの変数で管理していますが、
どちらの変数の値も正しく更新する必要が発生するため。難易度が高くなります。
banの全要素に対して駒が置けるかどうかをループでチェックし、
置ける座標(x,y)をArrayListに格納すると二重管理が防げます。

コマ反転に関しては白、黒、未配置以外に壁マスを作ると、縦、横、斜めの判定処理の使い回しが可能です。

5, コマは以下のようなenum型を作ると便利です。

Java

1public enum Stone { 2 3 /** 4 * None:未配置 5 * Black:黒 6 * White:白 7 * Wall:壁 8 */ 9 None(" "), Black("●"), White("○"), Wall("#"); 10 11 private final String label; 12 13 Stone(String label) { 14 this.label = label; 15 } 16 17 public Stone flip() { 18 if (this == Stone.Black) { 19 return Stone.White; 20 } 21 if (this == Stone.White) { 22 return Stone.Black; 23 } 24 throw new IllegalStateException(this.toString()); 25 } 26 27 public static boolean isStone(Stone s) { 28 return s == Stone.Black || s == Stone.White; 29 } 30 31 @Override 32 public String toString() { 33 return this.label; 34 } 35}

投稿2018/09/13 14:29

編集2018/09/13 15:22
umyu

総合スコア5846

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

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

maruta12

2018/09/14 12:27

永久ループになるのはループの終了条件を満たしていないときという当たり前のことを見落としていました。デバッグ実行等を使って調べてみます。 ほかにもマウスイベントに処理を移すなど変数の見直しをしてバグが起きにくくする配慮をするのが大切なのですね。 勝敗が決まるところまで作れるよう頑張ってみます。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問