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

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

ただいまの
回答率

90.84%

  • C

    3214questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3026questions

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

  • プログラミング言語

    634questions

    プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

トランプ52枚を使ったゲームを作りたい。シャッフルしたカードを、n人のプレイヤーにすべて配るプログラムを書きたいです。

解決済

回答 10

投稿

  • 評価
  • クリップ 3
  • VIEW 1,204

carnage0216

score 95

トランプ52枚を使ったゲームを作りたい。とのことですが52は数は多く私には難易度が高いため12枚にします。
プログラム全体はまだかけていませんが部分的なプログラムは何とか考えられています。
12枚のカード(すべてハート)なので
1人に配る場合余りなし
2人に配る場合余りなし
3人に配る場合余りなし
4人に配る場合余りなし
5人に配る場合あまり2枚になります。
そこで2枚の余りを5人にどう配るかで考えています。5人の内の1人に2枚配る場合と、5人の内の2人に一枚ずつ配る場合の二つがあります。
余りが2と言ところまでは作れました。問題はこの余り2を5人にどう渡すかです。

#include<stdio.h>

int main()
{
 int hito ;
 hito=5;
 int card ;
 card=12;

 printf("%d\n",card/hito);

    }

改良後がこちらです。A,B,C,D,Eの5人の手札と余りを表示するソースです。

#include<stdio.h>

