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

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

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

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

4回答

9090閲覧

【C#】回数指定のじゃんけんゲーム

k.h

総合スコア8

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2016/07/25 06:14

編集2022/01/12 10:55

###前提・実現したいこと
観覧してくださってありがとうございます
高卒SE0年生として現在会社で勉強していて簡単なじゃんけんゲームを作成しました
そこで応用で回数指定の限定じゃんけんを作ろうとしているのですがどこを改善すれば良いかで悩んでいます
ソースコードは私が作ったじゃんけんゲームのソースコードになります
若輩者ですがアドバイスをよろしくお願いします
【追記説明】
説明不足で申し訳ないです…
(ルール)
・プレイヤーは2人(プレイヤー1・CPU1)
・9回勝負
・グー、チョキ、パー各3回までしか出せない
(手順)
・じゃんけん→勝敗判定を9回繰り返し
・勝敗をカウント
(現在の仕様)
手を決めてじゃんけんするだけの勝敗などがまだカウントできてない状況です

なるべく詳細は書いていくつもりですが説明足りないかと思いますがそのつど言って頂ければと思います
よろしくお願いします

###該当のソースコード
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
class ゲーム//
{
static void Main(string[] args)
{
int player = 1;
int cpu = 1;
int a = 1;

string player1 = ""; string cpu1 = ""; Random rand = new Random();//乱数を設定 Console.WriteLine("数字を入力");//文字を表示 Console.WriteLine("じゃんけん\n数字を入力\n1グー、2チョキ、3パー");//文字を表示 while (a != 0)//条件が正しい場合反復処理 { try//実行 { player = int.Parse(Console.ReadLine()); cpu = rand.Next(1, 4); if (cpu == player) { Console.WriteLine("あいこ もう一度入力"); continue; } else if (player == 1 && cpu == 2) { Console.WriteLine("プレイヤー、グー"); Console.WriteLine("CPU、チョキ"); Console.WriteLine("勝ち"); } else if (player == 2 && cpu == 3) { Console.WriteLine("プレイヤー、チョキ"); Console.WriteLine("CPU、パー"); Console.WriteLine("勝ち"); } else if (player == 3 && cpu == 1) { Console.WriteLine("プレイヤー、パー"); Console.WriteLine("CPU、グー"); Console.WriteLine("勝ち"); } else if (player < 1 || player > 3) { Console.WriteLine("1か2か3を入力してね"); continue; } else { if (player == 1) player1 = player.ToString("グー"); if (player == 2) player1 = player.ToString("チョキ"); if (player == 3) player1 = player.ToString("パー"); if (cpu == 1) cpu1 = cpu.ToString("グー"); if (cpu == 2) cpu1 = cpu.ToString("チョキ"); if (cpu == 3) cpu1 = cpu.ToString("パー"); Console.WriteLine("プレイヤー、{0}\nCPU、{1}", player1, cpu1); Console.WriteLine("負け"); } //終了分岐の呼び出し bunki(ref player, ref cpu, ref a); if (a == 0) { Console.Clear(); Console.Write("終了します");//文字を表示 } } catch (FormatException) { Console.Clear(); Console.WriteLine("数字を入力");//文字を表示 Console.WriteLine("じゃんけん\n数字を入力\n1グー、2チョキ、3パー");//文字を表示 continue; } } } //終了分岐のメソッド static void bunki(ref int player, ref int cpu, ref int a) { if (player != cpu) { Console.WriteLine("\n終了なら0\n続行は0以外を入力"); a = int.Parse(Console.ReadLine()); Console.Clear(); Console.WriteLine("数字を入力");//文字を表示 Console.WriteLine("じゃんけん\n数字を入力\n1グー、2チョキ、3パー");//文字を表示 } } }

}
###補足情報(言語/FW/ツール等のバージョンなど)
VisualStudio2015

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

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

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

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

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

Chironian

2016/07/25 06:29

SEを目指されているのであれば、現在の仕様、および、それをどのような仕様に変更したいのか、きちんと説明してみると良いですよ。仕様を把握しそれを説明するのはSEの必須スキルの1つですから。意外に難しいですが、ガンバです。
jawa

2016/07/25 09:35

ソースコードは前後を```で囲んで投稿することでネストの段組みなどを表示することができます。 それだけで読みやすさがぐっと変わりますので、Teratailで投稿する際のマナーだと思って心掛けて頂きたいです。
mugicya

2016/07/25 16:05

まだ言語の基本的な記述など、理解が浅いようですね。 Webで検索すると、疑問の回答がポンと出てきてそれを使いがちですが、 やはり、僕は書籍を購入してチュートリアルを完遂して内容理解に努めるのが早いと思います。 がんばってください。
guest

回答4

0

オブジェクトを使って少し抽象化してみました。
多人数に対応しています。
また、Player を継承することで、コンソール以外の入力に対応できます。

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5 6namespace ConsoleApplication1 7{ 8 class ゲーム// 9 { 10 static void Main(string[] args) 11 { 12 var you = new ConsolePlayer() { Name = "あなた" }; 13 var cpu = new RandomPlayer() { Name = "CPU" }; 14 var players = new Player[] { you, cpu }; 15 do 16 { 17 foreach (var player in players) 18 { 19 //各プレイヤーが自分の手を決める 20 player.DecideHand(); 21 } 22 23 // 審判 24 var judge = new Judge(players); 25 26 foreach (var player in players) 27 { 28 // 各プレイヤーに結果報告 29 player.AnnounceResult(judge); 30 } 31 // 全員やめたいと言うまで続ける 32 } while (players.Any(p => !p.WantToQuit())); 33 } 34 } 35 36 enum Hand 37 { 38 グー, チョキ, パー 39 } 40 41 // 審判 42 class Judge 43 { 44 public Judge(IEnumerable<Player> players) 45 { 46 Players = players; 47 Winned = new Dictionary<Player, bool>(); 48 foreach (var player in Players) Winned[player] = false; 49 var varietyOfHands = players 50 .Select(p => p.Hand) 51 .Distinct() 52 .ToArray(); 53 if (varietyOfHands.Count() == 2) 54 { 55 // 手の種類が 2 種類なら勝者を決める(例: {グー, チョキ}, {チョキ, チョキ, パー})。それ以外なら勝者無し 56 Hand winnedHand = JudgeHand(varietyOfHands[0], varietyOfHands[1]); 57 foreach (var player in players.Where(p => p.Hand == winnedHand)) 58 { 59 Winned[player] = true; 60 } 61 } 62 } 63 64 // どちらが勝つかを定めたテーブル 65 private Dictionary<Hand, Hand> strongerHand = new Dictionary<Hand,Hand>() 66 { 67 {Hand.グー, Hand.パー}, 68 {Hand.パー, Hand.チョキ}, 69 {Hand.チョキ, Hand.グー} 70 }; 71 72 // 手を比較して勝った方の手を返す。手の種類が一種類の場合は例外。 73 public Hand JudgeHand(Hand a, Hand b) 74 { 75 if (a == b) throw new InvalidOperationException(); 76 if (strongerHand[a] == b) return b; 77 else return a; 78 } 79 80 // プレイヤーリスト 81 public IEnumerable<Player> Players { get; private set; } 82 83 // 勝者は true 敗者は false 84 public Dictionary<Player, bool> Winned { get; private set; } 85 } 86 87 // プレイヤー 88 abstract class Player 89 { 90 // 表示名 91 public string Name { get; set; } 92 93 // 手 94 public Hand Hand { get; set; } 95 96 // 次にどの手を出すか決める 97 public abstract void DecideHand(); 98 99 // 終わりたいなら true 続けたいなら false を返す 100 public abstract bool WantToQuit(); 101 102 // 結果発表 103 public abstract void AnnounceResult(Judge judge); 104 } 105 106 // コンソールを使って次の手を入力するプレイヤー 107 class ConsolePlayer : Player 108 { 109 public override void DecideHand() 110 { 111 while (true) 112 { 113 try 114 { 115 Console.WriteLine("じゃんけん\n数字を入力\n1グー、2チョキ、3パー"); 116 string s = Console.ReadLine(); 117 int h = int.Parse(s) - 1; 118 if (h < 0 || h >= Enum.GetNames(typeof(Hand)).Length) 119 { 120 throw new InvalidOperationException(); 121 } 122 Hand = (Hand)h; 123 break; 124 } 125 catch 126 { 127 Console.WriteLine("\n1か2か3を入力してね\n"); 128 } 129 } 130 } 131 132 public override bool WantToQuit() 133 { 134 Console.WriteLine("\n終了なら0\n続行は0以外を入力"); 135 string s = Console.ReadLine(); 136 return s == "0"; 137 } 138 139 public override void AnnounceResult(Judge judge) 140 { 141 Func<Player, int, string> result = (player, index) => 142 { 143 return string.Format( 144 "{0} [{1}]", 145 player.Name, 146 player.Hand.ToString() 147 ); 148 }; 149 var results = judge 150 .Players 151 .Select((player, index) => result(player, index)); 152 results.ToList().ForEach(s => Console.WriteLine(s)); 153 var winners = judge 154 .Players 155 .Where(p => judge.Winned[p]) 156 .Select(p => p.Name) 157 .ToArray(); 158 if (winners.Count() == 0) 159 { 160 Console.WriteLine("引き分け"); 161 } 162 else 163 { 164 Console.WriteLine(string.Format("勝者: {0}", string.Join(", ", winners))); 165 } 166 } 167 } 168 169 // 次の手をランダムで決めるプレイヤー 170 class RandomPlayer : Player 171 { 172 public RandomPlayer() 173 { 174 Random = new Random(); 175 } 176 177 protected Random Random { get; set; } 178 179 public override void DecideHand() 180 { 181 Hand = (Hand)Random.Next(Enum.GetNames(typeof(Hand)).Length); 182 } 183 184 public override bool WantToQuit() 185 { 186 // やめたくてやめたくてしょうがない 187 return true; 188 } 189 190 public override void AnnounceResult(Judge judge) 191 { 192 // 結果なんてどうでもいい 193 } 194 } 195}

投稿2016/07/25 08:14

Zuishin

総合スコア28656

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

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

Zuishin

2016/07/25 09:03

Player クラスに自分が何の手を何回出したか、何回勝ったかの情報を入れておいて、それを使って出せる手を制限すればいいと思います。 あと、SE を目指しているならこんな重要な情報を言われてから出すようではさすがに必死で頑張らないと厳しいかもしれませんね。 インデントも早く直しましょう。見直して全く気になりませんか?
Zuishin

2016/07/25 09:12

それと、私たちはあなたの部下ではありません。 「わからないことがあったら聞いてくれ」は上司の言です。 あなたがわからないことを聞いているのですから、必要な情報を揃えるのはあなたの仕事です。
guest

0

追加で改修する部分について、できるところまでは自力で考えた結果を提示していただきたかったです。
今回の質問の仕方では、提示しているソースコードは自作のものとのことですが、改修部分については「丸投げ」とも取れる内容ですので。

アドバイス

苦言だけでは申し訳ないので、自分ならここを作り変える、という観点からアドバイスです。

①勝ち負け判定
⇒特に「勝ち判定」の部分が出した手ごとに個別の処理になってしまっているのが気になります。
「負け判定」ではメッセージ出力を共通化できているので、「勝ち負けフラグ」のようなものを用意すればメッセージ出力は一本化できると思います。

また、出した手ごとに判定処理を記述していると、通算での勝ち数・負け数のカウントアップも手ごとに記述しなくてはならなくなり、管理が煩雑になります。

(宣言) //出し手の使用回数管理(対戦開始時の初期化処理) int[] player_te = {0, 3, 3, 3}; //出し手の表示名を配列で管理 string[] disp_te = {"", "グー", "チョキ", "パー"}; //判定結果 int result = 0; //勝ち数 int win = 0; //負け数 int lose = 0; (判定処理) if (player < 1 || player > 3) { Console.WriteLine("1か2か3を入力してね"); continue; } else if ( player_te[player] < 1) { //使用回数の判定 Console.WriteLine( "{0}は使用回数を超えています。", disp_te[player]); continue; } else if (cpu == player) { Console.WriteLine("あいこ もう一度入力"); continue; } else if (player == 1 && cpu == 2) || (player == 2 && cpu == 3) || (player == 3 && cpu == 1) { //勝ち判定 result = 1; win = win + 1; } else { //負け判定 result = 0; lose = lose + 1; } //今回出した手の使用回数を1つ減らす player_te[player] = player_te[player] - 1; //メッセージ表示 Console.WriteLine("プレイヤー、{0}\nCPU、{1}", disp_te[player], disp_te[cpu]); if (result == 1) { Console.WriteLine("勝ち"); } else { Console.WriteLine("負け"); }

※コードは机上で作成したものなので動作の保証はありません。あくまで考え方として参考までに。

②関数化
⇒これも「勝ち負け判定」の部分になりますが、判定の条件文が少し長すぎるため、処理の流れが分かりにくくなっています。
自分なら判定部分は勝ち/負け/あいこの結果を返す関数を用意すると思います。

それ以外の部分では、0が入力されるまでのループを対戦回数でのループに変更するくらいで目的が達せられるのではないでしょうか。
がんばってみてください。

投稿2016/07/25 09:58

編集2016/07/25 10:10
jawa

総合スコア3013

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

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

0

こんにちは。

(現在の仕様)

手を決めてじゃんけんするだけの勝敗などがまだカウントできてない状況です

現在の仕様は、何ができていないかではなく、何ができているか書きましょう。
現仕様と目標仕様を見比べて、何が不足しているか判断することになりますが、現仕様がかけないとそれが明確にならないのですよ。

目標仕様も不明点が残っているようです。
「グー、チョキ、パー各3回までしか出せない」について
あいこの時どうする?
4回目出してしまったらどうする?
など

あと、他の人にソースを読んで貰うためには、インデントはちゃんと付けましょう。
インデントのないソースってマジで読めないです。

ごめんなさい。少し厳しい回答をしてると思います。
しかし、仕様を明確に記述することはSEの最重要スキルですから頑張れ。

投稿2016/07/25 09:26

Chironian

総合スコア23272

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

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

0

質問が漠然としすぎているので、まずはそこを整理することからはじめては?
・プログラムの書き方(拡張性を考えた書き方とか、コメントの付け方とか)
・アルゴリズムに関して(判定の仕方とか、出力の仕方とか)
・teratail のマークダウン記法(ソースのソースとしての表現の仕方とか)
等々、聞きたいポイントが有るのではないかと思います。
どれを聞きたいのか、どのような観点で聞きたいか、整理できればほしい回答が手に入れられるかと。

投稿2016/07/25 06:24

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問