リバーシで8方向の処理をまとめる&置ける場所の表示

スポンサーリンク
スポンサーリンク


いろんなサイトを参考にしつつ、なんとなく頭の中にはできてきたので、サクサクいくかなぁと思ったらそんなことはなく、やたら手間取ってやっとできた。なんか色々あったけど全部は覚えてないのでさらっと書いとく。

スポンサーリンク

8方向の処理をまとめる

CheckFlip**()を分割する

石を置けるかどうかの処理とそれを元に引っ繰り返す処理が一緒になっているので、それを分けた。

checkCanFlip()

public void checkCanFlip(TextView tv){
    int di;
    int taptag = Integer.parseInt(tv.getTag().toString());
    TextView ttv;
    int StoneColor;

    for(int d = 0 ; d <= 7 ; d++){
        di = MoveQuantity[d];

        for(int c = 1 ; c <= 8 ; c ++) {
            ttv = parentView.findViewWithTag(String.format("%02d",taptag + (c * di)));

            if(ttv == null) {
                canFlip[d] = false;
                break;
            }

            if (!existStone(ttv)) {
                canFlip[d] = false;
                break;
            }

            StoneColor = getStoneColor(ttv);

            if (PlayerTurn == StoneColor && StoneCount[d] < 1) {
                canFlip[d] = false;
                break;
            }

            if (PlayerTurn != StoneColor) {
                StoneCount[d]++;
                continue ;
            }

            if (PlayerTurn == StoneColor) {
                canFlip[d] = true;
                break;
            }
        }
    }
}
オセロプログラム ~7行のC言語で書くコンピュータ対局~
このサイトでは、C言語でのオセロ(リバーシ)のプログラム開発方法を解りやすく説明しています。初級者、初心者でも作れるオセロ実装のコツ

こちらのサイトがすごく参考になった。ここまできれいには書けないけど、8方向の移動量を配列で持っておくっていうのがすごい。かっこいい。

  • MoveQuantity[]→方向ごとの移動量
  • StoneCount[]→方向ごとのひっくり返せる石の数
  • canFlip[]→方向ごとにひっくり返せるならtrue

としてばーっと8方向チェックする。上記3つはメンバ変数なので次の引っ繰り返す処理でも使える。

上端に来た時、getTag()すると”01″のはずが”1″になったりとint型にした弊害が出たのでString.formatで0埋めした。使い方がよく分かんなかった、特に引数が。のでコピペ。でも怒られる。怒られる内容がよくわかってなかったり。

for文も1方向ずつのコードからほぼ流用できたけど、return, break, continueの使い方がこんがらがり、1回1回ステップインしながら置き換えて確かめていった。大変だった。。。

引っ繰り返す処理を作る

public void FlipStone(TextView tv){
    int di;
    int taptag = Integer.parseInt(tv.getTag().toString());
    TextView ttv;

    for(int d = 0 ; d <= 7 ; d++) {
        di = MoveQuantity[d];

        if(canFlip[d]){
            setStoneToCell(tv);

            for(int c = 1 ; c <= StoneCount[d] ; c++){
                ttv = parentView.findViewWithTag(String.format("%02d",taptag + (c * di)));
                setStoneToCell(ttv);
            }
        }
    }

    canFlip = new boolean[]{false, false, false, false, false, false, false, false};
    StoneCount = new int[]{0,0,0,0,0,0,0,0};
}

上で使った3つの変数を元に、石をひっくり返していく。実際for文で回したり、使ってる変数は同じなんだけど、ここを分けとかないと次の置き石の表示でcheckcanflipを使い回せないと思ったので。最初、処理の最後で配列を初期化してなくて、置くごとにえらい場所に置き石可能の表示が出てた。

スポンサーリンク

置ける場所の表示

この前作ったCellArrayを使ってマスを全部検査していく。思ったんだけど、別にCellArray作んなくても、findViewWithTagで回しても別に良かったんじゃ…。どっちのが楽なんだろ。ていうか最初にちゃんと方針を決めて自分に分かりやすいように作っていってないのが悪いんだろうな。やっぱりあれが必要、とか、これいらなかった、とかが多いので、自分でも把握ができなくなってしまいます。

scanBoard()

この名前の関数はTextView達を配列にぶっこむ関数だったけど、そっちはmakeCellArrayに名前変えて、こっちでこの名前を利用することにした。

public void scanBoard(){

    for(TextView[] cc : CellArray){
        for(TextView c : cc) {
            if(existStone(c)){

            }else{
                checkCanFlip(c);

                for (boolean b : canFlip) {
                    if (b) {
                        c.setText("*");
                        break;
                    } else {
                        c.setText("");
                    }
                }
                canFlip = new boolean[]{false, false, false, false, false, false, false, false};
                StoneCount = new int[]{0, 0, 0, 0, 0, 0, 0, 0};
            }
        }
    }
}

ここに来るまでが長かった。これ作ってる間に、checkcanflipの不具合が見つかったりして、どっちがダメなのか分かんなくなった。置ける場所には「*」を表示することにした。

その前は

c.setBackgroundColor(Color.rgb(150, 255, 170));

こんな感じで色を付けようとしていたんだけど、色を付けると枠線が消えた。

こんな。

枠線はもう完全に理解しないでコピペしてきてるので、直し方も分からず。調べる気も起きず。なので「*」にした。それによって(“”)で判定していた部分、existStone()とか、に支障が出たので、「*」の場合も空白扱いにするようにコード変えた。これは3ヶ所ぐらいだったので助かった。

ここまで

書いた以外にも細かい所でいっぱい引っかかってるんだけど、書くのがめんどい。

あ、あとforとかifがなんだか深くなってしまうな。解消したいけど、そこまで頭が回らない…。

置き石可能かの表示ができたので、こっから「そこには置けません」のトーストと、パス機能に広げられるんじゃないかなと思ってる。やっぱり頭の中で考えるのと、実際書くんじゃ大違いだなぁ。頑張っていっぱい考えたけど、思い通りに動かないこと山の如し、先が思いやられるぞ。でもやっぱ完成させたい気持ちのほうがあるかな。うまくいくといいなぁ。

参考

Java:ゼロ埋め、半角スペース埋めする方法 - 覚え書き.com
Javaで「String.format」メソッドを使用して、数値をゼロパディング(ゼロ埋め)したり、文字列へ半
配列
変数には 1 つの値を保管することができますが、配列は同じデータ型の複数の値をまとめて保管・管理することができます。例えば 10 個の値を保存する場合、変数を使う場合は変数が 10 個必要ですが、配列では 10 個の要素を持つ 1 つの配列...
404 File Not Found

コメント

タイトルとURLをコピーしました