🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Java

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

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

ArrayList

Java用のタグです。arrayListはListインターフェースを実装した、リサイズ可能な配列用クラスです。

Q&A

解決済

3回答

2681閲覧

javaでオセロを作成したが反転に問題が生じて困っている

退会済みユーザー

退会済みユーザー

総合スコア0

Java

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

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

ArrayList

Java用のタグです。arrayListはListインターフェースを実装した、リサイズ可能な配列用クラスです。

1グッド

0クリップ

投稿2019/11/26 13:15

編集2019/11/28 07:16

前提・実現したいこと

java環境で8×8盤面のオセロを作成した。 - 石が置かれている、ひっくり返せないマスには置けない。 - 手番は考慮しない。 - 石を点(x,y)に置き、ひっくり返せる周囲の石を反転させたい。

発生している問題

石を反転させる処理に問題が生じる (例) 初期配置から 黒石[5][3] 白石[3][2] 黒石[2][4] 白石[3][5] の順に配置すると意図してない[4][4]の黒石が反転される。

問題があると思われるソースコード

java

1 //石を置き他を反転させる 2 void setStoneAndReverse(int x, int y, int s) { 3 //8方向をチェック 4 for (int d=0; d<8; d++) { 5 ArrayList<Integer> p = new ArrayList<Integer>(); 6 p = getLine(x, y, direction[d]); 7 int cx = x; 8 int cy = y; 9 int n = 0; 10 11 while ( n < p.size()-1 && p.get(n) != s && ste[cx][cy].obverse == s) { 12 cx += direction[d].x; 13 cy += direction[d].y; 14 System.out.println(d); 15 System.out.println("cx="+cx); 16 System.out.println("cy="+cy); 17 ste[cx][cy].doReverse(ste[cx][cy].obverse); 18 n++; 19 } 20 } 21 }

java

1//盤面(x,y)から方向dに向かって石を順番に取得 2 ArrayList<Integer> getLine(int x, int y, Point d) { 3 ArrayList<Integer> line = new ArrayList<Integer>(); 4 int cx = x + d.x; 5 int cy = y + d.y; 6 while ( isOnBoard(cx, cy) && ste[cx][cy].obverse != 0) { 7 line.add(ste[cx][cy].obverse); 8 cx += d.x; 9 cy += d.y; 10 } 11 return line; 12 }

試したこと

上記のsetStoneAndReverse(int x, int y, int s){}において、反転を行った方角を示すdirection[d]を出力した。 - 意図しない石が反転された際、予想外の方向にも反転を行っていることが分かった。 - このことから方角を取得するgetLine(int x, int y, Point d){}に問題があると考えた。

Stoneクラス

java

