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

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

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

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

1286閲覧

C++ トランプを配り、並び替え

amareno

総合スコア20

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/10/20 07:24

編集2018/10/21 21:33

前提・実現したいこと

カードをシャッフルし、プレイヤー4人に配ったら下記のようにアウトプットしたいです。

Player 1 Player 2 Player 3 Player 4 -------- -------- -------- -------- Spade 4 Spade 2 Spade 9 Spade Ace Heart 2 Spade 5 Spade 10 Spade 3 Heart 8 Spade 7 Spade Queen Spade 6 Heart King Spade Jack Heart 5 Spade 8

Diamond 2 Heart Ace Heart 6 Spade King
Diamond 3 Heart 3 Diamond 4 Heart 4
Diamond 9 Heart 7 Diamond 7 Heart 9
Diamond Queen Heart 10 Diamond 10 Heart Jack
Diamond King Heart Queen Club 4 Diamond Ace
Club 2 Diamond 5 Club 6 Diamond 8
Club 5 Diamond 6 Club 7 Diamond Jack
Club 9 Club 3 Club Jack Club Ace
Club 10 Club King Club Queen Club 8

しかし、下記のように、Spade 0しかアウトプットされません。私のコードのどこがおかしいか教えて頂けますでしょうか?

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

Enter 1 to shuffle, 2 to deal, or 3 to end: 1 Deck shuffled. 2 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 1 Deck shuffled. 2 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 Spade 0 3 Bye

該当のソースコード

C++

