C言語でポーカーを作っているんですが その2

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
南瓜

C言語でポーカーを作っているんですが その2

#1

投稿記事 by 南瓜 » 15年前

一応、解決!を押してしまったので続きを新たに立てました
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main (void) {
    char *number[13] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};/*カードの番号*/
    int i;
    int n_hand[5];/*5枚の数字の手札*/
    
    srand(time(NULL));
    printf("[ポーカー]\n");
    printf("あなたの手札は\n");
    
    for(i = 0; i < 5; i++) {/* 五枚のカードをrandで決定 */ 
        n_hand= rand() % 13 + 1;/*数字を出す*/
    }
    for(i = 0; i < 5;  i++) {
        printf("%s ",  n_hand[5]);/* 五枚のカードを表示 */ 
    }
    
    printf("\n");
    return 0;
}

これを実行すると何回やってもA A A A Aしか実行されません
恐らく最初のfor文の所がおかしいと思うんですが、どうでしょうか?
(やっぱり配列の所の書き方が悪いんだと思うんですが)

ideyan

Re:C言語でポーカーを作っているんですが その2

#2

投稿記事 by ideyan » 15年前

>printf("%s ", n_hand[5]);/* 五枚のカードを表示 */

iが関係なくなっている上に配列の添字の範囲をオーバーしています。
(int n_hand[5];なら添字は0~4ですよね?)

conio

Re:C言語でポーカーを作っているんですが その2

#3

投稿記事 by conio » 15年前

以前も指摘されていましたが、要素が5の配列の添え字の範囲は
0~4までです。 5はありません。

------------------------------------------------------------
for(i = 0; i < 5; i++) {
printf("%s ", n_hand[5]);/* 五枚のカードを表示 */
}
------------------------------------------------------------
それとこのfor文ですが、
5回 n_hand[5]の値を表示しているだけなので当然 値は変わりません。


あとint型の値を表示したいのであれば、printf関数で指定するのは%dです。
%sではありません。

【追記】
もしかすると、
-------------------------------------
5つの値を表示したい場合は、n_hand[5]
2つの値を表示したい場合は、n_hand[2]
-------------------------------------
と指定すればよい、というイメージを持ってますか?

それは間違いです。

ゲームを作成する前に、基本の構文や配列の使い方などを
入門書などで確認するべきだと思います。 画像

box

Re:C言語でポーカーを作っているんですが その2

#4

投稿記事 by box » 15年前

最終的に出力したいのは、"A"~"K"、つまり、number[0]~number[12]の
いずれかですよね?
どれを出力したいか、つまり、number[/url]の添字の値が
n_hand[/url]に入ることになります。
number[n_hand]
という書き方です。

rand()の値を13で割った後、1を足しているのは余分です。
なぜなら、rand() % 13 の結果は0~12のいずれかであり、
それに1を加えると1~13のいずれかとなり、number[/url]の定義範囲を
超えてしまう場合があります(13のとき)。

"A"が[0]、"K"が[12]という風に、手札の数字と配列添字の値が
1つずれているのがいやであれば、
rand() % 13 + 1
はそのままにしておいて、number[/url]の先頭(number[0])に
ダミーの要素を加えるとよいでしょう。
そうすると、配列定義はnumber[14]で、手札として使う範囲は
number[1]~number[13]となり、手札の数字と添字の値が一致して
わかりやすくなるでしょう。

ookami

Re:C言語でポーカーを作っているんですが その2

#5

投稿記事 by ookami » 15年前

横から失礼します。

南瓜さんの理解度を知りたいのですが、以下のソースコードを読んで(実行せずに)、どのような出力になるか予想してみてもらえますか?
まずは int 配列に絞ってます。

■例1
int arr[3];
arr[0]=100;
arr[1]=101;
arr[2]=102;
printf("%d ",arr[0]);
printf("%d ",arr[1]);
printf("%d ",arr[2]);

■例2
int arr[3];
arr[0]=10;
arr[1]=11;
arr[2]=12;
i=1;
printf("%d ",arr);

■例3
int i;
for(i=0;i<3;i++) {
printf("%d ",i);
}

■例4
int i;
for(i=0;i<3;i++) {
printf("%d ",arr);
}

たいちう

Re:C言語でポーカーを作っているんですが その2

#6

投稿記事 by たいちう » 15年前

【一応前スレ】
http://www.play21.jp/board/formz.cgi?ac ... &rln=50642


> 【追記】
> もしかすると、
> -------------------------------------
> 5つの値を表示したい場合は、n_hand[5]
> 2つの値を表示したい場合は、n_hand[2]
> -------------------------------------
> と指定すればよい、というイメージを持ってますか?
>
> それは間違いです。
>
> ゲームを作成する前に、基本の構文や配列の使い方などを
> 入門書などで確認するべきだと思います。

そうなんですよね。
配列の使い方について、No.50638よりも後退してしまってます。

南瓜

Re:C言語でポーカーを作っているんですが その2

#7

投稿記事 by 南瓜 » 15年前

何度も同じ指摘すみませんm(_ _)m
n_hand[5]でn_hand[1]なら値は0、h_hand[2]なら値は1、……n_hand[5]なら値は4ってことですよね?
なのにfor(i = 0; i < 5; i++)でi < 5と書いているのが間違っていると
> printf("%s ", n_hand[5]);
の部分のn_hand[5]にしていた理由は、にしていると
コンパイルして実行するとずっとBus Errorが出るので,
Bus Errorの出ない[5]にしてました
原因はint型なのにずっと%sにしてたのが原因だと指摘され気づきました

次に、ookamiさんの
例1がint arr[3]; で箱を3つ用意して、arr[0]=100; arr[1]=101; arr[2]=102;と 宣言されているので
100,101,102と出力されると思います
例2が例1同じようになっていますが、i=1と宣言されているので
11が出力されると思います
例3は0から3未満まで増え続けるので
0,1,2と出力されると思います
例4は例3と同じようにarr[0],arr[1],arr[2]と出力されると思います

たいちう

Re:C言語でポーカーを作っているんですが その2

#8

投稿記事 by たいちう » 15年前

> n_hand[5]で n_hand[1]なら値は0、h_hand[2]なら値は1、……n_hand[5]なら値は4ってことですよね?

何を言っているのか判りません。


> なのにfor(i = 0; i < 5; i++)でi < 5と書いているのが間違っていると

i < 5 は間違いではないですよ。


> コンパイルして実行するとずっと Bus Errorが出るので,
> Bus Errorの出ない[5]にしてました

原因を確かめずにその場しのぎで直すのはよくないことです。


もう一度書きますが、前スレのNo.50638を参考にして、No.50666を直してみてください。

南瓜

Re:C言語でポーカーを作っているんですが その2

#9

投稿記事 by 南瓜 » 15年前

boxさんの指摘は、後回しにして先にたいちうさんの指摘から直します
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main (void) {
    char *number[13] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};/*カードの番号*/

    int i;
    int n_hand[5];/*5枚の数字の手札*/

    srand(time(NULL));
    printf("[ポーカー]\n");
    printf("あなたの手札は\n");
    
    for(i = 0; i < 5; i++) {/* 五枚のカードをrandで決定 */ 
        n_hand= rand() % 13 + 1;/*数字を出す*/

    }
    for(i = 0; i < 5;  i++) {
        printf("%d ",  n_hand);/* 五枚のカードを表示 */ 
    }
    
    printf("\n");
    return 0;
}

No.50638を参考に書き直しました。実行しても問題なく?出力されました

Poco

Re:C言語でポーカーを作っているんですが その2

#10

投稿記事 by Poco » 15年前

んでは次に、No:50245でたいちうさんがおっしゃっていた仕様

>【新しい仕様】
>1.forループでカードを配ります(randで数字とスートを決定するということ)。
>2.5枚のカードを配り終えてから、その5枚のカードを表示します。

の1.の部分をやり遂げてみては?
まだスートの決定をやっていませんよね?

たいちう

Re:C言語でポーカーを作っているんですが その2

#11

投稿記事 by たいちう » 15年前

スートを実装してもよいですし、
折角用意しているnumberの配列を使って、
AとかKとか表示できるようにしてもよいでしょう。

No.50676でBoxさんが書いていることを理解する必要があります。

ookami

Re:C言語でポーカーを作っているんですが その2

#12

投稿記事 by ookami » 15年前

おkです。

あと、

