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

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

ただいまの
回答率

88.05%

Java オセロ隣接しているところに置く事と勝敗判定

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 911
退会済みユーザー

退会済みユーザー

課題で出た基礎的なコードを応用しているため、とても遠回りなコードになっていると思われます。

javaでオセロを作っているのですが、隣接されているところ以外も駒が置けるようになってしまっています。
どのようにすれば隣接しているところだけ置けるようにすることができるでしょうか?
また、最終的に駒数を数えて勝敗を判定したいのですが、どのようなアプローチをすればよいでしょうか?

今回が初めての質問ゆえに、至らぬところがあるかもしれませんがよろしくお願いします。

package b132;

import java.util.Scanner;

public class MyClass {

    static int BOARD_SIZE = 8;
    static String[] STONE_STR = {"□", "●", "○"};
    static int[][] board = new int[BOARD_SIZE][BOARD_SIZE];

    // 盤面の表示
    static void print_board() {
        System.out.print("  ");
        for(int j = 1; j <= board[0].length; j++) {
            System.out.printf("%2d", j);
        }
        System.out.println("");  // 改行のみ
        for(int i = 0; i < board.length; i++) {
            System.out.print((i + 1) + " ");
            for(int j = 0; j < board[i].length; j++) {
                System.out.print(STONE_STR[board[i][j]]);
            }
            System.out.println("");  // 改行のみ
        }

    }

    // 入力位置が盤面の外かどうかを判定
    static boolean is_out_board(int num_v, int num_h) {
        if((num_v < 0) || (num_v >= BOARD_SIZE) || (num_h < 0) || (num_h >= BOARD_SIZE)) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        int num_v, num_h;
        int num_hand = 1;                //手数
        int num_play = 1;

        Scanner scan = new Scanner(System.in);
        //初期位置の設定
        board[3][4] = 1;
        board[4][3] = 1;
        board[3][3] = 2;
        board[4][4] = 2;

        print_board();
        while(true) {
            System.out.println(STONE_STR[num_play] + "の番です");
            System.out.println("どこに置きますか?(" + num_hand + "手目)");
            System.out.print("縦:");
            num_v = scan.nextInt() - 1;
            System.out.print("横:");
            num_h = scan.nextInt() - 1;
            System.out.println("");  // 改行のみ

            // 位置が縦横ともに負の値の場合は終了
            if((num_v == -1) && (num_h == -1)) {
                System.out.println("終了します");
                break;
            }
            // 盤面の外には置けない
            if(is_out_board(num_v, num_h)) {
                System.out.println("そこには置けません");
                continue;
            }
            // 石を置く
            if(STONE_STR[board[num_v][num_h]].equals("□")) {
            board[num_v][num_h] = num_play;
            //左上の判定
            if(num_v > 1 && num_h >1) {
            if(board[num_v-1][num_h-1] != num_play) {
                for(int i = 2; true; i++) {
                    //駒がないとき
                    if(num_v - i < 0 || num_h -i < 0 || STONE_STR[board[num_v- i][num_h - i]].equals("□")) {
                    break;
                    }//自分の駒のとき
                    else if (board[num_v-i][num_h-i] == num_play) {
                    //ひっくり返す
                    for(int j = 1; j < i; j++) {
                        board[num_v -j][num_h -j] = num_play;
                    }
                    break;
                }
            }
        }
            }
            //真上の判定
            if(num_v >1) {
            if(board[num_v-1][num_h] != num_play) {
                for(int i = 2; true; i++) {
                    //駒がないとき
                    if(num_v - i < 0  || STONE_STR[board[num_v- i][num_h]].equals("□")) {
                    break;
                    }//自分の駒のとき
                    else if (board[num_v-i][num_h] == num_play) {
                    //ひっくり返す
                    for(int j = 1; j < i; j++) {
                        board[num_v -j][num_h] = num_play;
                    }
                    break;
                }
            }
        }
            }
            //右上の判定
            if(num_v >1 && num_h < 6) {
            if(board[num_v-1][num_h+1] != num_play) {
                for(int i = 2; true; i++) {
                    //駒がないとき
                    if(num_v - i < 0 || num_h + i > 7 || STONE_STR[board[num_v- i][num_h + i]].equals("□")) {
                    break;
                    }//自分の駒のとき
                    else if (board[num_v-i][num_h+i] == num_play) {
                    //ひっくり返す
                    for(int j = 1; j < i; j++) {
                        board[num_v -j][num_h + j] = num_play;
                    }
                    break;
                }
            }
        }    
            }
            //右の判定
            if(num_h <6) {
            if(board[num_v][num_h+1] != num_play) {
                for(int i = 2; true; i++) {
                    //駒がないとき
                    if(num_h + i > 7 || STONE_STR[board[num_v][num_h + i]].equals("□")) {
                    break;
                    }//自分の駒のとき
                        else if (board[num_v][num_h+i] == num_play) {
                    //ひっくり返す
                            for(int j = 1; j < i; j++) {
                                board[num_v][num_h + j] = num_play;
                    }
                    break;
                }
            }
        }
            }
            //右下の判定
            if(num_v <6 && num_h <6) {
            if(board[num_v+1][num_h+1] != num_play) {
                for(int i = 2; true; i++) {
                    //駒がないとき
                    if(num_v + i > 7 || num_h + i > 7 || STONE_STR[board[num_v + i][num_h + i]].equals("□")) {
                    break;
                    }//自分の駒のとき
                        else if (board[num_v+i][num_h+i] == num_play) {
                    //ひっくり返す
                            for(int j = 1; j < i; j++) {
                                board[num_v +j][num_h + j] = num_play;
                    }
                    break;
                }
            }
        }
            }
            //真下の判定
            if (num_v <6) {
            if(board[num_v+1][num_h] != num_play) {
                for(int i = 2; true; i++) {
                    //駒がないとき
                    if(num_v + i > 7 || STONE_STR[board[num_v + i][num_h]].equals("□")) {
                    break;
                    }//自分の駒のとき
                        else if (board[num_v+i][num_h] == num_play) {
                    //ひっくり返す
                            for(int j = 1; j < i; j++) {
                                board[num_v + j][num_h] = num_play;
                    }
                    break;
                }
            }
        }
            }
            //左下の判定
            if(num_v < 6 && num_h >1) {
            if(board[num_v+1][num_h-1] != num_play) {
                for(int i = 2; true; i++) {
                    //駒がないとき
                    if(num_v + i > 7 || num_h -i < 0 || STONE_STR[board[num_v + i][num_h - i]].equals("□")) {
                    break;
                    }//自分の駒のとき
                else if (board[num_v + i][num_h -i] == num_play) {
                    //ひっくり返す
                    for(int j = 1; j < i; j++) {
                        board[num_v +j][num_h - j] = num_play;
                    }
                    break;
                }
            }
        }
            }
            //左の判定
            if(num_h > 1) {
            if(board[num_v][num_h-1] != num_play) {
                for(int i = 2; true; i++) {
                    //駒がないとき
                    if(num_h -i < 0 || STONE_STR[board[num_v][num_h - i]].equals("□")) {
                    break;
                }//自分の駒のとき
                    else if (board[num_v][num_h - i] == num_play) {
                    //ひっくり返す
                        for(int j = 1; j < i; j++) {
                            board[num_v][num_h - j] = num_play;
                    }
                    break;
                }
            }
        }
            }
            // 盤面を表示
            print_board();
            }else {
                 // 既に駒がおいてある位置を指定した場合
                System.out.println("そこは置けません。");
                continue;
            }
            // 白黒の切り替え
            num_play = (num_play % 2) + 1;
            num_hand++;
        }
        scan.close();  // データ読み込みの完了
    }

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+1

実際にオセロをやりながら考えましょう。
Daregadaさんの指摘通り、「最低1つ石を裏返せる」マスでなければ石を置けません。では、あなたは石が置けるか置けないかをどのようにして判断していますか?それがわかれば、プログラムにそれをさせればいいだけです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

どのようにすれば隣接しているところだけ置けるようにすることができるでしょうか?

// 盤面の外には置けない
のコメント付近で、置いたマスの周囲に駒があるかチェックをすればいいです。

最終的に駒数を数えて勝敗を判定したいのですが、どのようなアプローチをすればよいでしょうか?

単純に実装するのであれば、手番が変わるときに、手番を数えて60手目が打ち終わったときや、盤の内容を確認して空きが無ければ終了とすれば良いでしょう。
その際にコマの数を数えれば勝敗の判定ができます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/22 11:25