1#include <string> 2#include <stdexcept> 3#include <iostream> 4#include <iomanip> 5#include <algorithm> 6#include <stdio.h> 7#include <time.h> 8 9using namespace std; 10 11enum Suit { 12 Clubs = 1, 13 Diamonds = 2, 14 Hearts = 3, 15 Spades = 4 16}; 17 18class Card { 19 20private: 21 int number; 22 Suit suit; 23 string description; 24public: 25 26 Card() { 27 number = 0; 28 description = ""; 29 } 30 31 Suit getCardSuit() { 32 return suit; 33 } 34 35 void setCardSuit(Suit m_suit) { 36 suit = m_suit; 37 } 38 39 int getCardNumber() { 40 return number; 41 } 42 43 void setCardNumber(int m_num) { 44 45 number = m_num; 46 } 47 48 string getCardDescription() { 49 50 return description; 51 } 52 53 void setDescription(string m_description) { 54 55 description = m_description; 56 } 57 58 bool operator <(const Card& card2) { 59 60 if (suit < card2.suit) 61 62 return true; 63 64 else if (suit > card2.suit) 65 66 return false; 67 68 else { 69 70 if (number == 1) 71 72 return false; 73 74 else if (card2.number == 1) 75 76 return true; 77 78 else if (card2.number < number) 79 80 return true; 81 } 82 83 return false; 84 } 85}; 86 87 88const int SIZE = 52; 89Card deck[52]; 90 91class Deck { 92 Card decks[SIZE]; 93public: 94 95 void initialize() { 96 97 98 string cardDesc; 99 100 char name[10]; 101 102 int setFlag; 103 104 for (int i = 1; i <= SIZE; i++) { 105 106 setFlag = 0; 107 108 if (i == 1 || i == 14 || i == 27 || i == 40) { 109 cardDesc = "Ace"; 110 111 setFlag = 1; 112 113 } else if (i == 11 || i == 24 || i == 37 || i == 50) { 114 cardDesc = "Jack"; 115 116 setFlag = 1; 117 118 } else if (i == 12 || i == 25 || i == 38 || i == 51) { 119 cardDesc = "Queen"; 120 121 setFlag = 1; 122 123 } else if (i == 13 || i == 26 || i == 39 || i == 52) { 124 cardDesc = "King"; 125 126 setFlag = 1; 127 } 128 129 if(i <= 13) { 130 decks[i - 1].setCardSuit(Spades); 131 132 decks[i - 1].setCardNumber(i); 133 134 if(setFlag == 0) { 135 136 (decks[i - 1].getCardNumber(), name, 10); 137 138 cardDesc = ((string)name); 139 } 140 141 cardDesc = " of Spades"; 142 143 decks[i - 1].setDescription(cardDesc); 144 145 } else if (i > 13 && i <= 26) { 146 147 decks[i - 1].setCardSuit(Hearts); 148 149 decks[i - 1].setCardNumber(i - 13); 150 151 if(setFlag == 0) { 152 153 (decks[i - 1].getCardNumber(), name, 10); 154 155 cardDesc = ((string)name); 156 } 157 158 cardDesc = " of Hearts"; 159 160 decks[i - 1].setDescription(cardDesc); 161 162 } else if(i > 26 && i <= 39) { 163 164 decks[i - 1].setCardSuit(Diamonds); 165 166 decks[i - 1].setCardNumber(i - 26); 167 168 if(setFlag == 0) { 169 170 (decks[i - 1].getCardNumber(), name, 10); 171 172 cardDesc = ((string)name); 173 174 } 175 176 cardDesc = " of Diamonds"; 177 178 decks[i - 1].setDescription(cardDesc); 179 180 } else { 181 182 decks[i - 1].setCardSuit(Clubs); 183 184 decks[i - 1].setCardNumber(i - 39); 185 186 if(setFlag == 0) { 187 188 (decks[i - 1].getCardNumber(), name, 10); 189 190 cardDesc = ((string)name); 191 } 192 193 cardDesc = (" of Clubs"); 194 195 decks[i - 1].setDescription(cardDesc); 196 } 197 } 198 } 199 200 void shuffle() { 201 202 Card card; 203 204 srand((unsigned int)time(NULL)); 205 206 for (int i = 0; i < SIZE ;i++) 207 { 208 int r = i + (rand() % (52 -i)); 209 210 card = decks[i]; 211 decks[i] = decks[r]; 212 decks[r] = card; 213 214 } 215 } 216}; 217 218 219class Player { 220private: 221 Card hand[13][4]; 222 string name_; 223 224public: 225 226 void deal() { 227 228 for ( int i = 0; i < 13; ++i ) { 229 for ( int j = 0; j < 4; ++j ) { 230 hand[i][j] = deck[j + 4 * i]; 231 } 232 } 233 234 sort(hand); 235 236 display(hand); 237 } 238 239 240 void sort(Card hand[13][4]) { 241 Card card; 242 243 int j; 244 245 for (int itr = 0; itr < 4; itr++) 246 { 247 for(int i = 1 ; i < 13 ; i++) 248 { 249 card = hand[i][itr]; 250 251 j = i - 1; 252 253 while(j >= 0 && hand[j][itr] < card) 254 { 255 hand[j + 1][itr] = hand[j][itr]; 256 257 j--; 258 } 259 hand[j + 1][itr] = card; 260 } 261 } 262 } 263 264 void display(Card hand[13][4]) { 265 266 Suit suit; 267 268 int number; 269 270 int numPlayers = 4; 271 272 for (int n = 0; n < 13; ++n) { 273 for (int i = 0; i < numPlayers; ++i) { 274 275 suit = hand[n][i].getCardSuit(); 276 277 number = hand[n][i].getCardNumber(); 278 279 if (suit == 1) 280 cout << setw(10) << "Club"; 281 282 else if (suit == 2) 283 cout << setw(10) << "Diamond"; 284 285 else if (suit == 3) 286 cout << setw(10) << "Heart"; 287 288 else 289 cout << setw(10) << "Spade"; 290 291 if (number == 1) 292 cout << setw(6) << "Ace"; 293 294 else if(number == 11) 295 cout << setw(6) << "Jack"; 296 297 else if(number == 12) 298 cout << setw(6) << "Queen"; 299 300 else if(number == 13) 301 cout << setw(6) << "King"; 302 303 else 304 cout << setw(6) << number; 305 306 } 307 cout << endl; 308 } 309 cout << endl; 310 } 311}; 312 313 314int main() { 315 316 Deck decks; 317 318 decks.initialize(); 319 320 Player hand; 321 322 int enter; 323 324 cout << "Enter 1 to shuffle, 2 to deal, or 3 to end: " << endl; 325 326 do { 327 cin >> enter; 328 329 330 switch (enter) { 331 case 1: 332 decks.shuffle(); 333 cout << "Deck shuffled." << endl; 334 break; 335 336 case 2: 337 hand.deal(); 338 break; 339 340 case 3: 341 cout << "Bye" << endl; 342 break; 343 344 default: 345 break; 346 } 347 348 } while (enter != 3); 349} 350

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

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

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

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

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