int arr[3];
arr[0]=100;
arr[1]=101;
arr[2]=102;
printf("%d ",arr[-1]); // ①
printf("%d ",arr[3]); // ②

①、②のようにするとインデックスが範囲外なので、何が表示されるかは不定ですね。この点で、冒頭の、n_hand[5]が間違っているのはideyanさんもご指摘の通りです。

次は文字列と配列について。[1]~[7]で出力される内容を予想してみてもらえますか?

char *st="A";
printf("%s ",st); // [1]

char *stArr[3]={"A","B","C"};
printf("%s ",stArr[0]); // [2]
printf("%s ",stArr[1]); // [3]
printf("%s ",stArr[2]); // [4]

int i,j;
i=1;
printf("%s ",stArr); // [5]

int arr[3];
arr[0]=1;
arr[1]=2;
arr[2]=0;
i=arr[1];
printf("%d %s ",i,stArr); // [6]

for(j=0;j<3;j++) {
i=arr[j];
printf("%d %s ",i,stArr); // [7]
}

lbfuvab

Re:C言語でポーカーを作っているんですが その2

#13

投稿記事 by lbfuvab » 15年前

キツイ言い方になりますが、一度入門書を読み直して配列を使った簡単なプログラムを組む事を勧めます。

どうも配列の取り扱いが慣れていない様に感じます。

ムンバ

Re:C言語でポーカーを作っているんですが その2

#14

投稿記事 by ムンバ » 15年前

こんばんはっ!

number[13] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};/*カードの番号*/
(前後のソース等々、略させて頂きます。)

number[0] → A
number[1] → 2
number[2] → 3
number[3] → 4
number[4] → 5
number[5] → 6
number[6] → 7
number[7] → 8
number[8] → 9
number[9] → 10
number[10] → J
number[11] → Q
number[12] → K

です。

>何度も同じ指摘すみませんm(_ _)m
>n_hand[5]でn_hand[1]なら値は0、h_hand[2]なら値は1、……n_hand[5]なら値は4ってことですよね?
  ↑これは一時、忘れて下さい。

n_hand[5] = {"A","2","3","Q","K"};/*カードの番号*/
だとしますと
カードは「"Aのカード","2のカード","3のカード","Qのカード","Kのカード"」
で、5枚のカードが用意されました。

n_hand[5] = {"A","2","3","Q","K"};/*カードの番号*/

で、この5枚のカードが、南瓜さんのソースで用意されたとします。
この5枚の用意されたカードを、何かの理由があって
南瓜さんが{"A","2","3","Q","K"}の値を呼び出したいとすると

"A" を呼び出したい時は n_hand[0](添え字 0 )
"2" を呼び出したい時は n_hand[1](添え字 1 )
"3" を呼び出したい時は n_hand[2](添え字 2 )
"Q" を呼び出したい時は n_hand[3](添え字 3 )
"K" を呼び出したい時は n_hand[4](添え字 4 )

誤字脱字があれば、ご容赦下さい。

ookamiさん(No:50752 )の、お答えが自分勝手に気になってます。^^;
南瓜さん!お時間あれば、もう一息お願いします。<(_ _)> 

---↓編集・追記---
boxさんへ(上から、すみません。<(_ _)>)
了解です。余計な事を書いてしまいました。
混乱してしまったら申し訳御座いません。 画像

box

Re:C言語でポーカーを作っているんですが その2

#15

投稿記事 by box » 15年前

> n_hand[5] = {"A","2","3","Q","K"};/*カードの番号*/

n_handは、乱数で定める1~13の数値です。
上のように書いちゃうと、質問者さんがますます混乱しそうです。
って、もう見てないかもしれないけど。

南瓜

Re:C言語でポーカーを作っているんですが その2

#16

投稿記事 by 南瓜 » 15年前

ちょっと忙しかったので返信してなかったらこんなに返信が!
先にookamiさんから
[1]はAが出力されて、[2][3][4]はstArr[0][1][2]は順にA,B,Cが順に出力されると思います
[5]はi = 1なので、stArr[1]でBが出力されると思います
[6]はi = arr[1]なので、arr[1]と2が出力されると思います
[7]は1 arr[0]、2 arr[1]、0 arr[2]が順に出力されると思います
他の返信はまた後で返信します

南瓜

Re:C言語でポーカーを作っているんですが その2

#17

投稿記事 by 南瓜 » 15年前

boxさんの指摘にあったrandの所を修正しました
int main (void) {
    char *number[13] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};/*カードの番号*/
    char *mark[4] = {"&#9829;","&#9830;","&#9824;","&#9827;"};/*カードのマーク*/

    int i;
    int n_hand[5];/*5枚の数字の手札*/
    int m_hand[5];/*5枚のマークの手札*/

    srand(time(NULL));
    printf("[ポーカー]\n");
    printf("あなたの手札は\n");
    
    for(i = 0; i < 5; i++) {/* 五枚のカードをrandで決定 */ 
        n_hand= rand() % 13;/*数字を出す*/
        m_hand = rand() % 4;/*マークを出す*/

    }
    for(i = 0; i < 5;  i++) {
        printf("%s - %s ", mark[m_hand], number[n_hand]);/* 五枚のカードを表示 */ 
    }
    printf("\n");

これをコンパイルして実行するとマークと数字両方ともちゃんと出力されるようになりました
で、次の仕様の5枚再表示ですが、ただ単にprintf("%s - %s ", mark[m_hand], number[n_hand]);
を書き足してもsegmentation faultが出る事ので、調べたらstrcpy関数を使うのかな?と思ったんですが
「s2が指す文字列を、s1が指す配列にコピーする」とあるので、
markとnumber2つの配列をコピーできるかどうかわからず困っております

たいちう

Re:C言語でポーカーを作っているんですが その2

#18

投稿記事 by たいちう » 15年前

> で、次の仕様の5枚再表示ですが、ただ単にprintf("%s - %s ", mark[m_hand], number[n_hand]);
> を書き足してもsegmentation faultが出る事ので、調べたらstrcpy関数を使うのかな?と思ったんですが

配列のコピーは必要無いですよ。
どうやったのですか?
segmentation faultの原因を理解しないまま迷走しているように思われますが。

conio

Re:C言語でポーカーを作っているんですが その2

#19

投稿記事 by conio » 15年前

>>printf("%s - %s ", mark[m_hand], number[n_hand]); を書き足しても
>>「s2が指す文字列を、s1が指す配列にコピーする」とあるので、
>>markとnumber2つの配列をコピーできるかどうかわからず困っております

--------------------------------------------------------------------
mark[m_hand]を1番目の"%s"にコピーして文字列を書き換える
number[n_hand]を2番目"%s"にコピーして文字列を書き換える
--------------------------------------------------------------------
こんな風に、printf関数は文字や文字列をコピーして表示していると解釈しているのですか?
printf関数は表示するだけで、コピーなどは行っていません。

%sや%c、%dというのは ただの書式指定子であって、
その文字列自体が書き換わっている訳では無いです。

また、値などをコピーしたら画面に表示されるという仕様でもありません。
解釈を間違えています。

南瓜

Re:C言語でポーカーを作っているんですが その2

#20

投稿記事 by 南瓜 » 15年前

for(i = 0; i < 5;  i++) {
        printf("%s - %s ", mark[m_hand], number[n_hand]);/* 五枚のカードを表示 */ 
    }
        printf("%s - %s ", mark[m_hand], number[n_hand]);
    printf("\n");

と単純に書き足しただけなのです^^;

conio

Re:C言語でポーカーを作っているんですが その2

#21

投稿記事 by conio » 15年前

for文から抜けたときのiの値を確認してください。
-----------------------------------------------------------------------------------
for(i = 0; i < 5; i++) {
printf("%s - %s ", mark[m_hand], number[n_hand]);/* 五枚のカードを表示 */
}
printf("iの値は%dです。"i);
//printf("%s - %s ", mark[m_hand], number[n_hand]);
-----------------------------------------------------------------------------------
そして、もしその値を添え字に使ったらどうなるのか?
を考えてみてください。

南瓜

Re:C言語でポーカーを作っているんですが その2

#22

投稿記事 by 南瓜 » 15年前

mark[m_hand],number[n_hand]でiを使っているのに
for文を書かなかったらiのままで出力される訳が無い^^;
と言うことですね?

conio

Re:C言語でポーカーを作っているんですが その2

#23

投稿記事 by conio » 15年前

