前提・実現したいこと
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}
多分他にもあるけど一個だけ
Board#getLine(int x, int y, Point d)でline.add(ste[cy][cx].obverse);してるところで、cyとcxが逆。
> 隣合う挟まれていない石まで反転されてしまいます
ご自身でお調べになっていると思いますが, どこまで状況と追跡されているでしょうか.
また, コードのご提示はファイル毎に分けて頂けると助かります.
> また, コードのご提示はファイル毎に分けて頂けると助かります.
ご指摘ありがとうございます。問題のありそうな箇所を絞りました。
勘違いでコメントしました。すみません。
いろいろな方がいろいろな意見を持ってるので、参考までにという話ですが、個人的な好みだけ言うと、コードは動かした方が解析が楽なので、現象を再現できる全てのコードを載せてもらった方がいいですね。
(自分で見つけてほしかったので)もうコメントする気もなかったのですが、書いてしまったので、最初のコメントで書かなかった他に気になった点も書いておきます。
・左クリックと右クリックで手番関係なく置けてしまうのが少し気になりました
・挟んでいる判定をする際に、敵色判定を抜けた後、最後が自色であることを確認してないコードがあったように思います
「問題があると思われるソースコード」と「Boardクラス」それぞれに存在するsetStoneAndReverseメソッドの内容が異なるのですが、現状どちらなのですか?
それから、その第3引数のsは石の色ということでいいのでしょうか?
>それから、その第3引数のsは石の色ということでいいのでしょうか?
第3引数のSは石の色を表してます。
>「問題があると思われるソースコード」と「Boardクラス」それぞれに存在するsetStoneAndReverseメソッドの内容が異なるのですが、現状どちらなのですか?
すみません、修正いたします。
「Boardクラス」の方が誤りです。
回答3件
あなたの回答
tips
プレビュー