int main()
{
 int hito;
 hito=5;
 int a;
 a=1;
 int b;
 b=1;
 int c;
 c=1;
 int d;
 d=1;
 int e;
 e=1;

 int A;
 int B;
 int C;
 int D;
 int E;


 int card ;
 card=12;

 A=card%(a+b+c+d+e);
 B=card%(a+b+c+d+e);
 C=card%(a+b+c+d+e);
 D=card%(a+b+c+d+e);
 E=card%(a+b+c+d+e);
printf("Aのカードの枚数は%d\n",A);
printf("Bのカードの枚数は%d\n",B);
printf("Cのカードの枚数は%d\n",C);
printf("Dのカードの枚数は%d\n",D);
printf("Eのカードの枚数は%d\n",E);
printf("カードの余りは%d\n",card/hito);

そのあと変数Aに余りの1か2のいずれかを加算させた際のプログラムを作りました。
変数Aに1か2が加算され、1の場合は1が余るので、その1がA以外のB~Dに入ります。
そこでランダム関数を使ってプログラムを書きました。途中までしかできなかったかというか詰まってしまい途中まで書いたようなプログラムになってしまいました。途中までではありますが実行は出来ます。しかし間違った結果が出ます。
もっとスマートに読みやすいように書くにはどうしたらよりでしょうか?
やはりif文などの分岐を使って長いコードを書くのでしょうか?
アドバイスと間違いを指摘していただければと思います。
またわがままながらできる限りプログラムの原型をとどめた状態で編集していただけると大変ありがたいです。どうかよろしくお願いいたします。
書いたソースはこちらです。

#include<stdio.h>
#include <stdlib.h>
#include <time.h>


int main()
{
 int hito;
 hito=5;
 int a;
 a=1;
 int b;
 b=1;
 int c;
 c=1;
 int d;
 d=1;
 int e;
 e=1;

 int A;
 int B;
 int C;
 int D;
 int E;


 int card ;
 card=12;

 A=card%(a+b+c+d+e);
 B=card%(a+b+c+d+e);
 C=card%(a+b+c+d+e);
 D=card%(a+b+c+d+e);
 E=card%(a+b+c+d+e);
printf("Aのカードの枚数は%d\n",A);
printf("Bのカードの枚数は%d\n",B);
printf("Cのカードの枚数は%d\n",C);
printf("Dのカードの枚数は%d\n",D);
printf("Eのカードの枚数は%d\n",E);
printf("カードの余りは%d\n",card/hito);

srand(time(NULL));
int amari;
  amari = rand() % 2 + 1;
 printf("Aのカードの枚数は余りを足されて%d\n", A+amari);
int x;
amari-1;
x=amari-1;
printf("Bのカードの枚数は余りを足されて%d\n", B+x);
  return 0;


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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • ozwk

    2018/04/25 22:36 編集

    こういう仕様で作りたいって言うなら仕方ないんですが、「5人の内の1人に2枚配る場合と、5人の内の2人に一枚ずつ配る場合の二つがあります。」ってどっちかに決めないんですか?ディーラーの気分で「うーん今回はAさんに2枚!」とかやるゲームなんですか?

    キャンセル

  • can110

    2018/04/25 22:39

    まずは「どうしたい」のかを決めて提示されないと回答は得られにくいかと思います。

    キャンセル

回答 10

+6

たぶん普通にトランプのカードを配る処理を作りたいだけなんだと思いますが、アルゴリズムの立て方がまずいので非常にややこしい話になっているのでしょう。

  1. カードをシャフルする。
  2. カードに1から順番に番号を振る。
  3. カードの順番を人数で整数除算して、余りを求める。
  4. 余りの数字がすなわちそのカードを手にするべき人の番号。

こういうことではないのでしょうか。ifとか出番はないんじゃないかと思いますね。

にっちもさっちもいかなくなったときは、思い切って方針を最初から考え直すことも大切だと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+5

A: 4, B: 2, C: 2, D:2, E: 2
でゲーム開始させられる可能性のあるAさんは親みたいなロールなのでしょうか?

 問題点

 配列

カードゲームのような
同列に扱っていい要素(プレイヤー,山札,手札)がたくさん出る場合
配列の知識が必須です。

逆に配列さえ理解していれば12枚だろうが52枚だろうが大差ありません。

 アルゴリズム

それぞれに配る枚数を計算し、生成してまわる事も不可能ではありませんが
その場合、重複に気をつけなければいけません。
そして、重複をどうにかしようとすると結局山札として生成した後にシャッフルするのが楽になります。
というわけで、人の手でやるのと同様に
山札を用意して、シャッフルして、1枚ずつ配っていくのが楽です。
手札の枚数が分からんと手札領域を作れないというのなら、単純に(山札枚数+人数-1)/人数
で全員に最大1枚の余剰札が来ても大丈夫にしておいても実用上問題はないでしょう。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/27 00:12

    アルゴリズムの説明、どうもありがとうございます。
    フォローありがとうございます。

    キャンセル

+4

可能な限り原型を残しました。

#include <stdio.h>
#include <stdlib.h>

#define hito 5
#define card 52

char getName(int i)
{
    return 'A' + i;
}

void swapInt(int *buffer, int a, int b)
{
    int t = buffer[a];
    buffer[a] = buffer[b];
    buffer[b] = t;
}

void shuffleInt(int *buffer, int size)
{
    srand(time(NULL));
    for (int i = 0; i < size; i++)
    {
        swapInt(buffer, i, rand() % size);
    }
}

void dealRemainder(int remainders[], int size, int remainder)
{
    for (int i = 0; i < size; i++)
    {
        remainders[i] = i < remainder ? 1 : 0;
    }
    shuffleInt(remainders, size);
}

int main()
{
    int hands[hito];
    for (int i = 0; i < hito; i++)
    {
        hands[i] = card / hito;
        printf("%cのカードの枚数は%d\n", getName(i), hands[i]);
    }
    int remainder = card % hito;
    printf("カードの余りは%d\n", remainder);
    int remainders[hito];
    dealRemainder(remainders, hito, remainder);
    for (int i = 0; i < hito; i++)
    {
        if (remainders[i] == 0)
            continue;
        printf("%cのカードの枚数は余りを入れて%d\n", getName(i), hands[i] + remainders[i]);
    }
    return 0;
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/26 00:40

    どうもありがとうございます。真似させていただきます。

    キャンセル

  • 2018/04/26 00:45 編集

    真似して何の意味があるんですか?
    if と for と配列とシャッフルのサンプルを出しましたので C 言語のリファレンスとにらめっこしてどう使うのかだけ知ってください。
    カードの枚数だけを求めるプログラムなどトランプゲームを作る上で出番などありません。

    キャンセル

  • 2018/04/26 00:46

    わかりました。使い方を覚えます。
    手取り足取り、何から何までどうもありがとうございます。

    キャンセル

+4

最初のコードでいきなり間違えています。

余りが2と言ところまでは作れました。

printf("%d\n",card/hito);

card / hitoで求められるのは一人あたりの配った枚数です。
余りを求めたいならcard % hitoが正解です。

今回、たまたま両方とも2だったので気付かなかったのでしょうか?
カードを10枚とか11枚にしてみれば間違いに気が付くと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/27 00:17

    /だとあまりではなく商が出力されてしまうため、あまりがでる%だったのですね。
    勘違いして/があまりがでる演算子だと思っていました。
    まだまだ勉強不足です。
    勉強します。
    どうもありがとうございました。

    キャンセル

  • 2018/04/27 08:09

    /が商で、%が余りを求める演算子であるという話は、私のも含む、過去の質問回答で何度も出てきました。
    いまだ理解していただけてなかったと言うことで、残念と言うほかありません。

    キャンセル

+4

シャッフルしたカードを、n人のプレイヤーにすべて配るプログラムを書きたいです。

ごめんなさい先に書いちゃいました。

#include <iostream>
#include <string>
#include <array>
#include <vector>
#include <algorithm>
#include <numeric>
#include <random>

std::string to_card(int n) {
  static const std::string suit = "SHDC";
  static const std::string rank = "A23456789TJQK";
  return std::string(1,suit[n/13])+rank[n%13];
}

int main() {
  using namespace std;

  // 52枚のcardからなるdeck
  array<int,52> deck;
  // card #0 ~ #51で埋める
  iota(deck.begin(), deck.end(), 0); 
  // deckをシャッフル
  shuffle(deck.begin(), deck.end(), mt19937(random_device()()));

  // N人のplayer
  const int N = 5;
  vector<int> players[N];

  // deck内の各cardを playerに配る
  int c = 0;
  for ( int card : deck ) {
    players[c].push_back(card);
    if ( ++c == N ) c = 0;
  }

  // 各playerの手札を公開
  for ( auto& hand : players ) {
    cout << hand.size() << " cards: ";
    for ( int id : hand ) {
      cout << to_card(id) << ' ';
    }
    cout << endl;
  }
}

/* 実行結果
11 cards: C5 C8 H8 CQ C4 HA D8 C6 CA D2 S6 
11 cards: HK S5 S4 H7 S7 HT D9 S9 D4 H4 S8 
10 cards: S3 H2 CJ D6 DK H6 CT D3 H9 D5 
10 cards: HJ SA D7 DA C2 SJ HQ DJ CK H3 
10 cards: C7 S2 DT ST SQ C9 H5 DQ C3 SK 
*/

[追記] こっちの方がイケてるかな。

#include <iostream>  // cout, endl
#include <string>    // string
#include <vector>    // vector
#include <algorithm> // sort
#include <numeric>   // iota
#include <random>    // mt19937, random_device
#include <utility>   // pair, make_pair
#include <cassert>   // assert

class card {
private:
  int id_;
  explicit card(int id) : id_(id) {
    assert( id >= 0 && id < 52 );
  }

public:
  card() = delete;
  int suit() const { return id_ % 4; }
  int rank() const { return id_ / 4; }
  std::string suit_str() const { return std::string(1,"CDHS"[suit()]); }
  std::string rank_str() const { return std::string(1,"A23456789TJQK"[rank()]); }
  std::string str() const { return suit_str() + rank_str(); }

  static card make(int id) { return card(id); }
};

inline bool operator<(const card& a, const card& b) {
  return std::make_pair(a.rank(),a.suit()) < std::make_pair(b.rank(),b.suit());
}

inline std::ostream& operator<<(std::ostream& stream, const card& c) {
  return stream << c.str();
}

int main() {
  using namespace std;

  // N人のplayer
  const int N = 5;
  vector<vector<card>> players(N);

  // 52枚のcardからなるdeck
  vector<card> deck;
  for ( int id = 0; id < 52; ++id ) {
    deck.emplace_back(card::make(id));
  }
  // deckをシャッフル
  shuffle(deck.begin(), deck.end(), mt19937(random_device()()));

  // deckが空になるまで、cardを各playerに配る
  for ( int c = 0; !deck.empty(); ++c %= N ) {
    players[c].emplace_back(deck.back());
    deck.pop_back();
  }

  // 各playerに対し
  for ( vector<card>& hand : players ) {
    // 手札を(ソートして)公開
    cout << hand.size() << " cards: ";
    sort(hand.begin(), hand.end());
    for ( const card& c : hand ) {
      cout << c << ' ';
    }
    cout << endl;
  }
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/27 00:14

    なぜ、そんなに早く、かつ美しいプログラムが書けるのですか?
    頭の中をのぞいてみたいです。
    解読するのに一週間くらいかかりますが、上達のため頑張ります!

    キャンセル

  • 2018/04/27 05:01

    コメントでわかるけど、やりたいことを上から下へ順に並べるだけ。

    キャンセル

  • 2018/04/27 13:40

    皆さんいろんな角度から回答してますけど、煎じ詰めると指摘の本質は同じなんです。プログラミングに向いた手順というのがあるので、「自分が最初に思いついた手順」ばかり考えていてはダメ。少し角度を変えて課題を眺めてみることを覚えるのが「早く、かつ美しい」プログラムを書くには必須ですね。

    キャンセル

  • 2018/04/27 19:13

    ↑せやな。
    呈示したコードも何度となくいぢくりまわした結果やし。
    「コマケーことはいいんだよ!」から始めるのがコツかなーとか思う。

    キャンセル

  • 2018/04/27 19:34 編集

    ひとつ気になるのは、各プレイヤーに配られるカードの枚数を"事前に"求めようとしてたのよね? それはナゼ? Cでは(vectorみたいな)可変長配列の実装が面倒だから?

    キャンセル

  • 2018/04/27 21:16

    理由はCでの可変長配列の存在を知らなかった為です。

    そのため、各プレイヤーにカードを渡す全ての場合を書こうとしました。
    というのも、必ず1人は一枚以上カードを持たなくてはいけない為、プレイヤー最大で52人の場合まで書けば良いと考えたのですが♡♣️◇♠️の4種類も考慮しなければなりません。
    今思うと全ての場合を書くほうが面倒ですが、それしか思いつきませんでした。

    キャンセル

  • 2018/04/27 21:25 編集

    横着して

    struct player {
    struct card hand[52]; // 最大容量
    int size; // 実際の枚数
    ...
    };

    でもよくね?
    # てかそんなんで悩むならC++で書いちゃえよ
    # vector<card> でイッパツやんか。

    キャンセル

  • 2018/04/27 22:55

    確かにC++で書いたほうがいいかもしれません。
    C言語初心者としていきなりC++ではなくⅭのみで書こうと思いました。

    キャンセル

+3

実際にカードを配るときのことを考えてください。自分を含めた5人で配ることを考えましょうか。

親(カードを配る人)が、自分、子1、子2、子3、子4 の順に、1枚ずつ配っていきませんか?
つまり、

  1. 渡す人の配列 player[5] を作る。とりあえず、player[0]は自分自身、以下[1]が子1、[2]が子2…とする
  2. n枚のカードをシャッフルして、配列 card[n] に並べる
  3. card[x] (ただし x は 0 ~ n-1 までのループを行う)を、
    x を5で割ったあまり(x % 5) の番号の人に渡す

ということをやっているのです。

この手順(アルゴリズム)さえ理解できれば、それをプログラミング言語で書き直すだけです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

checkベストアンサー

+2

なるべく質問者さんの意図に沿ったもののつもり

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>

void swap(int8_t *b1, int8_t *b2){
  if(b1 == b2) return;
  int8_t tmp = *b1;
  *b1 = *b2;
  *b2 = tmp;
}

// バイト単位でシャッフル
void shuffle(int8_t *buf, size_t size){
  for(;size > 1;){
    int pos = rand() % size;
    size--;
    swap(buf+size, buf+pos);
  }
}
// C言語にもconstexprください
#define TRUMP_SUIT 4
#define TRUMP_JOKER_ENABLE 0
#define TRUMP_JOKER_AMOUNT 1
#define TRUMP_MAX_RANK 13
#define TRUMP_SUIT_OFFSET 6
#define TRUMP_RANK_MASK 63
const int TRUMPS = TRUMP_SUIT * TRUMP_MAX_RANK + TRUMP_JOKER_ENABLE * TRUMP_JOKER_AMOUNT;
typedef uint8_t CARD;
// xxyyyyyy
// xx : suit
// yyyyyy: rank(0 は joker)
const char* SUIT_DISPLAY[] = {
  "♤","♥","♣","♦"
};
const char* RANK_DISPLAY[] ={
  "JK",
  "A","2", "3", "4", "5", "6", "7",
  "8","9","10", "J", "Q", "K"
};
#define PLAYERS 5

bool deck_build(CARD* deck, size_t size){
  if(size < TRUMPS) return false;
  int i = 0;
  for(int j = 0; j < TRUMP_SUIT; j++)
    for(int k = 1; k <= TRUMP_MAX_RANK; k++)
      deck[i++] = (j << TRUMP_SUIT_OFFSET) | k;
  // ジョーカーの挿入
  for(int j = 0; j < TRUMP_JOKER_AMOUNT; j++)
    deck[i++] = (j << TRUMP_SUIT_OFFSET);
  return true;
}
void display_cards(CARD* cards, size_t size){
  for(int i = 0; i < size; i++){
    int suit = cards[i] >> TRUMP_SUIT_OFFSET;
    int rank = cards[i] & TRUMP_RANK_MASK;
    if(rank == 0){
      printf(" %s", RANK_DISPLAY[rank]);
      continue;
    }
    printf(" %s%s", SUIT_DISPLAY[suit],RANK_DISPLAY[rank]);
  }
  puts("");
}
int main(){
  srand(time(NULL));
  CARD deck[TRUMPS];
  deck_build(deck, TRUMPS);
  shuffle(deck, TRUMPS);
  display_cards(deck, TRUMPS);

  CARD* player_hand[PLAYERS];
  int player_hand_size[PLAYERS]={0};
  // プレイヤーの並び順
  // めんどくさいからバイトシャッフル使うためにint8_t型
  // 真面目にやる時はint型のshuffle関数を作る
  int8_t player_order[PLAYERS];
  for(int8_t i = 0; i < PLAYERS;i++) player_order[i] = i;
  shuffle(player_order, PLAYERS);

  // それぞれの手札の枚数を求める
  for(int i = 0, amari = TRUMPS % PLAYERS; i < PLAYERS; i++){
    player_hand_size[i] = TRUMPS / PLAYERS;
    if(amari > player_order[i])
      player_hand_size[i]++;
    printf("%c hand size = %d\n", 'A' + i, player_hand_size[i]);
  }

  // 配る
  CARD *current = deck;
  for(int i = 0; i < PLAYERS; i++){
    player_hand[i] = current;
    current += player_hand_size[i];
  }

  // 表示
  for(int i = 0; i < PLAYERS; i++){
    printf("%c hand:", 'A' + i);
    display_cards(player_hand[i],player_hand_size[i]);
  }
}


出力 =>

A hand size = 10
B hand size = 11
C hand size = 10
D hand size = 10
E hand size = 11
A hand: ♤Q ♤323K5109610
B hand: ♦K ♥A ♥647 ♣J ♦33 ♤J ♣5 ♦Q
C hand: ♤K29457K ♥J ♣Q ♣9
D hand: ♦6 ♦J ♤A ♣10 ♥Q ♣29747
E hand: ♣888 ♦A ♣A ♦2104658

ラムダ式とconstexprがCにも欲しいですね

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/28 15:59

    こんなの眺めてると "Cがホントに初心者向きか?" って思っちゃうよねー...

    キャンセル

  • 2018/04/28 16:07

    どうもありがとうございます。
    解読するのに時間がかかりますが頑張ります。

    キャンセル

  • 2018/04/28 16:08

    初心者向きだとC#とかですかね。名前しか知りませんが。

    キャンセル

  • 2018/04/28 16:09

    アルゴリズムとか関係ない部分で、ただただ面倒くさいですからね

    キャンセル

  • 2018/04/28 16:37

    昔から C を初心者向き、なんて書いてた書籍はなかったような? プログラミングの勉強なら PASCAL の方がよいとされてたこともありますし。(PASCAL は文法がかっちりしているので、C ほど奔放なコードがない)
    C の難関「ポインタ」にしても、素養がある(=CPUレベルでのメモリの使い方とかを知っている、当初のCの利用者層)人であれば、すんなり理解できる代物なのですし。

    キャンセル

  • 2018/04/28 17:16

    asmさん、私の勘違いかもしれませんが、載せていただいたプログラムをgcc(Mingw)でコンパイルしたところ
    C:\MinGW\TRMPSAMPUL.c:6:11: error: unknown type name 'int8_t'
    void swap(int8_t *b1, int8_t *b2){
    ^~~~~~
    C:\MinGW\TRMPSAMPUL.c:6:23: error: unknown type name 'int8_t'
    void swap(int8_t *b1, int8_t *b2){
    ^~~~~~
    C:\MinGW\TRMPSAMPUL.c:14:14: error: unknown type name 'int8_t'
    void shuffle(int8_t *buf, size_t size){
    ^~~~~~
    C:\MinGW\TRMPSAMPUL.c:30:9: error: unknown type name 'uint8_t'
    typedef uint8_t CARD;
    ^~~~~~~
    C:\MinGW\TRMPSAMPUL.c: In function 'main':
    C:\MinGW\TRMPSAMPUL.c:73:3: warning: implicit declaration of function 'shuffle' [-Wimplicit-function-declaration]
    shuffle(deck, TRUMPS);
    ^~~~~~~
    C:\MinGW\TRMPSAMPUL.c:82:3: error: unknown type name 'int8_t'
    int8_t player_order[PLAYERS];
    ^~~~~~
    C:\MinGW\TRMPSAMPUL.c:83:7: error: unknown type name 'int8_t'
    for(int8_t i = 0; i < PLAYERS;i++) player_order[i] = i;
    ^~~~~~
    とエラーが出ました。そこでヘッダファイル#include <stdint.h>を加えたところコンパイルできました。ちゃんと実行ファイルも得られました。
    初心者の私が言えることではないのですが、#include <stdint.h>を付けたほうが良いのでしょうか?

    キャンセル

  • 2018/04/28 17:23

    付け忘れですね。gcc 7.3.0では動いたのでいらんのかと思ってました。
    ありがとうございます

    キャンセル

  • 2018/04/28 17:35

    私の勘違いでなくて良かったです。編集どうもありがとうございます。

    キャンセル

+2

 人と機械

目的が次のどちらなのか、をはっきりさせた方が良いと思います。

  • 「人」がトランプを配る(動作を模倣する)プログラムを作りたい
  • 「機械」がトランプを配るプログラムを作りたい

「人」と「機械」では配り方(アルゴリズム)が異なります。

 スネ夫

C言語で作りたい、とのことですが、私には難易度が高い為、JavaScriptにします。

'use strict';
function suneo (total, players, unit) {
  const hands = Array(players).fill(0);

  play: {
    while (total) {
      for (let i of hands.keys()) {
        if (total <= unit) {
          hands[i] += total;
          break play;
        }

        total -= unit;
        hands[i] +=  unit;
      }
    }
  }

  const length = hands.filter(hand => hand > 0).length;

  if (length !== players) {
    console.log('悪いな、のび太。このゲームは' + length + '人用なんだ。');
  }

  return JSON.stringify(hands); // debug code
}

console.log(suneo(12, 5, 1));
console.log(suneo(12, 5, 2));
console.log(suneo(12, 5, 4));

スネ夫は優しくないので、余剰分も規定通りの枚数で配ります。
しずかちゃんなら公平に近い配り方をするでしょう。
あなたは誰派ですか。

Re: carnage0216 さん

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/26 00:43

    ありがとうございます。しずかちゃんの考えはいいですが、スネ夫は「余剰分も規定通りの枚数で配る」ためスネ夫派ですね。

    キャンセル

  • 2018/04/26 00:44

    私は「人」がトランプを配る(動作を模倣する)プログラムを作りたいです。

    キャンセル

  • 2018/04/26 14:00 編集

    52枚のトランプを5人に配る場合、機械なら「11+11+10+10+10」のように一度に配れます。
    人間はそうはいきませんので、1枚ずつ、2枚ずつのように小分けして配ります。
    carnage0216さんは「5人に配る場合あまり2枚」と端数以外を既に配りきった後を考えましたが、人間は小分けに配る生き物で、一度に配る枚数を指定して人間流になります。
    人間は機械よりも効率が悪いのです。

    キャンセル

  • 2018/04/28 16:10

    そうだったのですか。
    どうもありがとうございます。
    参考にさせていただきます。

    キャンセル

+1

int amari;
  amari = card%hito - rand() % 2;
 printf("Aのカードの枚数は余りを足されて%d\n", A+amari);
int x;
x=card%hito - amari;
printf("Bのカードの枚数は余りを足されて%d\n", B+x);

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

自然に考えれば余った2枚は二人に一枚づつ配るのが適切だと思います。

この場合、カード枚数が52枚と決まっているので先に配列を用意しておくと良いです。この配列をシャッフルして一枚ずつplayerに配布するとかすれば確実です。余った二枚をどうするかという本題についてですが、これはダミーを使うという方法があります。最後に余った2枚に加えて無効カードを3枚用意して1枚ずつ配布し、これを無効分を除外するといった考え方です。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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

  • C

    3214questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3026questions

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

  • プログラミング言語

    634questions

    プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

  • トップ
  • C++に関する質問
  • トランプ52枚を使ったゲームを作りたい。シャッフルしたカードを、n人のプレイヤーにすべて配るプログラムを書きたいです。