>>mark[m_hand],number[n_hand]でiを使っているのに
>>for文を書かなかったらiのままで出力される訳が無い^^;
>>と言うことですね?
全然違います。 何を言っているのか分かりません。


もう一度詳しく言いますが、
配列のm_handと、配列のn_handの添え字の範囲は何なのか、
そして、変数iの値は何になっているのか調べてください。

それと、南瓜さんが質問したsegmentation faultというのはセグメンテーション違反
不正な場所へアクセスしようとした際などに発生します。

再度言いますが、for文を抜けた後の iの値を添え字に使ったらどうなるのか?
それを考えてみてください。

南瓜

Re:C言語でポーカーを作っているんですが その2

#24

投稿記事 by 南瓜 » 15年前

m_hand[5]の添字の範囲は0,1,2,3,4で、n_hand[5]の添字の範囲も0,1,2,3,4
変数iは、for文で0~4まで増やして各配列に代入されていくと思います。
>for文を抜けた後の iの値を添え字に使ったらどうなるのか?
ここがいまいち判んないんですが、for文がないのでint iのままで
そのままだとmark[m_hand]などは、表示されないんだと思いますが
正しいでしょうか?

conio

Re:C言語でポーカーを作っているんですが その2

#25

投稿記事 by conio » 15年前

添え字の範囲は0~4であってます。
そして、その範囲以外の値を設定してはいけない、という事もわかりますよね?
(分からない場合は、参考書などを見直してください)


>>ここがいまいち判んないんですが、for文がないのでint iのままで
for文にはよく変数としてiやjが使われますが、
iやjは別にfor文にしか使えないというものではありません。
よって、for文があるかないか、等は全く無関係です。

それと、main関数内で定義されている変数iは、main関数の最後まで有効です。
(main関数の中での有効範囲を明示的に設定しない限り)
最初にi = 10000;と代入したら、特に何もしない限り最後まで値は10000のままです。


で、さっきも書きましたが とりあえずfor文から抜けた時のiの値を
printf関数で表示してみてください。
iの値は0~4の範囲に収まってますか?
-----------------------------------------------------------------------------------
for(i = 0; i < 5; i++) {
printf("%s - %s ", mark[m_hand], number[n_hand]);/* 五枚のカードを表示 */
}
printf("iの値は%dです。\n",i); //iの値を表示してみる。
//printf("%s - %s ", mark[m_hand], number[n_hand]);  ←エラーの原因なのでコメントアウト。
----------------------------------------------------------------------------------- 画像

南瓜

Re:C言語でポーカーを作っているんですが その2

#26

投稿記事 by 南瓜 » 15年前

iの値は5であって、0~4に収まっていませんでした
いままで、何度も言われてる添字の範囲外の値が出力されていました

conio

Re:C言語でポーカーを作っているんですが その2

#27

投稿記事 by conio » 15年前

そうです。
変数には 有効範囲があり、
その範囲の中では値を保ち続けているので(書き換えが起こらない場合)
使いまわしをする際には、再度適切な代入を行って下さい。

ついでに、2番目のfor文でエラーが発生しなかったのは、
値が5になったiに、0を代入する処理が行われているからです。
---------------------------------
for(i = 0; i < 5; i++) {
//省略
}
for(i = 0; i < 5; i++) {
//省略
}
--------------------------------- 画像

南瓜

Re:C言語でポーカーを作っているんですが その2

#28

投稿記事 by 南瓜 » 15年前

大変お待たせしました
for(i = 0; i < 5;  i++) {
        printf("%s - %s ", mark[m_hand], number[n_hand]);/* 五枚のカードを表示 */ 
    }
    printf("\n");
    printf("念のため、もう一度5枚をお見せます。\n");/*もう一度同じカードを表示*/
    for(i = 0; i < 5; i++) {
        printf("%s - %s ", mark[m_hand], number[n_hand]);
    }
    printf("\n");

同じ所は省略しました。
これで、たいちうさんの仕様通りの結果が出力されました

ookami

Re:C言語でポーカーを作っているんですが その2

#29

投稿記事 by ookami » 15年前

おっと... [6]以降が違いますね... ヒントをば。

(途中のみコピー) -- ここから
arr[0]=1;
arr[1]=2;
arr[2]=0;
i=arr[1]; // ☆
printf("%d %s ",i,stArr); // [6]
-- ここまで

> [6]はi = arr[1]なので、arr[1]と2が出力されると思います

では、☆の行を i=2; と読み替えるとどうですか?読み替えてもう一度[6]の回答を。

たいちう

Re:C言語でポーカーを作っているんですが その2

#30

投稿記事 by たいちう » 15年前

> これで、たいちうさんの仕様通りの結果が出力されました

お疲れ様です。
次のステップは、カードの交換と役の判定のどちらかです。
どっちからやりたいですか?

それと何度もプログラムを動かすうちに、
5枚の手札の中に数字もスートも同じカードが現れるはずです。
本来一組のトランプでは起こりえないことですので、
まずは重複をなくす処理を追加しますか?

3つのうちで簡単なのは重複の除去ですが、
南瓜さんの好きな順番に実装してよいです。
但し、1つずつ順番に、です。

どれか次に追加する機能を決めて、どのようにすれば実装できるか、
自分なりに考えてみてください。

南瓜

Re:C言語でポーカーを作っているんですが その2

#31

投稿記事 by 南瓜 » 15年前

では、重複の除去から行おうと思います
マーク4つと数字13で配列を作ったので、[4][13]の二次元配列を新たに作って
52個分の箱を用意して、doやwhile文を使って違うマーク、数字を引くまで
引き続ける というプログラムを書き足そうと思います。

Ma

Re:C言語でポーカーを作っているんですが その2

#32

投稿記事 by Ma » 15年前

>doやwhile文を使って違うマーク、数字を引くまで
>引き続ける というプログラムを書き足そうと思います。

たまに思うのですが、この手法って間違っている気がするのですがどうでしょうか?
これだと、永遠に処理が終わらない確立がありますよね。数学的上ではありますが・・・。
まぁ、実際やると、普通そのようなことは起こらないですけど。(天文学的な可能性なので)

私はこのようなときは、最初っから手札にあるカードはランダムに選ぶときにの候補にならないような処理をしてます。
(*これは指摘ではなく、どちらかというと質問です。) 画像

たいちう

Re:C言語でポーカーを作っているんですが その2

#33

投稿記事 by たいちう » 15年前

> たまに思うのですが、この手法って間違っている気がするのですがどうでしょうか?

試行回数の期待値を考えてみてください。
5枚引くとして平均何回やりなおしがあるか?50枚引くとしたら?
期待値の数倍の処理時間でもクリティカルにならないならば、
必ずしも悪い方法ではないでしょう。

ただし擬似乱数のできが悪いなど無限ループに陥る可能性も確かにあります。
この可能性を無視できなかったり、やり直しが嫌ならば、
実際のトランプのように予め配列をシャッフルしておくのが良いでしょう。

http://ray.sakura.ne.jp/tips/shaffle.html

ちなみに私の場合だと、簡易的にはやり直しの方法で、
丁寧に作るときは配列のシャッフルです。
今回の場合だとstl::random_shuffleを使うでしょうね。


# もちろん南瓜さんは南瓜さんの方針で作ってもらってよいですよ。
# 後で気が向いたらこの部分だけ差し替えることもできます。

南瓜

Re:C言語でポーカーを作っているんですが その2

#34

投稿記事 by 南瓜 » 15年前

以下のように書き足しました
int card[4][13];/*引いたカードかを記憶する(1なら使用、0なら未使用)*/
    
