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

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

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

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

Q&A

4回答

5928閲覧

JAVAの数あてゲームについて

Yoshinori

総合スコア35

Java

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

0グッド

1クリップ

投稿2015/06/06 23:31

編集2022/01/12 10:55

現在JAVAでランダムに重複しない4つの数字(a)を設定し、Scannerで数字を4つ打ち込んでaとすべて一致したらOKと表示するコードを書いています
そこまでは行けたのですがたとえば
aが1234でScannerで1524
と打ち込んだ時に一致している部分は○、間違えている部分は×と表示したいです
例)上記のだと1、4が一致しているので
○2、×2という風にしたいです

答えではなくヒントといいますか手引きをしてほしいです
よろしくお願いします

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

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

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

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

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

guest

回答4

0

if(num[1] == ans[0] && num[2] == ans[1] && num[3] == ans[2] && num[4] == ans[3]){
System.out.println("OK");
}else{
System.out.println("bat");
}

ここをfor文にすると良いと思います。

for()
{
if()
○++;
else
×++;
}

このようにすると良いのではないでしょうか?

投稿2015/06/07 14:38

MasaakiIrie

総合スコア1021

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

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

0

こんにちは。

答えではなくヒントといいますか手引きをしてほしいです

とのことなので、現状のコードの修正を最小限にする方針でいくとして
例えば、以下のようなメソッドを追加するというのはいかがでしょうか。

lang

1private static int countMatches(int[] a, int b[])

このメソッドは、整数の配列 a と配列 b を比較して、同じ位置に同じ
数がある要素の数を返します。たとえば
a が、{ 1, 2, 3, 4 } で、b が { 1, 5, 2, 4 } のときに

countMatches(a, b)

は、2 を返すようなものです。countMatchesメソッドをこのように作成して、
このメソッドの返す値を◯の数にするという方針です。

main の中に直接、countMatchesの中でやることを書かないで
メソッドとして切り分けてることで、どこで何をやるかを切り分
けます。

このようなcountMatchesを作成して、a として最初にランダムに
生成した値の配列を渡し、b としてScannerで取得した値の配列
を渡します。

ただ、もしこれでいくなら、現状、num を長さ5の配列にして
num[0]にユーザーが入力した値を入れ、num[1]からnum[4]で
1000の位から1の位までを入れていますが、これを改めて、
現状のnum[0]に変わる変数をひとつ追加して、(たとえば、inputValue とか。)
num[0]からnum[3]までに1000の位から1の位までを入れて

countMatches(ans, num)

として一致している数字の数を求めます。

countMatchesメソッドの詳細は、

答えではなくヒント

とのことなので書かないでおきます。

以上が「こうしてみては?」というひとつの考え方です。

以下は蛇足ですが、現状のソースをみて少し気になった部分です。

(1) クラス名が hitblow となっていますが、クラス名は先頭を
大文字にするのが通例となっています。
なので、Hitblow とかHitBlow とする方が良いかと思います。

(2)余りを入れておく変数が t_much となっていますが、
割り算の余りは英語で

remainder

ですので、このまま変数名として使って、さきほど挙げた
inputValue
と併せて、

int remainder = inputValue % 1000;

とするのがよいと思います。
少なくとも、 t_much という名前からは、これが
割り算の余りであることが読み取れません。

変数やメソッドなどの名前にこだわりを持つ習慣をつけると、
今後プログラミングを続けていくときに、綺麗なコードを
書くための良い下地になっていきます。

ちなみに私は、この回答を書いているときに
追加することを提案したメソッド名を
countMatch
にするのか、
countMatches
にするのか、はたまた
matchCount
にするのかで、少し悩みました。

以上ご参考になれば幸いです。

追記(1)

(以下の懸案事項ですが、もし、すでに認識されている問題なら、すみません。)
現状のコードだと、ユーザーからの入力も4桁であることを前提にして
しまっているように思えますが、4桁よりも少ない桁の数(たとえば、
100とか)または大きい桁の数字(たとえば、9999999)を入力された場合に、
どのように対応するのかも、要検討かもしれませんね。

たとえば、ランダム生成したans が 1234 のときに、ユーザーからの入力が
134 だったとすると、

・両者をいわば"1234"と"134"という文字列と考えて、
先頭からの同じ位置の数字が一致するものを数えたい。

  =>この例では、"1"だけが一致しているので、一致しているものの数は1

なのか

・ユーザーから入力された134は、整数の値の百三十四であるとして
1234と134の各位の数字が一致しているものの数を数えたい。

  => この例では、十の位の3と、一の位の4が一致するので、
一致しているものの数は2