episteme

2018/10/20 14:29 編集

まず適切なコメントをつけよ。回答者に余計な負担をかけるな。
episteme

2018/10/20 10:34

library sortや、std::shuffle、std::random_shuffleなどは使ってはいけないです。→ それはなぜ? じゃぁ何を使っていいの?
amareno

2018/10/20 16:53

すいません、おっしゃる通りです。次回からコード内にコメントをつけて説明します。
amareno

2018/10/20 16:59

私の説明不足で申し訳ありません。library sortや、std::shuffle、std::random_shuffleなどは使ってはいけないと問題文に書かれてあるのでそれらは使えないです。rand関数、srand関数などが使えます。
guest

回答4

0

  • 52枚のカード・セットが グローバル変数/ Deckのメンバ/ Playerのメンバ の三か所に現れる。ムダ。
  • Player::deal() においてCard集合を初期化/シャッフル/表示しているが、カード集合のコピー元が Deck::decks[] ではなく、初期化していないグローバルなdeck[]から。
    そもそもshuffleとdealはDeckの責務ではないのか? なぜPlayerがカードを配る(deal)んだ?
  • main() 内の Deck decks はPlayer に何の影響も与えない(存在意義がない)。
  • Playerの実態が"4人のプレーヤ"になっている。プレーヤ数の増減に対応できない。
  • Cardの名称:descriptionをDeckが生成している。Cardの名称はCard自身が設定すべき
  • 52枚のCardは初期状態として唯一Deck内にあり、DeckからPlayerへ/PlayerからDeckへ移動すべきではないか?
    各Cardはゲーム中なくなることも重複することもなく、Deckあるいは4人のプレーヤのいずれかの手元にあるのだから。

とまぁ、そんなわけで設計ダメダメ。

投稿2018/10/22 10:04

episteme

総合スコア16614

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

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

0

"動けばいーや"なおちゃらか実装

C++