for(i = 0; i < 5; i++) {/* 五枚のカードをrandで決定 */ 
    do { /*別のカードを引くまで繰り返す*/
    n_hand= rand() % 13;/*数字を出す*/
    m_hand = rand() % 4;/*マークを出す*/
    } while (card[m_hand][n_hand] == 1);/*card[4][13]と同じなら1,違うなら0*/
    card[m_hand][n_hand] = 1;/*card[4][13]に引いた情報を記憶*/

1なら使用、0なら未使用の所がうまく書けてるか不安です
実行した限りでは、同じマーク、数字は出ませんでしたが

カードのシャッフル一つでも奥が深いんだなと感心しました。が、とりあえず今は
完成させてから、そのような細かい所をどうするかを考えようと思います

たいちう

Re:C言語でポーカーを作っているんですが その2

#35

投稿記事 by たいちう » 15年前

> 1なら使用、0なら未使用の所がうまく書けてるか不安です

配列cardの初期化を忘れてはいませんよね?
掲示された部分については間違いは見当たりません。

で、次は何を追加しますか?
手札の交換か、役の判定かのどっちかだと思いますが。

南瓜

Re:C言語でポーカーを作っているんですが その2

#36

投稿記事 by 南瓜 » 15年前

int型で宣言しただけで、初期化はしてませんでした
なのでint card[4][13]の部分を以下のように書き直しました
int main (void) {
    int card[4][13] = {{0}};/*引いたカードかを記憶する(1なら使用、0なら未使用)*/
    char *number[13] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};/*カードの番号*/
    char *mark[4] = {"&#9829;","&#9830;","&#9824;","&#9827;"};/*カードのマーク*/
以下省略
これで、int card[4][13]は0で初期化されてますか?
書き方が正しかったら、次はカードの交換を行いたいです

hoge

Re:C言語でポーカーを作っているんですが その2

#37

投稿記事 by hoge » 15年前

>これで、int card[4] [13]は0で初期化されてますか?

YES

でも俺なら
 int card[4][13] = {{0}};
こんな中途半端な描き方しないで
 int card[4][13] = {0};
こうする。

それと配列宣言で初期値を書くときは配列サイズは勝手にあわせてくれるので
char *mark[/url] = {"&#9829;","&#9830;","&#9824;","&#9827;"};
これでいい。その方が間違えた値を入れてしまう心配がない。
ただし右辺がない場合は
 char *mark[4];
こうしないと、エラーになる。
画像

南瓜

Re:C言語でポーカーを作っているんですが その2

#38

投稿記事 by 南瓜 » 15年前

確かに{{0}}より{0}の方がすっきりして見えますね
[/url]に値を入れない方法は、本にも書いてありました。
同じ結果になるのに書き方は、ほんといろいろあるんだなと
驚きます。どっちにするかは慣れなんだろうけど、最初は値を入れようと思います

5枚を表示→scanfで交換するカード(1~5)を選択(これ辺をどう書くかがいまいち漠然としか思いつかない)
→選んだカードのみrandで選び直す→選んだカード、選ばなかったカード合わせて5枚を表示

交換しない場合はscanfで0を押す→そのまま再表示と言う流れでいこうかと思ってます

box

Re:C言語でポーカーを作っているんですが その2

#39

投稿記事 by box » 15年前

> どっちにするかは慣れなんだろうけど、最初は値を入れようと思います

配列の要素数なんてのはコンピューターに数えさせる、
という考え方もありかな、と思います。

たいちう

Re:C言語でポーカーを作っているんですが その2

#40

投稿記事 by たいちう » 15年前

> 5枚を表示→scanfで交換するカード(1~5)を選択(これ辺をどう書くかがいまいち漠然としか思いつかない)

前スレでも書きましたが、
例えば次の様な入力方法はいかがですか?

0 : 交換なし
4 : 4枚目を交換
135 : 1枚目・3枚目・5枚目を交換
12345 : 全部交換

ご検討ください。

# 前スレへのリンクが切れてしまっているので、一応貼りなおし。
# http://www.play21.jp/board/formz.cgi?ac ... &rln=50642

南瓜

Re:C言語でポーカーを作っているんですが その2

#41

投稿記事 by 南瓜 » 15年前

int i, j; 新しく変数jを書き足して
printf("カードを交換する場合1~5を入力して下さい(0は交換しない) > ");
    scanf("%d", &j);
    while (getchar() != '\n') { }
    if(j != 0) 
    for(j = 0; j < 5; j++) {
        printf("%s - %s ", mark[m_hand[j]], number[n_hand[j]]);
    }
    if (j == 0) 
    printf("念のため、もう一度5枚をお見せます。\n");/*もう一度同じカードを表示*/
    for(i = 0; i < 5; i++) {
        printf("%s - %s ", mark[m_hand], number[n_hand]);
    }

交換しない=0を選んだ時は、いいんですがそれ以外1~5を選んだとき
if(j != 0)以下をどう書けばいいのか判りません
この書き方だとまた5枚表示して、計10枚表示される書き方になると
思ってましたが、交換したい配列を選んで、そこだけrandで選び直す
書き方が思いつきません

たいちう

Re:C言語でポーカーを作っているんですが その2

#42

投稿記事 by たいちう » 15年前

今までのプログラムはしばらく忘れ、必ず新しいプログラムを作ってください。
(今までのプログラムを間違って消さないように!)
こんな入出力を作ってください。
カードの実体も交換も不要です。ユーザーインタフェースだけです。

【Step 1】
入力方法の説明 > 135
あなたの入力した数値は 135 でした。

【Step 2】
入力方法の説明 > 135
あなたの入力した数値は 135 でした。
1枚目のカードを交換します。
3枚目のカードを交換します。
5枚目のカードを交換します。

Step1はできますよね?
まずはそれをここに載せ、Step2の方法を考えてみてください。

南瓜

Re:C言語でポーカーを作っているんですが その2

#43

投稿記事 by 南瓜 » 15年前

おまたせしました
int main (void) {
    int i;
    
    printf("入力方法の説明 > ");
    scanf("%d", &i);
    printf("あなたの入力した数値は%dでした。\n", i);
    return 0;
}
変数を増やして表現する?
%d枚目のカードを交換します。, i
%d枚目のカードを交換します。, j
%d枚目のカードを交換します。, k
みたいに でもこのやり方だとものすごくまどろっこしいですよね

たいちう

Re:C言語でポーカーを作っているんですが その2

#44

投稿記事 by たいちう » 15年前

> 変数を増やして表現する?
> %d枚目のカードを交換します。, i
> %d枚目のカードを交換します。, j
> %d枚目のカードを交換します。, k
> みたいに でもこのやり方だとものすごくまどろっこしいですよね

変数を増やして表現する、というのがどんな方法か判りませんが、
もっと良い方法が思いつかないなら仕方ないでしょう。
後でいくらでも改良することができますので、まずは動くものを作りましょう。
考えてみて下さい。

南瓜

Re:C言語でポーカーを作っているんですが その2

#45

投稿記事 by 南瓜 » 15年前

変数を増やしても思った感じに成らなかったので
それっぽく動きそうなのにしました
int main (void) {
    int i, j;
    
    printf("入力方法の説明 > ");
    scanf("%d", &i);
    printf("あなたの入力した数値は%dでした。\n", i);
    for(j = 0; j < i; j++) {
        printf("%d枚目のカードを交換します。\n", i);
    }
欠点は、13入力すると13回処理を行うのと1 3とすると
スペースを認識せずに1として認識して処理をする所です

conio

Re:C言語でポーカーを作っているんですが その2

#46

投稿記事 by conio » 15年前

--------------------------------------------------------
int main (void) {
int i, j;

printf("入力方法の説明 > ");
scanf("%d", &i);
printf("あなたの入力した数値は%dでした。\n", i);
for(j = 0; j < i; j++) {
printf("%d枚目のカードを交換します。\n", i);
}
return(0);
}
--------------------------------------------------------

これは、やり方がおかしいです。
35と入力したら
----------------------------
0枚目のカードを交換します。
1枚目のカードを交換します。
2枚目のカードを交換します。
3枚目のカードを交換します。
:
:

31枚目のカードを交換します。
32枚目のカードを交換します。
33枚目のカードを交換します。
34枚目のカードを交換します。
----------------------------
こんな風になってしまいます。


あと数字の間にスペースを空けて入力するのではなく、
135(ひゃくさんじゅうご)と入力したら
1(いち)と3(さん)と5(ご)と分離して読み込む方法を考えてみてください。

【追記】
混乱しそうなので追記。
ゲームの仕様を実装出来ればいいので、やり方は好きな方法を選んで下さい。 画像

たいちう

Re:C言語でポーカーを作っているんですが その2

#47

投稿記事 by たいちう » 15年前

> 欠点は、13入力すると13回処理を行うのと1 3とすると
> スペースを認識せずに1として認識して処理をする所です

そのようなプログラムを書いてしまったのだから当然です。

色々方法はありますが、入力を文字列として受け取ってみてください。
想定外の入力に対する処理も後回しにして、13という入力を
"13"という文字列として受け取って、Step 1を作れますか?
Step 2は?

南瓜

Re:C言語でポーカーを作っているんですが その2

#48

投稿記事 by 南瓜 » 15年前

遅くなりました
char change[/url] = "012345";
    
printf("入力方法の説明 > ");
scanf("%s", change);
while(getchar() != '\n') {}
printf("あなたの入力した数値は%sでした。\n", change);
printf("%s枚目のカードを交換します。\n", change);
こういうことでしょうか?

たいちう

Re:C言語でポーカーを作っているんですが その2

#49

投稿記事 by たいちう » 15年前

> こういうことでしょうか?

当然違います。
No:51076に書いた仕様を満たしていません。
"135"と入力すれば判るでしょう。

# 違うということは自分で気付けたと思うのですが。
# もしも気付いていたのならば、無駄なやり取りは避けましょう。
# 掲示板での一回のやり取りで数時間から数日かかる場合、
# 問題解決がその分遅れて損するのは誰ですか?
# もっと上手に掲示板と私を利用してください。

南瓜

Re:C言語でポーカーを作っているんですが その2

#50

投稿記事 by 南瓜 » 15年前

char change[7] = "012345";
    
    printf("入力方法の説明 > ");
    scanf("%s", change);
    while(getchar() != '\n') {}
    printf("あなたの入力した数値は%sでした。\n", change);
    printf("%s枚目のカードを交換します。\n", change);

    return 0;
本で調べたり、ネットで調べましたが
どうしてもstep2の仕様ができません
どの知識を使えばいいのかもわからず
完全に手詰まりです

Ma

Re:C言語でポーカーを作っているんですが その2

#51

投稿記事 by Ma » 15年前

>たいちうさん
conio さんも言っているとおり、いっそのこともっとやさしい仕様にしてはいかがでしょうか。
桁でコントロールではなく、一回一回入力する方針でもいいんじゃないでしょうか?

目的にそぐわない方法でしたら無視してください。

*追記
彼の仕様を使いint型で読み込むなら、以下のようなアポローチが可能だと思います。

1桁目
change%10

2桁目
int temp = change - 1桁目
(temp%10)/10

....

や、
5桁目
change/10000

4桁目
(change%10000)/1000

...

などが思いつきます。*深く考えていないので穴だらけかも。
あと、当然想定外の値や文字が来た場合の判定もしなくてはなりません。 画像

たいちう

Re:C言語でポーカーを作っているんですが その2

#52

投稿記事 by たいちう » 15年前

それではもう少しヒントを。

【Step 2】
入力方法の説明 > 135
あなたの入力した文字列は 135 でした。
文字列の長さは 3 です。
1 文字目は 1 です。
2 文字目は 3 です。
3 文字目は 5 です。


> 桁でコントロールではなく、一回一回入力する方針でもいいんじゃないでしょうか?

それでもよいです。しかし複数回の入力を処理するほうが難しいと思ってのこの仕様です。

南瓜

Re:C言語でポーカーを作っているんですが その2

#53

投稿記事 by 南瓜 » 15年前

int i;
    char change[6] = "12345";
    char *p1;
    
    p1 = change;
    printf("入力方法の説明 > ");
    scanf("%s", change);
    while(getchar() != '\n') {}
    printf("あなたの入力した数値は%sでした。\n", change);
    printf("文字列の長さは%dです。\n", strlen(change));
    for(i = 1; i <= strlen(change); i++) {
            printf("%d文字目は%cです。\n", i, *p1+i-1);
    }
だいぶ言われた仕様に近づいたと思います
(0や6以上を打ち込んだ時の対処法はまだですが)
打ち込んだ回数ループする仕様は問題ないとおもうんですが、
「?文字目は?です」の所が123や345とかは、仕様通りになるのですが
(たまたまうまくいってるだけ?)135だと
1文字目は1、2文字目は2、3文字目は3のように出力されてしまいます
直す所は「*p1+i-1」の部分だと思うんですが、どのように直せばいいでしょうか?

たいちう

Re:C言語でポーカーを作っているんですが その2

#54

投稿記事 by たいちう » 15年前

for(i = 0; i < strlen(change); i++) {
    printf("%d文字目は%cです。\n", i + 1, change);
}

これで行けるんじゃないかと。
p1は不要ですし、changeの初期値も不要です。
十分な領域が必要なだけなので、
char change[10]; とでもしておけばよいでしょう。

Step 3ですが、forループの中を次のように変えてください。
int n = ???;
printf("%d文字目は%dです。\n", i + 1, n);

南瓜

Re:C言語でポーカーを作っているんですが その2

#55

投稿記事 by 南瓜 » 15年前

指摘通り直したらうまくいきました
for(i = 0; i < strlen(change); i++) {
        int n = ???;
            printf("%d文字目は%dです。\n", i+1, n);
    }
ただ、step3のint n = ???;の意味がわかりません
というよりコンパイルできません
?は条件演算子を指しているんでしょうか?

box

Re:C言語でポーカーを作っているんですが その2

#56

投稿記事 by box » 15年前

> ?は条件演算子を指しているんでしょうか?

考えすぎ。
「何を書けばよいですか?」という問いかけです。

南瓜

Re:C言語でポーカーを作っているんですが その2

#57

投稿記事 by 南瓜 » 15年前

for(i = 0; i < strlen(change); i++) {
        int n = change;
            printf("%d文字目は%cです。\n", i+1, n);
    }

step2と同様の結果が得られたんですが、これはたいちうさんの
意図する仕様になったでしょうか?
特に%dじゃなくて%cにしてしまった所が気にかかる…
でも%dじゃstep2と同様の結果が得られないし…

たいちう

Re:C言語でポーカーを作っているんですが その2

#58

投稿記事 by たいちう » 15年前

> step2と同様の結果が得られたんですが、これはたいちうさんの
> 意図する仕様になったでしょうか?
> 特に%dじゃなくて%cにしてしまった所が気にかかる…

%dで表示することが目的です。
なぜならば、入力を配列の添え字に変換する必要があるからです。

> でも%dじゃstep2と同様の結果が得られないし…

どんな結果になりましたか?
その結果は何を表していますか?
その結果をどのように加工したら望む結果が得られますか?

Ma

Re:C言語でポーカーを作っているんですが その2

#59

投稿記事 by Ma » 15年前

文字列 数字 変換
とかって検索。

atoi

南瓜

Re:C言語でポーカーを作っているんですが その2

#60

投稿記事 by 南瓜 » 15年前

int n = atoi(change);
printf("%d文字目は%dです。\n", i+1, n);
%dだと1が49と出力されていたので
調べた所ASCIIコードが関与してることが判ったので
文字列を10進法に替えるatoiを使いました
次のステップは123と入力すると123と返ってくるので
atoiを使ってstep2の仕様にするのでしょうか?

たいちう

Re:C言語でポーカーを作っているんですが その2

#61

投稿記事 by たいちう » 15年前

> atoiを使ってstep2の仕様にするのでしょうか?

私はatoiの使用はお勧めしません。
atoiは文字列を数値に変換する関数ですが、
今回は1文字ずつ処理した方が簡単なので、
文字から数値への変換が必要です。

'1'という文字はASCIIコードで49です。
'2'という文字はASCIIコードで50です。
...

nの求め方が判りませんか?

南瓜

Re:C言語でポーカーを作っているんですが その2

#62

投稿記事 by 南瓜 » 15年前

int n = change - '0';
        printf("%d文字目は%dです。\n", i+1, n);

これでいいでしょうか?
これなら%dでもいままでと変わらずの結果になるので…

たいちう

Re:C言語でポーカーを作っているんですが その2

#63

投稿記事 by たいちう » 15年前

> これでいいでしょうか?

OKです。
そろそろポーカーに戻って、出来るところまで作ってください。

南瓜

Re:C言語でポーカーを作っているんですが その2

#64

投稿記事 by 南瓜 » 15年前

とりあえず、カード交換らしき所だけ書きました
38~45行目は、条件文のchangeの変数の所が書き方が
いけないと思うんですが、どのように書き換えればいいでしょうか?
(changeをjとかに替えたらちゃんとif文は機能しました。ただその後はエラーが出ましたが…)
46-53行目は、コンパイルできなかったため、考え方自体が根本から間違っているかまでは判りませんでした
(char型なのにint型に代入しようとするやり方がいけないのだとは思うのですが…
交換する時は、あのように一時的に他の変数に代入するのだと本に書いてあったのですが
ちゃんと理解してなかったのか?)

たいちう

Re:C言語でポーカーを作っているんですが その2

#65

投稿記事 by たいちう » 15年前

色々まずいですが、致命的なのは同じ指摘を何度も受けていることです。
forループの外にiがありますが、このiには何が代入されていると思いますか?

それと交換の部分ですが、複数枚交換するため、交換の処理は
複数回呼ばれなければいけません。
こんな感じに。
for(i = 0; i < strlen(change); i++) {
    int n = change - '0';
    printf("%d枚目のカードを交換します。%s - %s\n", n, mark[m_hand[n-1]], number[n_hand[n-1]]);
    /* カード交換の処理 */
    printf("%d枚目のカードを交換しました。%s - %s\n", n, mark[m_hand[n-1]], number[n_hand[n-1]]);
}

南瓜

Re:C言語でポーカーを作っているんですが その2

#66

投稿記事 by 南瓜 » 15年前

前のfor文によりiには5が代入されているままだと思います
同じ指摘何度もされて申し訳ないです
本やサイトで勉強し直してるのですが中途半端な理解のままだと
痛感しています
本当にすみません

たいちう

Re:C言語でポーカーを作っているんですが その2

#67

投稿記事 by たいちう » 15年前

謝ってもらう必要はないのですが、理解することを大切にしないと上達は望めません。
「この様な場合にはどうしたら良いか?」という質問に対しては、
答えるだけなら答えやすいのですが、それを延々と繰り返すことが上達につながるでしょうか?

1つ指摘を受けた時、それを適用してプログラムが動けばそれで良しとしていませんか?
言われるままに直す人と、何故駄目だったのかを理解して直す人は違います。
これを繰り返していけば、表面的には同じものが出来上がったとしても、
身に着く実力は比べ物にならないでしょう。
もしも指摘が理解できない場合は、入門書などを読み返さないといけません。
それでも理解できない場合は、再度質問しなければいけません。

前スレの最初のプログラムをスタートとして、
カードの交換と役の判定の完成をゴールと考えると、
今は大体半分くらいの完成度という印象です。
今まで言われるままに直していたのならば、同じだけの手間がかかりますが、
今までで理解が深まっているのならば、後半はもっと楽でしょう。

行き詰った場合、前スレとこのスレのどこかからヒントが得られる場合もあるでしょうから、
質問の回答を待つ間に全体を読み直すことも有効でしょう。
完成まで付き合うつもりですので、焦らず頑張ってください。

box

Re:C言語でポーカーを作っているんですが その2

#68

投稿記事 by box » 15年前

> 前のfor文によりiには5が代入されているままだと思います

そうなのかどうかは、当該のfor文を抜けた直後で
printf()してみるとすぐにわかりますね。

「~だと思います」ではなくて、コードを書いて
自分で確認しましょう。

南瓜

Re:C言語でポーカーを作っているんですが その2

#69

投稿記事 by 南瓜 » 15年前

printfを使った所、iなら5、changeは?でした。
if文の条件式がうまくいかないのは初期化していないchange
書いていたから?変数を変えればうまくいく?
かといってscanfで入力した値を元にfor文に入る前にif文で判断させたい訳だし
changeを変えてしまったらfor文のchangeが機能しないし…
38~45行目のif文の所を修正するには、if,配列の他にどの辺の知識がいりますか?

たいちう

Re:C言語でポーカーを作っているんですが その2

#70

投稿記事 by たいちう » 15年前

> 38~45行目のif文の所を修正するには、if,配列の他にどの辺の知識がいりますか?

自分で考える力と、人からの指摘を理解する力。
if文をどのように修正したいのですか?

南瓜

Re:C言語でポーカーを作っているんですが その2

#71

投稿記事 by 南瓜 » 15年前

38~45行目のif文を前のscanfで入力した値を元に分岐させたいです
1~5なら交換する処理を、0なら交換しませんと処理、それ以外なら
もう一度値を入力するように促す処理です
特に判断する変数の所です
if(1 < ???) && (??? < 5)

Ma

Re:C言語でポーカーを作っているんですが その2

#72

投稿記事 by Ma » 15年前

for(i = 0; i < strlen(change); i++) {
int n = change - '0';
if ((1 <= n) && (n <= 5)) {
printf("%d枚目のカードを交換します。%s - %s\n", n, mark[m_hand[n-1]], number[n_hand[n-1]] );
}
else if(n == 0)
printf("0なので交換しません。\n");
}

これでどうですか?
あと、何が間違っていたのか指摘すれば、
change を比較しているなら、int n = change - '0';の教訓を忘れていませんか?
for文でチェックしないと、入力された文字数がいくつであっても対応することができないと思いませんか?

*注意:この方法では、毎カード 0 の可能性を比較しています。
もし、最初の一回だけでいいなら、

if(change[0] == '0'){
printf("0なので交換しません。\n");
}
else{
for(i = 0; i < strlen(change); i++) {
int n = change - '0';
printf("%d枚目のカードを交換します。%s - %s\n", n, mark[m_hand[n-1]], number[n_hand[n-1]] );
}
}

こちらのほうが好ましいかも。 画像

ムンバ

Re:C言語でポーカーを作っているんですが その2

#73

投稿記事 by ムンバ » 15年前

こんばんは?!

飛び込み、ごめんなさい。(謝
プログラミングは、相変わらず初心者です。

>>こちらのほうが好ましいかも。

 南瓜さんが、ポーカーを作る過程での質問ですので
 好ましいか好ましくないかは、南瓜さんが決める事だと思います。

勝手にずっと最初から、このスレを傍観させて頂いてます。
南瓜さんの自作のポーカー、完成できる事を祈ります。
余計なお世話かと思いますし、なんにもお役に立てませんが
南瓜さん、がんばってると思うんですよね。(間違ってたら、ごめんなさい。)

オリジナルのポーカーの完成、応援させて頂きます。
ぜひ、完成までがんばって下さいっ!
(この私のコメント、レス無し希望です。宜しくお願い致します。)

南瓜

Re:C言語でポーカーを作っているんですが その2

#74

投稿記事 by 南瓜 » 15年前

ookamiさん すみません 読み飛ばして返信に気づきませんでした
%dはarr[1]が出力がされて、%sはstArr[arr[1]]となってstArr[2]で正しいでしょうか?

確かに先にif文を書いてしまったら対応できませんよね
Maさんが案を提案してくれたので、0~5以外の数字を入力したとき
0~5を入力するまでループする機能を付けてから投稿しようとしたら
遅くなりました。しかしゴチャゴチャな出来になってしまって…

この仕様が特に問題なかったらカード交換に移りたいと思います
複数回呼び出すという事は
mark[m_hand[n-1]] = m_temp[n-1];
    m_temp[n-1] = c_m_hand[m_hand[n-1]];
    c_m_hand[m_hand[n-1]] = mark[m_hand[n-1]];
これを複数回実行すればいいということですか?

たいちう

Re:C言語でポーカーを作っているんですが その2

#75

投稿記事 by たいちう » 15年前

> これを複数回実行すればいいということですか?

実行時エラーになるでしょう。いや、処理系依存かな。
いずれにしても、やってみればうまくいかないことは判ります。
私個人の意見ですが、できればこのような質問は避けるべきです。
質問の仕方・掲示板の有効な使い方についても考えてみて下さい。


まだ躓いているようですので、少し簡単な仕様を考えてみました。

1.カードを5枚選択。
2.カードを5枚表示。
3."1"が入力されたものとする。(strcpy(change, "1"); と書く)
4.1枚目のカードを交換。
5.カードを5枚表示。(新しいカードと、元の4枚のカードが表示される)

カードの交換とは何を意味しているのか、考えてみて下さい。

南瓜

Re:C言語でポーカーを作っているんですが その2

#76

投稿記事 by 南瓜 » 15年前

しばらく、本やネットでstrcpyについて調べてたんですが
ファイルだと31~33の所の???の書き方が判りません

カードの交換は、値を交換すると言うこと?

strcpyは文字列をコピーしてもう一つの配列にコピーするのと
temp = x;
    x = x[j];
    x[j] = temp;

のような値の交換って何が違うんですか?

Ma

Re:C言語でポーカーを作っているんですが その2

#77

投稿記事 by Ma » 15年前

>カードの交換は、値を交換すると言うこと?
はい。

>何が違うんですか?
文字通り、コピー、と交換の違いです。

x = x[j];
これで、コピー。
片方、上書きされるほうのデータは消失します。


temp = x;
x = x[j];
x[j] = temp;

これで交換。
一時的に、上書きされるほうのデータを新しく作った変数でとっておくことでデータの消失を防ぎます。
もちろん、実際には strcpy の内部はこんなシンプルではないでしょうが。

たいちう

Re:C言語でポーカーを作っているんですが その2

#78

投稿記事 by たいちう » 15年前

本筋を見失っています。

私の仕様が要求しているのは、
「"1"が入力された時は、正しく動作する」という事です。
入力は、"1"だったり、"14"だったり、"12345"だったりしますので、
これらの全てに対応したプログラムが必要ですが、
初めの一歩として、"1"に対応させましょう、ということ。

毎回"1"を入力するのが面倒だろうから、changeに"1"を代入したら楽だよ、
という意味で、strcpyを提案しました。
strcpyを使ってカードを交換するわけではありません。
strcpyの使い方が判らないならば、毎回"1"を入力してください。


次に、Maさんの説明だと判りにくいのではないかと思うので、
私からも交換について説明します。

南瓜さんはソートのプログラムを作ったことがあるでしょうか?
ソートのプログラムの基本的な要素として、値の比較と値の「交換」があります。
この交換はしばしば次の様に書かれています。

> temp = x;
> x = x[j];
> x[j] = temp;

カードの交換を実装しようという時に、「交換」の意味を深く考えずに
上述の「交換」を使おうという事が間違いです。
実際にトランプでポーカーをするときに、手札を一枚「交換」するということは、
手札のうちの一枚を場に移し、山から新しいカードを一枚引くことです。
実装すべきなのは、この動作です。
同じ「交換」でも、ソートのプログラムの「交換」とは全然似てないことが判るでしょう。

南瓜

Re:C言語でポーカーを作っているんですが その2

#79

投稿記事 by 南瓜 » 15年前

Maさん、説明ありがとうございます
ソートのプログラムは、本やネットで見ただけで、使えるかな?
と思っただけでそこまで考えてませんでした^^;
>手札のうちの一枚を場に移し、山から新しいカードを一枚引くことです。
>実装すべきなのは、この動作です。
ということは、step1としてはまた山札から引き直す処理を書き加えれば達成?
ただ、この書き方だと交換する枚数の位置を指示できないから
(5と入力すると5枚全て交換されてしまう…)
また新たな処理(int n = change - '0'以降のやつ)を作る?
でも書き足したらうまくいかなかったので書き足す前のやつを載せました。

言葉が同じ交換でもその交換する手段は異なるんですね

たいちう

Re:C言語でポーカーを作っているんですが その2

#80

投稿記事 by たいちう » 15年前

> ただ、この書き方だと交換する枚数の位置を指示できないから
> (5と入力すると5枚全て交換されてしまう…)

forループを二重にしてはいけません。

> printf("%d枚目のカードを交換します。%s - %s\n", n, mark[m_hand[n-1]], number[n_hand[n-1]] );
> /* カード交換の処理 */
> printf("%d枚目のカードを交換しました。%s - %s\n", n, mark[m_hand[n-1]], number[n_hand[n-1]]);

"/*カード交換の処理*/"と書かれている部分で、1枚だけ交換です。

南瓜

Re:C言語でポーカーを作っているんですが その2

#81

投稿記事 by 南瓜 » 15年前

とりあえずこれで”1”と入力すれば1枚だけ交換して
新しい1枚と元の4枚が表示されるようになりました。

forループを二重にしてはいけないのは
最初のforループの中で 次のforループが繰り返されて
しまうからですよね?

たいちう

Re:C言語でポーカーを作っているんですが その2

#82

投稿記事 by たいちう » 15年前

> forループを二重にしてはいけないのは
> 最初のforループの中で 次のforループが繰り返されて
> しまうからですよね?

その理由も十分ではありません。
結局のところ、二重にする必要がない、というのが理由です。


> とりあえずこれで”1”と入力すれば 1枚だけ交換して
> 新しい1枚と元の4枚が表示されるようになりました。

それでは、他の入力も試してください。
(何度も書いていますが、勝手に次のステップに進んでください)

南瓜

Re:C言語でポーカーを作っているんですが その2

#83

投稿記事 by 南瓜 » 15年前

No:51901の書き方だと
1から連番(123とか12345とか)で入力すれば無事交換できるのですが
2以降や135などの入力すると場所指定が出来ずに打ち込まれた数
135なら135枚目を交換するのではなく、123枚を交換してしまうのは
for文のstrlen(change)によると推測してるのですが、ここを変えてしまっては
元も子もないので、少しヒントを頂けないでしょうか?

たいちう

Re:C言語でポーカーを作っているんですが その2

#84

投稿記事 by たいちう » 15年前

for(i = 0; i < strlen(change); i++) {
    int n = change - '0';
    if ((1 <= n) && (n <= 5)) {
        printf("%d枚目のカードを交換します。%s - %s\n", n, mark[m_hand[n-1]], number[n_hand[n-1]] );

        int index = n - 1;
        // i ではなくて、indexを使ってください。ここから
        do {
            n_hand= rand() % 13;
            m_hand = rand() % 4;
        } while (card[m_hand][n_hand] == 1);
        card[m_hand][n_hand] = 1;
        // ここまで。
        
        printf("%d枚目のカードを交換しました。%s - %s\n", n, mark[m_hand[n-1]], number[n_hand[n-1]]);
    } else if (n == 0) {
        printf("0なので交換しません。\n");
    }
}

i, n, indexがそれぞれ何を表すのか、正確に理解していないとプログラムは作れませんよ。
「正確に理解」という言葉の目安は、第三者に正確に説明できる程度、と考えてください。

南瓜

Re:C言語でポーカーを作っているんですが その2

#85

投稿記事 by 南瓜 » 15年前

変数iは0で初期化して、strlen(change)まで増加する
変数nはchange-'0'により入力した文字を数値に変換し
ifが1<=n<=5のとき、交換する処理になる
nは打ち込んだ数字が表示され、
mark~、number~がn-1なのは、配列の添字が0から始まるから。
変数indexはn-1なのも、これも配列の添字が0から始まるから
n-1で、nはすでに数値変換しているから入力した数字から1引かれる事で
正しい配列の添字になっている。
最期にn=0なら交換しない処理をする
どうでしょうか?正しい説明になってますか?

もし、正しかったら残りは役を判断する所だと思うので
役を判断する処理として、64~65行目の書き方というより
考え方の方向性は正しいでしょうか?正しかった場合、これにあと何を書き足せば
処理がうまくいくのか、ご指摘お願いします。

たいちう

Re:C言語でポーカーを作っているんですが その2

#86

投稿記事 by たいちう » 15年前

> どうでしょうか?正しい説明になってますか?

間違ってはいないと思うけど、この説明からは
南瓜さんが正しく理解している、とまでは判断できません。
今までのやり取りを見ると特に。

「自分が理解している」と主張するためにも、
「自分の理解は正しい?」と質問するためにも、
国語の力が必要です。これももっと磨いてください。


> 役を判断する処理として、64~65 行目の書き方というより
> 考え方の方向性は正しいでしょうか?正しかった場合、これにあと何を書き足せば
> 処理がうまくいくのか、ご指摘お願いします。

方向性も何も、何か考えがあるようには見えません。
実際に配られたトランプを見て、フラッシュかどうか、
どのように判断していますか?
まずは、日本語で丁寧に書いてみましょう。

# 「交換」という言葉を深く考えなかった反省も生かして下さいね。

南瓜

Re:C言語でポーカーを作っているんですが その2

#87

投稿記事 by 南瓜 » 15年前

今フラッシュ、ストレートの役の判定を作っている途中で
フラッシュは、うまくいったんですがストレートで苦戦してます
(この書き方だとSegmentation faultが出るので、74~82行は/**/を
使ってます)
Segmentation faultが出るという事は、74~82行目の書き方が
悪いんでしょうが、何処がいけないんでしょうか?

たいちう

Re:C言語でポーカーを作っているんですが その2

#88

投稿記事 by たいちう » 15年前

> Segmentation fault が出るという事は、74~82行目の書き方が
> 悪いんでしょうが、何処がいけないんでしょうか?

実行時エラーの原因は、配列の範囲を超えているから。
配列のインデックスは、0~4までです。

> int n_hand[5];/*5枚の数字の手札*/

それと、どうしてこのプログラムでストレートの
判定ができると考えているのですか?
この辺に南瓜さんの根本的な問題があると思います。

例によって第一段階の仕様はできるだけ簡単にしたいので、
キングとエースはつながっていなくても結構です。

南瓜

Re:C言語でポーカーを作っているんですが その2

#89

投稿記事 by 南瓜 » 15年前

int n_hand[5]で範囲指定してるのに、i+4や[12]は超えてしまう
またやってしまったorz

12345( [i+1]…)やA10JQK([0] [9]…)のストレートをどう表現すればいいかな
と思いあのような書き方をしました
あぁ…orz

たいちう

Re:C言語でポーカーを作っているんですが その2

#90

投稿記事 by たいちう » 15年前

> 12345( [i+1]…)やA10JQK([0] [9]…)のストレートを
> どう表現すればいいかなと思い

ここまでは良いのですが、

> あのような書き方をしました

どうしてそれであのような書き方になったのですか?
なんとなくで適当に書いているとしか思えないのですが。
これが一番の問題ですので、上達したいのならば
自分で自分を分析してください。

南瓜

Re:C言語でポーカーを作っているんですが その2

#91

投稿記事 by 南瓜 » 15年前

char *number[13]から13個の数字を宣言して、int n_hand[5]から5個の箱を用意する
number[n_hand]は、5個の箱にランダムで選ばれた13個の数字を入れて出力するために必要な書き方
23456のストレートならn_hand[1]で2が選ばれて、n_hand[2]で3…と続き
number[n_hand[1]],number[n_hand[2]]…number[n_hand[[5]]で23456と出力される
やっぱりストレートを判断するには、n_handが重要になる
しかし、number[n_hand],number[n_hand[i+1]]…number[n_hand[i+4]]だと
Segmentation faultになってしまう

ストレートの判断でn_handは重要ではなく、別の判断基準が必要なのでしょうか?

たいちう

Re:C言語でポーカーを作っているんですが その2

#92

投稿記事 by たいちう » 15年前

for(i = 0; i < 5; i++) {/* 五枚のカードをrandで決定 */ 
    do { /*別のカードを引くまで繰り返す*/
        n_hand= rand() % 13;/*数字を出す*/
        m_hand = rand() % 4;/*マークを出す*/
    } while (card[m_hand][n_hand] == 1);/*card[4][13]と同じなら1,違うなら0*/
    card[m_hand][n_hand] = 1;/*card[4][13]に引いた情報を記憶*/
}


↑の部分をコメントアウトして、その代わりに、
23456のストレートをn_handとm_handにセットしましょう。

これをストレートと判定できますか?

南瓜

Re:C言語でポーカーを作っているんですが その2

#93

投稿記事 by 南瓜 » 15年前

判定できませんでした…
というより、何にでもストレートの判定が(そういう書き方だから当然なのだがorz)
m_handにも23456をセットする理由は、エラーを起こさせないため?

たいちう

Re:C言語でポーカーを作っているんですが その2

#94

投稿記事 by たいちう » 15年前

> 判定できませんでした…
> というより、何にでもストレートの判定が(そういう書き方だから当然なのだがorz)
> m_handにも23456をセットする理由は、エラーを起こさせないため?

違います。m_handにそんな数値をセットしてはいけません。こうしましょうか。
int m_hand[5] = { 0,1,2,3,3 };

m_hand(スート)とn_hand(数)の組み合わせで1枚のカードを表現しているので、
手札を決めるには、m_handにも値をセットしなくてはならないから書いたのであり、
m_handに23456をセットするようにとは書いていません。
m_handの取りうる値の範囲を考えれば当然です。

最終的には、どんな手札でもストレートの判定を正しくできるプログラムですが、
とりあえず23456をストレートと判定できるプログラムを作りましょう、ということ。

南瓜さんは、23456がどうしてストレートだと認識できるのですか?
その手順をできるだけ詳しく日本語で書いてください。
それをC言語に直したら完成です。

南瓜

Re:C言語でポーカーを作っているんですが その2

#95

投稿記事 by 南瓜 » 15年前

1)カードが5枚配られる→2)カードは32564だった→3)数字を確認→4)数字を順に並べ直す
→5)23456になった→6)ストレート

