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

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

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

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

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Q&A

解決済

2回答

676閲覧

javaのScannerについて

NEKOTABETAI

総合スコア14

Java

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

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

0グッド

0クリップ

投稿2020/09/29 16:31

前提・実現したいこと

初めてScannerを使ったのですがなぜか意図しない挙動になってしまいます。
というのはEnterを二回入力しなければ処理が進まない?感じなのでしょうか、
コンソールに描画されるはずのものが描画されません。
二回押すようにすりゃ済む話なのですがすっきりしないので誰かご指摘お願いいたします。

発生している問題・エラーメッセージ

リソース・リーク: 'scan' が閉じられることはありません

これはエラーというより警告みたいな感じなんですがこれが現れてから挙動がおかしいです。

該当のソースコード

java

1import java.util.ArrayList; 2import java.util.Arrays; 3import java.util.List; 4import java.util.Random; 5import java.util.Scanner; 6 7public class maruBatu { 8 9 static ArrayList<Integer> playerPositions = new ArrayList<Integer>(); 10 static ArrayList<Integer> cpuPositions = new ArrayList<Integer>(); 11 12 13 public static void main(String[] args) { 14 15 char [][] gameBoard = { 16 {' ', '|', ' ', '|', ' '}, 17 {'-', '+', '-', '+', '-'}, 18 {' ', '|', ' ', '|', ' '}, 19 {'-', '+', '-', '+', '-'}, 20 {' ', '|', ' ', '|', ' '} 21 }; 22 23 printGameBoard(gameBoard); 24 25 while(true) { 26 27 back:while(true) { 28 29 String crlf = System.getProperty("line.separator"); 30 31 Scanner scan = new Scanner(System.in); //入力の受付 32 System.out.println(crlf + "どこに置きますか?1~9で選んでください"); 33 int playerPos = scan.nextInt(); //ここの下の行 //System.inの入力結果をintに変換 34 if(playerPositions.contains(playerPos) || cpuPositions.contains(playerPos)) { //自分orCPUがとっていたら 35 System.out.println("そこはすでに置かれています。違う場所にしてください"); 36 printGameBoard(gameBoard); 37 break back; 38 } 39 40 placePiece(gameBoard, playerPos, "player"); 41 42 String result = checkWinner(); 43 if(result.length() > 0) { 44 System.out.println(result); 45 break; 46 } 47 48 Random rand = new Random(); 49 int cpuPos = rand.nextInt(9) + 1 ; 50 51 while(playerPositions.contains(cpuPos) || cpuPositions.contains(cpuPos)) { 52 cpuPos = rand.nextInt(9) + 1 ; 53 } 54 55 placePiece(gameBoard, cpuPos, "cpu"); 56 57 printGameBoard(gameBoard); 58 59 result =checkWinner(); 60 if(result.length() > 0) { 61 System.out.println(result); 62 break; 63 } 64 } 65 //break; ここにbreakを入れても同じような不具合になりましたのでコメントアウトしました。全く関係なさそうなのになぜでしょう? 66 } 67 68 } 69 70 public static void printGameBoard(char [][] gameBoard) { 71 for(char[] row : gameBoard) { //for each文 72 for(char c : row) { 73 System.out.print(c); 74 } 75 System.out.println(); 76 } 77 } 78 79 public static void placePiece(char[][] gameBoard, int pos, String user) { 80 81 char symbol = ' '; 82 83 if(user.equals("player")) { 84 symbol = 'X'; 85 playerPositions.add(pos); 86 }else if(user.equals("cpu")) { 87 symbol = 'O'; 88 cpuPositions.add(pos); 89 } 90 91 switch(pos) { 92 case 1: 93 gameBoard[0][0] = symbol; 94 break; 95 case 2: 96 gameBoard[0][2] = symbol; //[1]ではない 97 break; 98 case 3: 99 gameBoard[0][4] = symbol; 100 break; 101 case 4: 102 gameBoard[2][0] = symbol; 103 break; 104 case 5: 105 gameBoard[2][2] = symbol; 106 break; 107 case 6: 108 gameBoard[2][4] = symbol; 109 break; 110 case 7: 111 gameBoard[4][0] = symbol; 112 break; 113 case 8: 114 gameBoard[4][2] = symbol; 115 break; 116 case 9: 117 gameBoard[4][4] = symbol; 118 break; 119 default: 120 break; 121 122 } 123 } 124 125 public static String checkWinner() { 126 127 List topRow = Arrays.asList(1, 2, 3); //3要素 128 List midRow = Arrays.asList(4, 5, 6); 129 List botRow = Arrays.asList(7, 8, 9); 130 List leftCol = Arrays.asList(1, 4, 7); 131 List midCol = Arrays.asList(2, 5, 8); 132 List rightCol = Arrays.asList(3, 7, 9); 133 List cross1 = Arrays.asList(1, 5, 9); 134 List cross2 = Arrays.asList(3, 5, 7); 135 136 List<List> winning = new ArrayList<List>(); 137 winning.add(topRow); 138 winning.add(midRow); 139 winning.add(botRow); 140 winning.add(leftCol); 141 winning.add(midCol); 142 winning.add(rightCol); 143 winning.add(cross1); 144 winning.add(cross2); 145 146 for(List l : winning) { 147 if(playerPositions.containsAll(l)) { 148 return "YOU WIN!"; 149 }else if(cpuPositions.containsAll(l)) { 150 return "YOU LOSE"; 151 }else if(playerPositions.size() + cpuPositions.size() == 9) { 152 return "引き分け"; 153 } 154 } 155 156 return ""; 157 } 158 159} 160

試したこと

ググったらScannerを閉じればいいというのを見たのでscan.close()をコメントアウトしている場所(わかりにくくてすみません)
に書いたんですが、今度は別のエラーになったので消しました。

Exception in thread "main" どこに置きますか?1~9で選んでください java.util.NoSuchElementException at java.base/java.util.Scanner.throwFor(Scanner.java:937) at java.base/java.util.Scanner.next(Scanner.java:1594) at java.base/java.util.Scanner.nextInt(Scanner.java:2258) at java.base/java.util.Scanner.nextInt(Scanner.java:2212) at TicTacToe.main(TicTacToe.java:33)

でした。ちょっとこれは意味わかんないです。

補足情報(FW/ツールのバージョンなど)

自分で書いたコードなので読みにくいと思います。
ここはこうしたほうがいい、という事があればぜひ教えていただきたいです。

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

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

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

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

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

guest

回答2

0

ベストアンサー

Enterが二回・・については提示のコードでも警告の有無に関わらずEnter1回で処理が進んだ為、答えられませんが
NoSuchElementExceptionについてはこちらの回答が参考になりました。

警告を消す際にwhile文が二重になっているのが面倒だったので、mainだけ少し変えてみました。元コードと比べ、勝敗が決まるとプログラムが終了するようになってます。

public static void main(String[] args) { char [][] gameBoard = { {' ', '|', ' ', '|', ' '}, {'-', '+', '-', '+', '-'}, {' ', '|', ' ', '|', ' '}, {'-', '+', '-', '+', '-'}, {' ', '|', ' ', '|', ' '} }; printGameBoard(gameBoard); Scanner scan = new Scanner(System.in); // 入力の受付 Random rand = new Random(); String crlf = System.getProperty("line.separator"); String result = ""; while (true) { System.out.println(crlf + "どこに置きますか?1~9で選んでください"); int playerPos = scan.nextInt(); // ここの下の行 //System.inの入力結果をintに変換 if (playerPositions.contains(playerPos) || cpuPositions.contains(playerPos)) { // 自分orCPUがとっていたら System.out.println("そこはすでに置かれています。違う場所にしてください"); printGameBoard(gameBoard); continue; } placePiece(gameBoard, playerPos, "player"); result = checkWinner(); if (result.length() > 0) break; int cpuPos = rand.nextInt(9) + 1; while (playerPositions.contains(cpuPos) || cpuPositions.contains(cpuPos)) { cpuPos = rand.nextInt(9) + 1; } placePiece(gameBoard, cpuPos, "cpu"); result = checkWinner(); if (result.length() > 0) break; printGameBoard(gameBoard); } printGameBoard(gameBoard); System.out.println(result); scan.close(); }

投稿2020/09/30 07:01

ihigaku

総合スコア71

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

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

NEKOTABETAI

2020/09/30 13:06

回答ありがとうございます。 とても参考になりました。 continueの存在を忘れてました... Enter二回の方はもう少し探ってみます。
guest

0

ループの中に置くと、毎回Scannerを生成してしまうので、ループに入る前に生成して、
それを使った方が良いように思います。
ついでに、Randomも同様に。

投稿2020/09/29 17:59

amiya

総合スコア1218

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

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

NEKOTABETAI

2020/09/30 12:58

回答ありがとうございます。 修正いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問