1#include <string> 2#include <stdexcept> 3#include <iostream> 4#include <iomanip> 5#include <algorithm> 6#include <vector> 7#include <random> 8 9class Card { 10public: 11 enum class Suit { Spade, Heart, Diamond, Club}; 12private: 13 int number; 14 Suit suit; 15public: 16 Card(int n=0, Suit s=Suit(-1)) : number(n), suit(s) {} 17 Card(const Card& c) : number(c.number), suit(c.suit) {} 18 19 int getNumber() const { 20 if ( number < 1 || number > 13 ) throw range_error("bad Number"); 21 return number; 22 } 23 Suit getSuit() const { 24 if ( int(suit) < 0 || int(suit) > 3 ) throw range_error("bad Suit"); 25 return suit; 26 } 27 string description() const; 28 29 int key() const { 30 int n = getNumber() - 1; 31 if ( n == 0 ) n = 13; 32 return (int)getSuit() * 13 + n; 33 } 34}; 35 36inline bool operator<(const Card& c1, const Card& c2) { 37 return c1.key() < c2.key(); 38} 39 40string to_string(const Card::Suit& s) { 41 switch ( s ) { 42 case Card::Suit::Spade : return "Spade"; 43 case Card::Suit::Heart : return "Heart"; 44 case Card::Suit::Diamond : return "Diamond"; 45 case Card::Suit::Club : return "Club"; 46 } 47 return string(); 48} 49 50string Card::description() const { 51 static const char* nums[] = { "Ace", "2", "3", "4", "5", 52 "6", "7", "8", "9", "10", 53 "Jack", "Queen", "King" }; 54 return to_string(getSuit()) + " " + nums[getNumber()-1]; 55} 56 57inline std::ostream& operator<<(std::ostream& stream, const Card& c) { 58 return stream << c.description(); 59} 60 61class Deck { 62private: 63 std::vector<Card> deck_; 64public: 65 Deck() { 66 for ( int i = 0; i < 13; ++i ) { 67 for ( int j = 0; j < 4; ++j ) { 68 deck_.push_back(Card(i+1,Card::Suit(j))); 69 } 70 } 71 } 72 void shuffle() { 73 static std::mt19937 gen; 74 std::shuffle(deck_.begin(), deck_.end(), gen); 75 } 76 Card draw() { Card c = deck_.back(); deck_.pop_back(); return c; } 77 bool empty() const { return deck_.empty(); } 78}; 79 80 81class Player { 82private: 83 std::vector<Card> hand_; 84 std::string name_; 85 86public: 87 void sort() { std::sort(hand_.begin(), hand_.end()); } 88 void add(const Card& card) { hand_.push_back(card); } 89 const Card& at(int n) const { return hand_.at(n); } 90}; 91 92 93int main() { 94 95 Deck deck; 96 deck.shuffle(); 97 98 // 4人のプレイヤーにカードを配る 99 const int nplayers = 4; 100 Player players[nplayers]; 101 for ( int i = 0; !deck.empty(); i = (i + 1) % nplayers) { 102 Card c = deck.draw(); 103 players[i].add(c); 104 ; 105 } 106 107 // 各プレイヤーの手札をソートする 108 for ( auto& player : players ) { 109 player.sort(); 110 } 111 112 // 各プレイヤーの手札を出力する 113 for ( int n = 0; n < 13; ++n ) { 114 for ( int i = 0; i < nplayers; ++i ) { 115 std::cout << std::setw(16) << players[i].at(n); 116 } 117 std::cout << std::endl; 118 } 119}

library sortや、std::shuffle、std::random_shuffleなどは使ってはいけないです。

適宜置き換えておくれ。

投稿2018/10/20 13:46

episteme

総合スコア16614

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

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

amareno

2018/10/20 17:12