1はすでに出来ている。2,5は便宜的ではあるけどセットしてある。
3,4は書かなくてもいい所? 重要なのはやはり6か?

23457にセットしてもストレートと判定されてしまうので、
書き方云々より考え方が間違ってる?

たいちう

Re:C言語でポーカーを作っているんですが その2

#96

投稿記事 by たいちう » 15年前

> if(n_hand[1] && n_hand[2] && n_hand[3] && n_hand[4] && n_hand[5]) {
> flag_s = 1;
> }

まずい点は2つ。
1つめは、何度も指摘されている配列のindexの有効範囲。

2つめについてですが、このif文の条件を日本語で表してみて下さい。
そもそも何をやっているつもりなのですか?


>→5)23456になった→6)ストレート
...
> 3,4は書かなくてもいい所? 重要なのはやはり6か?

これも何度か書いていますが、どうして23456をストレートと認識できるのですか?
ストレートの定義は?
それをC言語に翻訳できるレベルまで細かく日本語で表すと?

南瓜

Re:C言語でポーカーを作っているんですが その2

#97

投稿記事 by 南瓜 » 15年前

int nは入力した文字の長さstrlen(change)を数値に変換したもの
int indexは変換した数値から1を引いたもので、有効範囲はint nが1~5
の時に0<=index<=4