    回答ありがとうございます。
    置いたマスの周囲にコマがあるかの確認は8方向すべて確認する形でいいのでしょうか?それとも他のもっと良い方法があるのでしょうか?
    お答えいただけると助かります。

    キャンセル

  • 2020/07/22 20:05

    他の方の回答の通り厳密なルールとしては正しくないですが、
    とりあえずの「なんちゃってオセロ」を作る場合としては上記回答になります。

    周囲の確認は8方向確認するのが手っ取り早い実装でしょうね。

    正式なルールに則って作る場合、終了条件は盤面が埋まった場合だけでなく、両者がパス(置ける場所がない)場合も含まれます。

    キャンセル

  • 2020/07/23 11:19

    お答えいただきありがとうございます。
    検討してみます。

    キャンセル

0

オセロで駒がおけるのは、「隣接した場所に駒があるマス」ではありません。
「そこに置くと、最低ひとつは相手の駒をひっくり返せるマス」です。
そのため、「どこにも駒が置けない」展開が生じます(パスをする)。
白黒とも、「どこにも駒が置けない」状態になると、(空いているマスがあっても)そこでゲームは終了になります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/22 11:31

    そうなのですね、すみません勘違いしていました。
    そういうことでしたら、ひっくり返す条件式のところに石を置く式を書くということであっていますか?
    また、パスする場合の式は石を置く条件式の最後に入れるのですか?それとも他に方法があるのでしょうか?
    お答えいただけると助かります。

    キャンセル

  • 2020/07/22 11:40

    いや、あなたのコードは読んでいないのでそこまでは付き合えない。

    「隣接した場所に駒があるマス」のうち、「実際に駒を置いたときに相手の駒をひっくり返せるかどうか」のチェックを通ったマスだけが対象になるでしょう。

    そのマスがひとつもないときには、パス(相手に手番を渡す)ことになります。

    なお、おけるマスがひとつでもあれば、(どんなに置きたくない場所であっても)そこに駒を置かなければならない(自由にパスはできない)のがオセロのルールです。

    キャンセル

  • 2020/07/22 12:23

    お答えいただきありがとうございます。
    自分で考えなければならいないところを、余計に聞いてしまい申し訳ありませんでした。検討してみます。

    キャンセル

check解決した方法

-2

新たに変数を作ることで解決しました。
お手数をおかけしました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.05%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る