回答ありがとうございます。 main関数のところに下記のようにswitch文を追加してアウトプットしてみたのですが、 int main() { Deck deck; int enter; cout << "Enter 1 to shuffle, 2 to deal, or 3 to end: " << endl; do { cin >> enter; switch (enter) { case 1: deck.shuffle(); cout << "Deck shuffled." << endl; break; case 2: { // 4人のプレイヤーにカードを配る const int nplayers = 4; Player players[nplayers]; for (int i = 0; !deck.empty(); i = (i + 1) % nplayers) { Card c = deck.draw(); players[i].add(c);; } // 各プレイヤーの手札をソートする for (auto &player : players) { player.sort(); } // 各プレイヤーの手札を出力する for (int n = 0; n < 13; ++n) { for (int i = 0; i < nplayers; ++i) { std::cout << std::setw(16) << players[i].at(n); } std::cout << std::endl; } } break; case 3: cout << "Bye" << endl; break; default: break; } } while (enter != 3); } 1回目の2を押してカード配りは正常にアウトプットされますが、2回目、2を押してカード配りの選択をしてアウトプットするとlibc++abi.dylib: terminating with uncaught exception of type std::out_of_range: vectorとエラーが出ます。なぜでしょうか? 下記がアウトプットです。 Enter 1 to shuffle, 2 to deal, or 3 to end: 1 Deck shuffled. 2 Spade 2 Spade 4 Spade 6 Spade 3 Heart 3 Spade 5 Spade 9 Spade 8 Heart 4 Spade 7 Spade King Spade 10 Heart 5 Spade Ace Heart 8 Spade Jack Heart 6 Heart 2 Diamond 3 Spade Queen Heart 10 Heart 7 Diamond 5 Heart 9 Diamond 2 Heart Jack Diamond 7 Heart King Club 6 Heart Queen Diamond 8 Heart Ace Club 8 Diamond 6 Diamond 9 Diamond 4 Club 9 Diamond Queen Diamond Jack Diamond 10 Club 10 Club 2 Diamond King Diamond Ace Club Queen Club 4 Club 3 Club Jack Club King Club 5 Club 7 Club Ace 1 Deck shuffled. 2 libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: vector Process finished with exit code 6
episteme

2018/10/21 00:51

そりゃそーだ、Deckからカードをdrawし尽くせばDeckが空になるよう作ったから。
episteme

2018/10/21 00:57

で、僕のコードを質問にベタ貼りするのはなんのつもりなんだい?
amareno

2018/10/21 02:22

なるほど、回答ありがとうございます。
amareno

2018/10/21 02:29

すいません、取り下げたほうがよろしいでしょうか?epistemeさんのコードから発展させていこうと、コードを書き進めているのですが。
episteme

2018/10/21 02:35

貼るのはかまわんが出自を明記せよ。じゃないと"あなたが書いたもの"と見なされる。
amareno

2018/10/21 02:57

コードの上にコメントで明記しました。ありがとうございます。
episteme

2018/10/21 03:08

> おかしいところが多いと思います。 申し訳ない。
episteme

2018/10/21 03:12

> const int SIZE = 52; > Card deck[52]; ← これの意図は? > > class Deck { > private: > vector<Card> deck_; > Card decks[SIZE]; ← これの意図は? > ... 説明できないものを一行たりとも書いてはいけない。
amareno

2018/10/21 07:05

すいません、vectorに対する理解力がまだ十分でないので、arrayを使ってコードを書いていこうとしております。
guest

0

ベストアンサー

Card, Deck の基本動作をまずは完成させるとよいです。

  • Deck を初期化してから、Deck を頭から引いていって、Card を表示する。
  • Card の大小を比較する。

これができるようになったら、 つぎのような機能を足していきます。
Deck に suffle の機能をもたせる。
Player に 13 回ずつカードを引かせる。
Player が持っているカードを表示する。
Player が持っているカードをソートしてから、表示する。

参考情報

  • I need help generating a deck of cards in C++

https://stackoverflow.com/questions/26952727

  • Playing cards

https://rosettacode.org/wiki/Playing_cards#C.2B.2B

投稿2018/10/20 09:12

katoy

総合スコア22324

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

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

amareno

2018/10/20 17:25

回答ありがとうございます。 大変役に立つ情報と貴重なご意見ありがとうございます。 参考にしてコードを書き進めていきます。
guest

0

しょーもない回答ですが、ユーザーの入力で分岐するswitch分のところで一点。
switchで大文字小文字の差異を吸収するより、入力を小文字に変換する処理を挟んでから、switch文にかけたほうがスマートな気がします。分岐が増えるたびに、ケース分が+2行されますし、break漏れが発生しそうなので。

投稿2018/10/20 07:51

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

amareno

2018/10/20 08:26

回答ありがとうございます。 #include <algorithm>を追加してtransform(enter.begin(), enter.end(), enter.begin(), toupper);を試してみましたがエラーが出たのでchar enter を int enterにして cout <<"Enter 1 to shuffle, 2 to deal, or 3 to end: " << endl;としました。 貴重なご意見ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問