もしn_hand[1]かつn_hand[2]かつn_hand[3]かつn_hand[4]かつn_hand[5]なら
(もし23456なら)flag_sを1にしろ
(もちろん上記の書き方で23456は判断出来てませんが
number[n_hand]、number[n_hand[i+1]]…の書き方が駄目なら他の書き方が思いつかない…)

ストレートは、値がi,i+1,i+2,i+3,i+4のようになっているから(最初に書いたような)
その方法で判断しようとしてました

5枚のカードの値がマークは関係なしに連続しているなら(23456とか)ストレートと認識できる

1枚目の数字2を記憶する→残りのカードから1枚目の記憶した数字の±1のカードがあるか
探す→1はなかったが3がある→では4があるか探す→4があった→5はあるか探す→5があった
→6があるか探す→6があった→5枚のカードのチェック終わり
→if(ストレートを判断する条件)ならばflag_sを1にしろ→flag_s=1ならprintf(ストレートを表示)

たいちう

Re:C言語でポーカーを作っているんですが その2

#98

投稿記事 by たいちう » 15年前

> (もちろん上記の書き方で23456 は判断出来てませんが
> number[n_hand]、number[n_hand[i+1]]…の書き方が駄目なら他の書き方が思いつかない…)

適当に書いてもうまくいくわけがありません。
「適当」と「試行錯誤」は全く別物ですよ。