1class Stone { 2 public final static int black = 1; 3 public final static int white = 2; 4 public int obverse = 0; 5 6 Stone() { 7 obverse = 0; 8 } 9 10 //表面の色を設定 11 void setObverse(int color) { 12 if ( color == black || color == white) 13 obverse = color; 14 else 15 System.out.println("黒か白でなければいけません"); 16 } 17 18 //白黒を入れ替える 19 void doReverse(int color) { 20 if ( color == black ) 21 obverse = white; 22 else if ( color == white ) 23 obverse = black; 24 else 25 System.out.println("黒か白でなければいけません"); 26 } 27 28 //表面の色で中心p, 半径radの円を塗り潰す 29 void paint(Graphics g, Point p, int rad) { 30 if (obverse == black) { 31 g.setColor(Color.black); 32 g.fillOval(p.x - 32, p.y - 32, 2*rad, 2*rad); 33 } 34 else if (obverse == white) { 35 g.setColor(Color.white); 36 g.fillOval(p.x - 32, p.y - 32, 2*rad, 2*rad); 37 } 38 } 39}

Boardクラス

java

1class Board { 2 Stone[][] ste = new Stone[8][8]; 3 public int num_grid_black; 4 public int num_grid_white; 5 private Point[] direction = new Point[8]; 6 public int[][] eval_black = new int[8][8]; 7 public int[][] eval_white = new int[8][8]; 8 9 //コンストラクタ初期化 10 Board() { 11 12 for(int i=0; i<8; i++) { 13 for(int j=0; j<8; j++) { 14 ste[i][j] = new Stone(); 15 } 16 } 17 ste[3][3].setObverse(1); 18 ste[3][4].setObverse(2); 19 ste[4][3].setObverse(2); 20 ste[4][4].setObverse(1); 21 //方向ベクトル 22 direction[0] = new Point(1,0); 23 direction[1] = new Point(1,1); 24 direction[2] = new Point(0,1); 25 direction[3] = new Point(-1,1); 26 direction[4] = new Point(-1,0); 27 direction[5] = new Point(-1,-1); 28 direction[6] = new Point(0,-1); 29 direction[7] = new Point(1,-1); 30 } 31 32 33 //盤面の中か? 34 boolean isOnBoard(int x, int y) { 35 if ( x<0 || 7<x || y<0 || 7<y) 36 return false; 37 else 38 return true; 39 } 40 41 //盤面(x,y)から方向dに向かって石を順番に取得 42 ArrayList<Integer> getLine(int x, int y, Point d) { 43 ArrayList<Integer> line = new ArrayList<Integer>(); 44 int cx = x + d.x; 45 int cy = y + d.y; 46 while ( isOnBoard(cx, cy) && ste[cx][cy].obverse > 0 ) { 47 line.add(ste[cx][cy].obverse); 48 cx += d.x; 49 cy += d.y; 50 } 51 return line; 52 } 53 54 55 //盤面(x,y)に石sを置いた場合に反転できる石の数を数える 56 int countReverseStone(int x, int y, int s) { 57 //既に石が置かれていたら、置けない 58 if (ste[x][y].obverse != 0) return -1; 59 //8方向をチェック 60 int cnt = 0; 61 for (int d=0; d<8; d++) { 62 ArrayList<Integer> line = new ArrayList<Integer>(); 63 line = getLine(x, y, direction[d]); 64 int n = 0; 65 while ( n < line.size() && line.get(n) != s) n++; 66 if (1 <= n && n < line.size()) cnt += n; 67 } 68 return cnt; 69 } 70 71 //石を置き他を反転させる 72 void setStoneAndReverse(int x, int y, int s) { 73 //8方向をチェック 74 for (int d=0; d<8; d++) { 75 ArrayList<Integer> p = new ArrayList<Integer>(); 76 p = getLine(x, y, direction[d]); 77 int cx = x; 78 int cy = y; 79 int n = 0; 80 while ( n < p.size()-1 && p.get(n) != s) { 81 cx += direction[d].x; 82 cy += direction[d].y; 83 System.out.println(d); 84 ste[cx][cy].doReverse(ste[cx][cy].obverse); 85 n++; 86 } 87 } 88 } 89 90 91 92 //盤面を見る 93 void evaluateBoard() 94 { 95 num_grid_black = 0; 96 num_grid_white = 0; 97 for ( int i=0; i<8; i++) { 98 for (int j=0; j<8; j++) { 99 eval_black[i][j] = countReverseStone(i, j, 1); 100 if (eval_black[i][j] > 0) num_grid_black++; 101 eval_white[i][j] = countReverseStone(i, j, 2); 102 if (eval_white[i][j] > 0) num_grid_white++; 103 } 104 } 105 } 106 107 108 //盤面をコンソールに表示する 109 void printBoard() { 110 for ( int i=0; i<8; i++) { 111 for (int j=0; j<8; j++) { 112 System.out.printf("%2d ", ste[j][i].obverse); 113 } 114 System.out.println(""); 115 } 116 } 117 118 //盤面の評価結果をコンソールに表示する 119 void printEval() { 120 System.out.println("Black(1):"); 121 for ( int i=0; i<8; i++) { 122 for ( int j=0; j<8; j++) { 123 System.out.printf("%2d " , eval_black[j][i]); 124 } 125 System.out.println(""); 126 } 127 System.out.println("White(2):"); 128 for ( int i=0; i<8; i++) { 129 for ( int j=0; j<8; j++) { 130 System.out.printf("%2d " , eval_white[j][i]); 131 } 132 System.out.println(""); 133 } 134 } 135 136 137 //画面描画 138 void paint(Graphics g, int unit_size) { 139 140 //背景 141 g.setColor(Color.black); 142 g.fillRect(0, 0, unit_size*10, unit_size*10); 143 144 //盤面 145 g.setColor(new Color(0, 85, 0)); 146 g.fillRect(unit_size, unit_size, unit_size*8, unit_size*8); 147 148 //横線 149 g.setColor(Color.black); 150 for (int i = 0; i<9 ; i++) { 151 g.drawLine(unit_size*(i+1), unit_size, unit_size*(i+1), unit_size*9 ); 152 } 153 154 //縦線 155 g.setColor(Color.black); 156 for (int i = 0; i<9 ; i++) { 157 g.drawLine(unit_size, unit_size*(i+1), unit_size*9, unit_size*(i+1) ); 158 } 159 160 // 目印 161 for (int i=0; i<2; i++) { 162 for (int j=0; j<2; j++) { 163 g.fillRect(unit_size*(3+4*i)-(unit_size/16), unit_size*(3+4*j)-(unit_size/16), (unit_size/8), (unit_size/8)); 164 } 165 } 166 167 //各マスの中心座標を計算した後描画 168 Point p = new Point(); 169 int rad = ((unit_size/2) * 4 ) / 5; 170 for(int i=0; i<8; i++) { 171 for(int j=0; j<8; j++) { 172 p.x = (unit_size*(i+1) + unit_size*(i+2))/2; 173 p.y = (unit_size*(j+1) + unit_size*(j+2))/2; 174 ste[i][j].paint(g, p, rad); 175 } 176 } 177 } 178 179 //クリックされたマス(x,y)に石sを配置する 180 void setStone(int x, int y, int s) { 181 ste[x][y].setObverse(s); 182 } 183}
退会済みユーザー👍を押しています

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2019/11/26 15:23

多分他にもあるけど一個だけ Board#getLine(int x, int y, Point d)でline.add(ste[cy][cx].obverse);してるところで、cyとcxが逆。
jimbe

2019/11/26 16:02

> 隣合う挟まれていない石まで反転されてしまいます ご自身でお調べになっていると思いますが, どこまで状況と追跡されているでしょうか. また, コードのご提示はファイル毎に分けて頂けると助かります.
退会済みユーザー

退会済みユーザー

2019/11/27 04:37

> また, コードのご提示はファイル毎に分けて頂けると助かります. ご指摘ありがとうございます。問題のありそうな箇所を絞りました。
swordone

2019/11/27 04:57 編集

勘違いでコメントしました。すみません。
退会済みユーザー

退会済みユーザー

2019/11/27 05:31

いろいろな方がいろいろな意見を持ってるので、参考までにという話ですが、個人的な好みだけ言うと、コードは動かした方が解析が楽なので、現象を再現できる全てのコードを載せてもらった方がいいですね。 (自分で見つけてほしかったので)もうコメントする気もなかったのですが、書いてしまったので、最初のコメントで書かなかった他に気になった点も書いておきます。 ・左クリックと右クリックで手番関係なく置けてしまうのが少し気になりました ・挟んでいる判定をする際に、敵色判定を抜けた後、最後が自色であることを確認してないコードがあったように思います
swordone

2019/11/27 18:34

「問題があると思われるソースコード」と「Boardクラス」それぞれに存在するsetStoneAndReverseメソッドの内容が異なるのですが、現状どちらなのですか? それから、その第3引数のsは石の色ということでいいのでしょうか?
退会済みユーザー

退会済みユーザー

2019/11/28 07:15

>それから、その第3引数のsは石の色ということでいいのでしょうか? 第3引数のSは石の色を表してます。 >「問題があると思われるソースコード」と「Boardクラス」それぞれに存在するsetStoneAndReverseメソッドの内容が異なるのですが、現状どちらなのですか? すみません、修正いたします。 「Boardクラス」の方が誤りです。
guest

回答3

0

まずは、ここ

java

1 line.add(ste[cy][cx].obverse);

は、こう

java

1 line.add(ste[cx][cy].obverse);

ですね。

あとは、順番に関係なく石を置けてしまう問題があります。
パスする処理も変です。

こちらで正常動作確認したソースコードです。

java

1import java.awt.*; 2import javax.swing.*; 3import java.awt.event.*; 4import java.util.*; 5 6class Stone { 7 public final static int black = 1; 8 public final static int white = 2; 9 public int obverse = 0; 10 11 Stone() { 12 obverse = 0; 13 } 14 15 void setObverse(int color) { 16 if (color == black || color == white) 17 obverse = color; 18 else 19 System.out.println("黒か白でなければいけません"); 20 } 21 22 void doReverse(int color) { 23 if (color == black) 24 obverse = white; 25 else if (color == white) 26 obverse = black; 27 else 28 System.out.println("黒か白でなければいけません"); 29 } 30 31 void paint(Graphics g, Point p, int rad) { 32 if (obverse == black) { 33 g.setColor(Color.black); 34 g.fillOval(p.x - 32, p.y - 32, 2 * rad, 2 * rad); 35 } else if (obverse == white) { 36 g.setColor(Color.white); 37 g.fillOval(p.x - 32, p.y - 32, 2 * rad, 2 * rad); 38 } 39 } 40} 41 42class Board { 43 Stone[][] ste = new Stone[8][8]; 44 public int num_grid_black; 45 public int num_grid_white; 46 private Point[] direction = new Point[8]; 47 public int[][] eval_black = new int[8][8]; 48 public int[][] eval_white = new int[8][8]; 49 50 Board() { 51 52 for (int x = 0; x < 8; x++) { 53 for (int y = 0; y < 8; y++) { 54 ste[x][y] = new Stone(); 55 } 56 } 57 ste[3][3].setObverse(1); 58 ste[3][4].setObverse(2); 59 ste[4][3].setObverse(2); 60 ste[4][4].setObverse(1); 61 62 direction[0] = new Point(1, 0); 63 direction[1] = new Point(1, 1); 64 direction[2] = new Point(0, 1); 65 direction[3] = new Point(-1, 1); 66 direction[4] = new Point(-1, 0); 67 direction[5] = new Point(-1, -1); 68 direction[6] = new Point(0, -1); 69 direction[7] = new Point(1, -1); 70 } 71 72 boolean isOnBoard(int x, int y) { 73 if (x < 0 || 7 < x || y < 0 || 7 < y) 74 return false; 75 else 76 return true; 77 } 78 79 ArrayList<Integer> getLine(int x, int y, Point d) { 80 ArrayList<Integer> line = new ArrayList<Integer>(); 81 int cx = x + d.x; 82 int cy = y + d.y; 83 while (isOnBoard(cx, cy) && ste[cx][cy].obverse != 0) { 84 line.add(ste[cx][cy].obverse); 85 cx += d.x; 86 cy += d.y; 87 } 88 return line; 89 } 90 91 int countReverseStone(int x, int y, int s) { 92 if (ste[x][y].obverse != 0) 93 return -1; 94 int cnt = 0; 95 for (int d = 0; d < 8; d++) { 96 ArrayList<Integer> line = new ArrayList<Integer>(); 97 line = getLine(x, y, direction[d]); 98 int n = 0; 99 while (n < line.size() && line.get(n) != s) 100 n++; 101 if (1 <= n && n < line.size()) 102 cnt += n; 103 } 104 return cnt; 105 } 106 107 void setStoneAndReverse(int x, int y, int s) { 108 for (int d = 0; d < 8; d++) { 109 ArrayList<Integer> p = new ArrayList<Integer>(); 110 p = getLine(x, y, direction[d]); 111 int cx = x; 112 int cy = y; 113 int n = 0; 114 115 while (n < p.size() - 1 && p.get(n) != s && ste[cx][cy].obverse == s) { 116 cx += direction[d].x; 117 cy += direction[d].y; 118 System.out.println(d); 119 System.out.println("cx=" + cx); 120 System.out.println("cy=" + cy); 121 ste[cx][cy].doReverse(ste[cx][cy].obverse); 122 n++; 123 } 124 } 125 } 126 127 void evaluateBoard() { 128 num_grid_black = 0; 129 num_grid_white = 0; 130 for (int i = 0; i < 8; i++) { 131 for (int j = 0; j < 8; j++) { 132 eval_black[i][j] = countReverseStone(i, j, 1); 133 if (eval_black[i][j] > 0) 134 num_grid_black++; 135 eval_white[i][j] = countReverseStone(i, j, 2); 136 if (eval_white[i][j] > 0) 137 num_grid_white++; 138 } 139 } 140 } 141 142 void printBoard() { 143 for (int y = 0; y < 8; y++) { 144 for (int x = 0; x < 8; x++) { 145 System.out.printf("%2d ", ste[x][y].obverse); 146 } 147 System.out.println(""); 148 } 149 } 150 151 void printEval() { 152 System.out.println("Black(1):"); 153 for (int i = 0; i < 8; i++) { 154 for (int j = 0; j < 8; j++) { 155 System.out.printf("%2d ", eval_black[j][i]); 156 } 157 System.out.println(""); 158 } 159 System.out.println("White(2):"); 160 for (int i = 0; i < 8; i++) { 161 for (int j = 0; j < 8; j++) { 162 System.out.printf("%2d ", eval_white[j][i]); 163 } 164 System.out.println(""); 165 } 166 } 167 168 void paint(Graphics g, int unit_size) { 169 170 g.setColor(Color.black); 171 g.fillRect(0, 0, unit_size * 10, unit_size * 10); 172 173 g.setColor(new Color(0, 85, 0)); 174 g.fillRect(unit_size, unit_size, unit_size * 8, unit_size * 8); 175 176 g.setColor(Color.black); 177 for (int i = 0; i < 9; i++) { 178 g.drawLine(unit_size * (i + 1), unit_size, unit_size * (i + 1), unit_size * 9); 179 } 180 181 g.setColor(Color.black); 182 for (int i = 0; i < 9; i++) { 183 g.drawLine(unit_size, unit_size * (i + 1), unit_size * 9, unit_size * (i + 1)); 184 } 185 186 for (int i = 0; i < 2; i++) { 187 for (int j = 0; j < 2; j++) { 188 g.fillRect(unit_size * (3 + 4 * i) - (unit_size / 16), unit_size * (3 + 4 * j) - (unit_size / 16), 189 (unit_size / 8), (unit_size / 8)); 190 } 191 } 192 193 Point p = new Point(); 194 int rad = ((unit_size / 2) * 4) / 5; 195 for (int x = 0; x < 8; x++) { 196 for (int y = 0; y < 8; y++) { 197 p.x = (unit_size * (x + 1) + unit_size * (x + 2)) / 2; 198 p.y = (unit_size * (y + 1) + unit_size * (y + 2)) / 2; 199 ste[x][y].paint(g, p, rad); 200 } 201 } 202 } 203 204 void setStone(int x, int y, int s) { 205 ste[x][y].setObverse(s); 206 } 207} 208 209public class Reversi extends JPanel { 210 private final static int UNIT_SIZE = 80; 211 private Board board = new Board(); 212 213 private int turn = 1; 214 215 public Reversi() { 216 setPreferredSize(new Dimension(800, 800)); 217 addMouseListener(new MouseProc()); 218 } 219 220 public void paintComponent(Graphics g) { 221 board.paint(g, UNIT_SIZE); 222 } 223 224 void changeTurn() { 225 if (turn == 1) 226 turn = 2; 227 else if (turn == 2) 228 turn = 1; 229 } 230 231 void MessageDialog(String str) { 232 JOptionPane.showMessageDialog(this, str, "情報", JOptionPane.INFORMATION_MESSAGE); 233 } 234 235 void EndMessageDialog(int num_black, int num_white) { 236 if (num_black > num_white) { 237 String str = "[黒:" + num_black + ",白:" + num_white + "]で黒の勝ち"; 238 JOptionPane.showMessageDialog(this, str, "ゲーム終了", JOptionPane.INFORMATION_MESSAGE); 239 } else if (num_black == num_white) { 240 String str = "[黒:" + num_black + ",白:" + num_white + "]で引き分け"; 241 JOptionPane.showMessageDialog(this, str, "ゲーム終了", JOptionPane.INFORMATION_MESSAGE); 242 } else { 243 String str = "[黒:" + num_black + ",白:" + num_white + "]で白の勝ち"; 244 JOptionPane.showMessageDialog(this, str, "ゲーム終了", JOptionPane.INFORMATION_MESSAGE); 245 } 246 247 System.exit(0); 248 } 249 250 class MouseProc extends MouseAdapter { 251 public void mouseClicked(MouseEvent me) { 252 Point point = me.getPoint(); 253 int btn = me.getButton(); 254 System.out.println("(" + point.x + "," + point.y + ")"); 255 board.evaluateBoard(); 256 if (turn == 1 && btn == MouseEvent.BUTTON1) { 257 int x = point.x / UNIT_SIZE - 1; 258 int y = point.y / UNIT_SIZE - 1; 259 System.out.println("[" + x + "]" + "[" + y + "]"); 260 if (0 <= x && x < 8 && 0 <= y && y < 8) { 261 if (board.eval_black[x][y] < 1) { 262 System.out.println("そこに石を置けません"); 263 } else { 264 board.setStone(x, y, 1); 265 board.setStoneAndReverse(x, y, 1); 266 repaint(); 267 board.printBoard(); 268 board.evaluateBoard(); 269 board.printEval(); 270 changeTurn(); 271 if (board.num_grid_black >= 1) { 272 MessageDialog("白の番です"); 273 } else { 274 changeTurn(); 275 MessageDialog("あなたはパスです"); 276 } 277 } 278 } 279 } else if (turn == 2 && btn == MouseEvent.BUTTON3) { 280 int x = point.x / UNIT_SIZE - 1; 281 int y = point.y / UNIT_SIZE - 1; 282 System.out.println("[" + x + "]" + "[" + y + "]"); 283 if (0 <= x && x < 8 && 0 <= y && y < 8) { 284 if (board.eval_white[x][y] < 1) { 285 System.out.println("そこに石を置けません"); 286 } else { 287 board.setStone(x, y, 2); 288 board.setStoneAndReverse(x, y, 2); 289 repaint(); 290 board.printBoard(); 291 board.evaluateBoard(); 292 board.printEval(); 293 changeTurn(); 294 if (board.num_grid_black >= 1) { 295 MessageDialog("黒の番です"); 296 } else { 297 changeTurn(); 298 MessageDialog("あなたはパスです"); 299 } 300 } 301 } 302 } 303 304 int num_black = 0; 305 int num_white = 0; 306 for (int x = 0; x < 8; x++) { 307 for (int y = 0; y < 8; y++) { 308 if (board.ste[x][y].obverse == 1) 309 num_black++; 310 if (board.ste[x][y].obverse == 2) 311 num_white++; 312 } 313 } 314 315 if (board.num_grid_black < 1 && board.num_grid_white < 1) { 316 EndMessageDialog(num_black, num_white); 317 } 318 } 319 } 320 321 public static void main(String[] args) { 322 JFrame f = new JFrame(); 323 324 f.getContentPane().setLayout(new FlowLayout()); 325 f.getContentPane().add(new Reversi()); 326 f.pack(); 327 f.setResizable(false); 328 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 329 f.setVisible(true); 330 } 331}

投稿2019/11/26 16:09

編集2019/11/27 17:24
shiracamus

総合スコア5406

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

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

退会済みユーザー

退会済みユーザー

2019/11/27 04:34

ご指摘ありがとうございます。 指定カ所を更新いたしました。
shiracamus

2019/11/27 04:58

解決しませんか?
退会済みユーザー

退会済みユーザー

2019/11/27 05:24

解決しないですね…
shiracamus

2019/11/27 05:46

*.class ファイルを全部削除して、再コンパイルしてみてはいかがでしょう?
shiracamus

2019/11/27 05:48

動くようになったコードが自宅にあるので、帰宅したら修正ソースを添付します。
shiracamus

2019/11/27 17:26 編集

こちらで動作確認したソースコードを回答欄に追記しました。 文字数が多いと言われてしまったため、コメントをすべて削除してあります。
退会済みユーザー

退会済みユーザー

2019/11/28 09:00 編集

追記ありがとうございます。 しかし、書いていただいたコードでも同じような問題が生じてしまいます…
guest

0

ベストアンサー

「現在のターンの石では無い石があるか」は見ていますが, その先に現在のターンの石があるか, つまり ”挟んでいるか” という判定になっていないのではないでしょうか.

二つのメソッドを修正してみました.

java

1 //盤面(x,y)に石sを置いた場合に反転できる石の数を数える 2 int countReverseStone(int x, int y, int s) { 3 //既に石が置かれていたら、置けない 4 if(ste[x][y].obverse != 0) 5 return -1; 6 //8方向をチェック 7 int cnt = 0; 8 for(int d = 0; d < 8; d++) { 9 ArrayList<Integer> line = new ArrayList<Integer>(); 10 line = getLine(x, y, direction[d]); 11 //int n = 0; 12 //while(n < line.size() && line.get(n) != s) n++; 13 //if(1 <= n && n < line.size()) cnt += n; 14 int n = line.indexOf(s); 15 if(n > 0) cnt += n; 16 } 17 return cnt; 18 } 19 20 //石を置き他を反転させる 21 void setStoneAndReverse(int x, int y, int s) { 22 //8方向をチェック 23 for(int d = 0; d < 8; d++) { 24 ArrayList<Integer> p = getLine(x, y, direction[d]); 25 int cx = x; 26 int cy = y; 27 int n = 0; 28 //while(n < p.size() - 1 && p.get(n) != s) { 29 while(n < p.indexOf(s)) { 30 cx += direction[d].x; 31 cy += direction[d].y; 32 System.out.println(d); 33 ste[cx][cy].doReverse(ste[cx][cy].obverse); 34 n++; 35 } 36 } 37 }

投稿2019/11/28 08:47

編集2019/11/28 10:00
jimbe

総合スコア13204

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

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

退会済みユーザー

退会済みユーザー

2019/11/28 08:58

そうですね。 ”挟んでいるか”を判定をしていないですね…
退会済みユーザー

退会済みユーザー

2019/11/28 09:18

修正したところ問題無く動きました。 ありがとうございます!
jimbe

2019/11/28 10:02

countReverseStone のほうの修正を for ループから indexOf に変更しました.
guest

0

回答ではないですが、少しリファクタリングしてみました。
まだリファクタリングできるところはあると思います。

java

1import java.util.*; 2import java.util.stream.*; 3import java.awt.*; 4import java.awt.Point; 5import java.awt.event.*; 6import javax.swing.*; 7 8interface Disk { 9 public void paint(Graphics g, Point p, int size); 10 public String toString(); 11} 12 13class Disks { 14 static final Disk NONE, BLACK, WHITE; 15 16 static { 17 NONE = new Disk() { 18 public void paint(Graphics g, Point p, int size) { 19 } 20 21 public String toString() { 22 return "□"; 23 } 24 }; 25 26 BLACK = new Disk() { 27 public void paint(Graphics g, Point p, int size) { 28 int r = (size / 2) * 4 / 5; 29 g.setColor(Color.black); 30 g.fillOval(p.x - r, p.y - r, r * 2, r * 2); 31 } 32 33 public String toString() { 34 return "×"; 35 } 36 }; 37 38 WHITE = new Disk() { 39 public void paint(Graphics g, Point p, int size) { 40 int r = (size / 2) * 4 / 5; 41 g.setColor(Color.white); 42 g.fillOval(p.x - r, p.y - r, r * 2, r * 2); 43 } 44 45 public String toString() { 46 return "●"; 47 } 48 }; 49 } 50 51 private static final Map<Disk, Disk> OPPOSITE = new HashMap<Disk, Disk>() { 52 { 53 put(NONE, NONE); 54 put(BLACK, WHITE); 55 put(WHITE, BLACK); 56 } 57 }; 58 59 static Disk opposite(Disk disk) { 60 return OPPOSITE.get(disk); 61 } 62} 63 64class Square { 65 private Disk disk; 66 67 Square() { 68 this.disk = Disks.NONE; 69 } 70 71 boolean is_used() { 72 return this.disk != Disks.NONE; 73 } 74 75 boolean is(Disk disk) { 76 return this.disk == disk; 77 } 78 79 void put(Disk disk) { 80 this.disk = disk; 81 } 82 83 void reverse() { 84 this.disk = Disks.opposite(this.disk); 85 } 86 87 void paint(Graphics g, Point p, int size) { 88 disk.paint(g, p, size); 89 } 90 91 public String toString() { 92 return disk.toString(); 93 } 94} 95 96class Board { 97 final Square[][] squares = new Square[8][8]; 98 final int[][] eval_black = new int[8][8]; 99 final int[][] eval_white = new int[8][8]; 100 101 private static final Color COLOR = new Color(0, 85, 0); 102 private static final Point[] DIRECTION = { 103 new Point(-1, -1), 104 new Point( 0, -1), 105 new Point( 1, -1), 106 new Point(-1, 0), 107 new Point( 1, 0), 108 new Point(-1, 1), 109 new Point( 0, 1), 110 new Point( 1, 1), 111 }; 112 113 Board() { 114 for (int x = 0; x < 8; x++) { 115 for (int y = 0; y < 8; y++) { 116 squares[x][y] = new Square(); 117 } 118 } 119 squares[3][3].put(Disks.WHITE); 120 squares[4][3].put(Disks.BLACK); 121 squares[3][4].put(Disks.BLACK); 122 squares[4][4].put(Disks.WHITE); 123 } 124 125 boolean isOnBoard(int x, int y) { 126 return 0 <= x && x < 8 && 0 <= y && y < 8; 127 } 128 129 long count(Disk disk) { 130 return Arrays.stream(squares) 131 .flatMap(Stream::of) 132 .filter(m -> m.is(disk)) 133 .count(); 134 } 135 136 class Reversible { 137 final ArrayList<Point> points = new ArrayList<Point>(); 138 139 void add(Point point) { 140 points.add(point); 141 } 142 143 void removeAll() { 144 points.clear(); 145 } 146 147 int count() { 148 return points.size(); 149 } 150 151 void reverse() { 152 for (Point p: points) { 153 squares[p.x][p.y].reverse(); 154 } 155 } 156 } 157 158 Reversible getReversible(int x, int y, Point d, Disk s) { 159 Reversible reversible = new Reversible(); 160 Disk opposite = Disks.opposite(s); 161 x += d.x; 162 y += d.y; 163 while (isOnBoard(x, y) && squares[x][y].is(opposite)) { 164 reversible.add(new Point(x, y)); 165 x += d.x; 166 y += d.y; 167 } 168 if (!(isOnBoard(x, y) && squares[x][y].is(s))) 169 reversible.removeAll(); 170 return reversible; 171 } 172 173 int countReversible(int x, int y, Disk s) { 174 if (squares[x][y].is_used()) 175 return -1; 176 177 return Arrays.stream(DIRECTION) 178 .mapToInt(d -> getReversible(x, y, d, s).count()) 179 .sum(); 180 } 181 182 void putAndReverse(int x, int y, Disk s) { 183 squares[x][y].put(s); 184 Arrays.stream(DIRECTION).forEach(d -> getReversible(x, y, d, s).reverse()); 185 } 186 187 void evaluate() { 188 for (int x = 0; x < 8; x++) { 189 for (int y = 0; y < 8; y++) { 190 eval_black[x][y] = countReversible(x, y, Disks.BLACK); 191 eval_white[x][y] = countReversible(x, y, Disks.WHITE); 192 } 193 } 194 } 195 196 void printBoard() { 197 for (int y = 0; y < 8; y++) { 198 for (int x = 0; x < 8; x++) { 199 System.out.printf("%s ", squares[x][y]); 200 } 201 System.out.println(); 202 } 203 } 204 205 void printEvaluation() { 206 System.out.println("Black(" + Disks.BLACK + "):"); 207 for (int y = 0; y < 8; y++) { 208 for (int x = 0; x < 8; x++) { 209 System.out.printf("%2d ", eval_black[x][y]); 210 } 211 System.out.println(); 212 } 213 System.out.println("White(" + Disks.WHITE + "):"); 214 for (int y = 0; y < 8; y++) { 215 for (int x = 0; x < 8; x++) { 216 System.out.printf("%2d ", eval_white[x][y]); 217 } 218 System.out.println(); 219 } 220 } 221 222 void paint(Graphics g, int square_size) { 223 224 // Background 225 g.setColor(Color.black); 226 g.fillRect(0, 0, square_size * 10, square_size * 10); 227 228 // Board 229 g.setColor(Board.COLOR); 230 g.fillRect(square_size, square_size, square_size * 8, square_size * 8); 231 232 // Horizontal Line 233 g.setColor(Color.black); 234 for (int x = 0; x < 9; x++) { 235 g.drawLine(square_size * (x + 1), square_size, square_size * (x + 1), square_size * 9); 236 } 237 238 // Vertical Line 239 g.setColor(Color.black); 240 for (int y = 0; y < 9; y++) { 241 g.drawLine(square_size, square_size * (y + 1), square_size * 9, square_size * (y + 1)); 242 } 243 244 // Dots 245 for (int x = 0; x < 2; x++) { 246 for (int y = 0; y < 2; y++) { 247 g.fillRect(square_size * (3 + 4 * x) - (square_size / 16), 248 square_size * (3 + 4 * y) - (square_size / 16), 249 square_size / 8, 250 square_size / 8); 251 } 252 } 253 254 // Disk 255 Point p = new Point(); 256 for (int x = 0; x < 8; x++) { 257 for (int y = 0; y < 8; y++) { 258 p.x = square_size * (x + 1) + square_size / 2; 259 p.y = square_size * (y + 1) + square_size / 2; 260 squares[x][y].paint(g, p, square_size); 261 } 262 } 263 } 264} 265 266class Player { 267 private final String name; 268 private final Disk disk; 269 private final int[][] reversible; 270 271 Player(String name, Disk disk, int[][] reversible) { 272 this.name = name; 273 this.disk = disk; 274 this.reversible = reversible; 275 } 276 277 public String toString() { 278 return name; 279 } 280 281 boolean putable(Board board, int x, int y) { 282 return reversible[x][y] >= 1; 283 } 284 285 void putAndReverse(Board board, int x, int y) { 286 board.putAndReverse(x, y, disk); 287 } 288 289 long count(Board board) { 290 return board.count(disk); 291 } 292 293 boolean pass() { 294 for (int[] row: reversible) { 295 for (int n: row) { 296 if (n >= 1) 297 return false; 298 } 299 } 300 return true; 301 } 302} 303 304public class Reversi extends JPanel { 305 private static final int SQUARE_SIZE = 80; 306 private final Board board = new Board(); 307 private final Player player1 = new Player("黒", Disks.BLACK, board.eval_black); 308 private final Player player2 = new Player("白", Disks.WHITE, board.eval_white); 309 private Player player = player1; 310 311 public Reversi() { 312 setPreferredSize(new Dimension(800, 800)); 313 addMouseListener(new MouseHandler()); 314 } 315 316 void turnPlayer() { 317 player = player == player1 ? player2 : player1; 318 } 319 320 public void paintComponent(Graphics g) { 321 board.paint(g, SQUARE_SIZE); 322 } 323 324 void showMessage(String message, String title) { 325 JOptionPane.showMessageDialog(this, message, title, JOptionPane.INFORMATION_MESSAGE); 326 } 327 328 void showMessage(String message) { 329 showMessage(message, "情報"); 330 } 331 332 void endGameAndExit() { 333 long num_player1 = player1.count(board); 334 long num_player2 = player2.count(board); 335 String message = "[" 336 + player1 + ":" + num_player1 + "," 337 + player2 + ":" + num_player2 + "]で"; 338 if (num_player1 > num_player2) { 339 message += player1 + "の勝ち"; 340 } else if (num_player1 <= num_player2) { 341 message += player2 + "の勝ち"; 342 } else { 343 message += "引き分け"; 344 } 345 showMessage(message, "ゲーム終了"); 346 347 System.exit(0); 348 } 349 350 class MouseHandler extends MouseAdapter { 351 public void mouseClicked(MouseEvent me) { 352 board.printBoard(); 353 Point point = me.getPoint(); 354 System.out.println("(" + point.x + "," + point.y + ")"); 355 int x = point.x / SQUARE_SIZE - 1; 356 int y = point.y / SQUARE_SIZE - 1; 357 if (!(0 <= x && x < 8 && 0 <= y && y < 8)) return; 358 System.out.println("[" + x + "]" + "[" + y + "]"); 359 int btn = me.getButton(); 360 if (player == player1 && btn == MouseEvent.BUTTON1 || 361 player == player2 && btn == MouseEvent.BUTTON3) { 362 put(x, y); 363 } 364 } 365 } 366 367 void put(int x, int y) { 368 board.evaluate(); 369 if (!player.putable(board, x, y)) { 370 System.out.println("そこに石を置けません"); 371 return; 372 } 373 player.putAndReverse(board, x, y); 374 repaint(); 375 board.printBoard(); 376 board.evaluate(); 377 board.printEvaluation(); 378 379 if (player1.pass() && player2.pass()) { 380 endGameAndExit(); 381 } 382 turnPlayer(); 383 if (player.pass()) { 384 showMessage(player + "はパスです"); 385 turnPlayer(); 386 } 387 showMessage(player + "の番です"); 388 } 389 390 public static void main(String[] args) { 391 JFrame f = new JFrame(); 392 f.getContentPane().setLayout(new FlowLayout()); 393 f.getContentPane().add(new Reversi()); 394 f.pack(); 395 f.setResizable(false); 396 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 397 f.setVisible(true); 398 } 399}

投稿2019/11/27 20:28

編集2019/11/28 03:28
shiracamus

総合スコア5406

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

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

退会済みユーザー

退会済みユーザー

2019/11/28 09:01

こちらのソースコードでは特に問題無く機能しておりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問