なのかで、書くべきプログラムも変わってきます。

今回の数あてプログラムのようなものでも、考えるべきことは
たくさんありますね。がんばってください!


追記(2)

ランダム生成する数も、入力される数も4桁と決まっていて、
それら2つの4桁の数について、同じ位に同じ数字がいくつ
あるかを数えることが目的で、それを果たせればそれぞれの
位の数字を配列にする必要が特にないのであれば、
以下のメソッド

int countMatchedDigits(int a, int b)

のようにシンプルに書けます。

lang

1public class Hitblow2 { 2 3 // 2つの4桁の整数、a と bについて、同じ桁に同じ数が 4 // いくつあるかを返す。 5 private static int countMatchedDigits(int a, int b) 6 { 7 int count = 0; 8 9 for ( int divisor = 1000; divisor >= 1; divisor /= 10 ) { 10 if ( a / divisor == b / divisor) 11 count ++; 12 a %= divisor; 13 b %= divisor; 14 } 15 16 return count; 17 } 18 19 // 上記のメソッドのテスト 20 public static void main(String[] args) 21 { 22 System.out.println(countMatchedDigits(1234, 1234)); // 4と表示される。 23 System.out.println(countMatchedDigits(1234, 2345)); // 0と表示される。 24 System.out.println(countMatchedDigits(1234, 9234)); // 3と表示される。 25 } 26 27}

以上、参考になれば幸いです。


追記(3)

もう1つ、
「4桁の数字が2つあったときに、同じ位の数字が一致しているかを判定する方法」
を思いついたので、挙げておきますね。

まず前提として、今回の場合、ランダム生成する4桁の数字は、各桁が
ans[i] = (int)(Math.random() * 9) + 1;
という作成のされ方をするので、どの桁も1以上9以下ですので、
数字0を含まない4桁の整数として、aとbを検証の対象とします。

このとき、

(1) aとbを文字列として連結した文字列s を作成します。
たとえば、
a=1234, b=1784 なら、s="12341784" です。

(2)このように s を作ると、 a と b の千の位の数字が一致するか
どうかを判定するには、文字列 s の一番左の数字と、左から
5番目の数字が一致するかどうかを調べればよいことになります。

(3) 上記(2)を調べるには、文字列s が正規表現

^([1-9])[1-9]{3}\1[1-9]{3}$

にマッチするかどうかを調べればよいです。
この正規表現は、
「1以上9以下の数字だけで構成された、長さ8の文字列で、
かつ、一番左の数字と左から5番目の数字が同じもの」
を表しています。

たとえば、

  • a=1234, b=1784 のときの s="12341784" はこの正規表現にマッチしますが、
  • a=5678, b=9876 のときの s="56789876" はこの正規表現にマッチしません。

(4) 同様に、aとbの百の位、十の位、一の位の数字が一致するかどうかを
判定するための、sに対する正規表現を、各々作ることができて、これら4つの
正規表現のうち、s にマッチするものの個数が、aとbとで数字が同じ桁の個数
になります。

正規表現の学習はこれからかもしれませんが、こんな感じにも
書けますということで、参考に留めて頂ければ幸いです。

 

投稿2015/06/07 01:12

編集2015/06/07 13:19
jun68ykt

総合スコア9058

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

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

0

擬似的なコードで示します。

count_x = 0 // 不一致の数
count_o = 0 // 一致のかず
i = [0, 1, 2, 3] でループする。
if num[i] == ans[i]
count_o += 1 // 一致の数を +1 する
else
count_x += 1 // 不一致の数を +1 する

投稿2015/06/07 00:36

katoy

総合スコア22324

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

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

Yoshinori

2015/06/07 01:44

ありがとうございます 教えていただいたように以下のように書いてみました。 ですが実行すると aが1234で答えを1235とすると 1つ間違い 2つ間違い 3つ間違い 4つ間違い となってしまいます なぜ正解の部分が処理されないのでしょうか? if(num[1] == ans[0] && num[2] == ans[1] && num[3] == ans[2] && num[4] == ans[3]){ System.out.println("OK"); }else{ for(int i = 0; i < 4; i++){ if(num[i] == ans[i]){ ans_ok += 1; System.out.println(ans_ok + "つ正解"); }else{ ans_bat += 1; System.out.println(ans_bat + "つ間違い"); } } }
swordone

2015/06/07 01:56

インデックスの付け方がずれているからです ans:[1,2,3,4] num:[1235,1,2,3,5]となっているので, 1 == 1235 =false 2 == 1 = false という比較になり,すべて間違い判定になるのです. 比較する配列インデックスをnumの方だけ+1するか, そもそもnumの配列の入れ方がおかしいのでそれを修正するかですね
Yoshinori

2015/06/07 02:02

申し訳ございません JAVAを勉強してからまだ少ししかたっていませんのでもう少し噛み砕いて説明してほしいです・・・。
swordone

2015/06/07 02:28

ans[0]:千の位,ans[1]:百の位・・・に対し, num[0]:解答した数字,num[1]:千の位,num[2]:百の位・・・ あなたのコードではこうなっています. そしてans[i]==num[i]という比較は, ans[0]==num[0], ans[1]==num[1]・・・という比較になります
swordone

2015/06/07 02:32

なので解決するには比較をans[i]==num[i+1]とするか, Scanner sc = new Scanner(System.in); int[] num = new int[4]; int x = sc.nextInt(); num[0] = x / 1000; t_much = x % 1000; num[1] = t_much / 100; t_much = t_much % 100; num[2] = t_much / 10; t_much = t_much % 10; num[3] = t_much; このように入力した数値を配列に入れずに,桁の数字を配列の0からスタートさせるかするべきですね. ちなみに整合性の問題から考えると後者が好ましいです.
Yoshinori

2015/06/07 02:43

なるほど!ありがとうございます!! よくわかりました! すみません最後の質問です 正解するまで数字の入力を繰り返せるようにしたく、以下のようにdo~while文で囲んだのですがnumがエラーとなります。これはなぜなのでしょうか? do{ Scanner sc = new Scanner(System.in); int[] num = new int[4]; int x = sc.nextInt(); int ans_ok = 0; int ans_bat = 0; num[0] = x / 1000; t_much = x % 1000; num[1] = t_much / 100; t_much = t_much % 100; num[2] = t_much / 10; t_much = t_much % 10; num[3] = t_much; if(num[0] == ans[0] && num[1] == ans[1] && num[2] == ans[2] && num[3] == ans[3]){ System.out.println("OK"); }else{ for(int i = 0; i < 4; i++){ if(num[i] == ans[i]){ ans_ok += 1; System.out.println(ans_ok + "つ正解"); }else{ ans_bat += 1; System.out.println(ans_bat + "つ間違い"); } } } }while(num[0] == ans[0] && num[1] == ans[1] && num[2] == ans[2] && num[3] == ans[3]);
swordone

2015/06/07 02:53

numはdoブロックの中のローカル変数で,whileで継続条件をチェックする時点でブロックから抜けているためです. numをdoブロックの前で宣言するか,while(true)でループして正解した時にbreakで抜けるかする必要があります. それと正解数をカウントする以上,長ったらしい if(num[0] == ans[0] && num[1] == ans[1] && num[2] == ans[2] && num[3] == ans[3]) というのを使わずに,ans_ok==4でチェックすればいいのでは?
katoy

2015/07/29 13:56 編集

if(num[1] == ans[0] && num[2] == ans[1] && num[3] == ans[2] && num[4] == ans[3]) { System.out.println("OK"); } else { for(int i = 0; i < 4; i++){ if(num[i + 1] == ans[i]) { ans_ok += 1; }else{ ans_bat += 1; } } System.out.println(ans_ok + "つ正解 " + ans_bat + "つ間違い"); } とすれば良いと思います。 > ... なぜ正解の部分が処理されないのでしょうか? ... そのような疑問をもったら、自分でプログラムの挙動をしらべて修正をすすめていくことが大事です。 コードをよんだだけはわからなければ、デバッグでステップ実行するとか、print 文を埋め込んでみるとか。 いまの場合だと、   ...   System.out,println( "i=" + i + ", num[i]=" + num[i] + ", ans[i] =" + ans[i])")   if(num[i] == ans[i]){   ... のような文を追加して実行してみると、num[i] == ans[i]) がいつも 成り立っていないことがわかると思います。 (print 文は融通がきかないので、 debug での step 実行方法を習得した方がよいです。)
guest

0

一致した桁の数を保持する変数を用意し、
桁ごとに比較し一致したら変数に1を加え、
その結果をもとに表示すればいい。

4桁の乱数生成方法もちょっと気になるので私なりに書いてみます

lang

1for(int i = 0; i < 4; i++){ 2 check: while(true){ 3 int n = (int)(Math.random() * 9) + 1; 4 for(int j = 0; j < i; j++){ 5 if(n == ans[j]) continue check; //一致したら乱数生成に戻る 6 } 7 ans[i] = n; 8 break; 9 } 10}

投稿2015/06/07 00:34

編集2015/06/07 01:23
swordone

総合スコア20649

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問