> 1枚目の数字2を記憶する→残りのカードから1枚目の記憶した数字の±1のカードがあるか
> 探す→1はなかったが3がある→では4があるか探す→4があった→5はあるか探す→5があった
> →6があるか探す→6があった→5枚のカードのチェック終わり
> →if(ストレートを判断する条件)ならばflag_sを1にしろ→flag_s=1ならprintf(ストレートを表示)

近づいてきました。しかし、今度は欲張りすぎです。
23456がストレートであることが判りさえすればよいので、
次の手順を考えて下さい。

1枚目の数字2を記憶する
→2枚目の数字が(2+1)であるか
→3枚目の数字が(2+2)であるか
→4枚目の数字が(2+3)であるか
→5枚目の数字が(2+4)であるか

ookami

Re:C言語でポーカーを作っているんですが その2

#99

投稿記事 by ookami » 15年前

南瓜さん すみません、51662で回答されていることに気づきませんでした。考え方は合っていますが、「出力結果」を聞いたので、その回答では間違いです。(そういう意味では、前の回答も間違いの部分はあったのですが...)

とはいえ、たいちうさんとのやり取りで、かなり先に進まれているようですので、私とのやり取りはいったん置いておきましょう。

南瓜

Re:C言語でポーカーを作っているんですが その2

#100

投稿記事 by 南瓜 » 15年前

ookamiさん、わかりました

一応、判断する時の形らしきものは出来たのですが
同じ23456でも並びが異なる23456(35462とか)は
ストレートと判断されない凡庸性なしの書き方になってしまいました…

数字の記憶とは、int n = 2;みたいな(数字を宣言する)認識よりも
言葉通りに数字を(新たな変数とかに)記憶させるという認識が正しいのでしょうか?

閉鎖

“C言語何でも質問掲示板” へ戻る