初心者です。

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

初心者です。

#1

投稿記事 by カート » 6年前

はじめまして、プログラミングを勉強して3か月くらいの初心者です。明解C言語入門編やC言語ポインタ完全制覇を使って今まで独学で勉強してきました。入門編は2回読み終えて実際にプログラミングして問題もほとんど解くこともできました。ポインタ完全制覇を今読んでいます。この本がオススメとネットで見たのですが、言いたいことはわかるのですが、いまいちピンときません。
そして、自分でなにかプログラミングできないかとふと考えてじゃんけんゲームを作ろうと思って考えてみたんですが、プログラミングがあやふやにしか思いつかない自分に失望しました。なんとなくif文や構造体を使うんだろうなあとは思いつくんですが、実際にどうプログラミングしていいか全く思いつきませんでした。入門編の問題はサンプルを見ずにできたのですが、実際は何も自分ではできなくてサンプルコードをみないとできなくなってたみたいです。
これからどうすればいいのでしょうか?もう一度入門編に取り組むべきでしょうか?将来はiphoneアプリやアプリのゲームを作りたいと考えています。オススメの本や自分でプログラミングできるような訓練方法などなんでもいいのでアドバイスお願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#2

投稿記事 by softya(ソフト屋) » 6年前

はじめまして。
そうですね。プログラムは小さな構造が寄り集まって出来ていると考えてみてください。
じゃんけんも小さな構造の寄り集まります。この考え方はより大きなプログラムの時も同様なので、応用が利きます。
さて、まずじゃんけんの小さな構造を作ってみましょう。
グー、チョキ、パーを乱数で表示する。これは作れませんか?

【補足】iPhoneアプリとのことですが、Macが必須だったり、Appleアプリストアに置くのに年間1万円弱の費用がかかったたり学生さんには厳しいと思いますが大丈夫ですか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

カート

Re: 初心者です。

#3

投稿記事 by カート » 6年前

返信ありがとうございます。Macや年会費の件は大丈夫です。
一応自分なりにやってみました。よろしくお願いします。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
int random;
srand((unsigned)time(NULL));


random = rand() % 3 + 1;

printf("グー=%d\n", random);
printf("チョキ=%d\n", random);
printf("パー=%d\n", random);

return (0);
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#4

投稿記事 by softya(ソフト屋) » 6年前

これだと、グー、チョキ、パーのどれかを表示するって事に成っていないですよね。
randomの値でグー、チョキ、パーのいずれかを表示してください。

【実行時の表示例】
CPUの手:グー
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ただの屍のようだ

Re: 初心者です。

#5

投稿記事 by ただの屍のようだ » 6年前

カートさん、自分は人を励ます行為をしませんが、君は実にいい線にいってると断言できます。
さまざまな仕事、芸術に無知な人々はセンスや才能という言葉で彼ら自身の尊厳を保とうとします。
ですが、はっきりいいます。
”センス”があるとすれば、それは自分に才能のかけらもないと気付くことです。
”才能”があるとすれば、それは世間に対し極端に鈍感となり、ひたすら自分を磨き続けることです。

カートさんに足りないのは、スキル(学んだ知識の使い方やそれぞれの特徴)と経験(実際に組んできたプログラムの数)です。
基本的に”お勧めできない”本なのですが、時間かけてゆっくり、確実に身につける覚悟があるのであれば、「プログラミング言語C[第2版]」でしっかりやってください

カート

Re: 初心者です。

#6

投稿記事 by カート » 6年前

このような感じでしょうか。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
int cpu;
srand((unsigned)time(NULL));

cpu = rand() % 3 + 1;

if(cpu == 1)
{
printf("CPUの手:グー\n");
}
if(cpu == 2)
{
printf("CPUの手:チョキ\n");
}
if(cpu == 3)
{
printf("CPUの手:パー\n");
}
return (0);
}

カート

Re: 初心者です。

#7

投稿記事 by カート » 6年前

ただの屍のようださん。じっくりがんばっていきたいのでその本読んでみようかと思います。
アドバイスありがとうございます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#8

投稿記事 by softya(ソフト屋) » 6年前

そうです! それでCPUの手を出すことは出来ました。
さて、じゃあ今度は人間の手をsacnf入力してもらって、同じように
人間の手:チョキ
などと表示する別プログラムを書いてみましょうか。あとで2つを組み合わせます。

それとcodeタグの使い方を説明しておきますね。他の規約も読んでおいてください。
「C言語何でも質問掲示板~規約~」
http://dixq.net/board/board.html#k10

> プログラミング言語C[第2版]

プログラムを組む練習という面では特におすすめできる所は無いんですが、C言語開発者ご本人が書いた本です。
知っていて損はないって本でしょうか。 古本屋で百円で買えたりしますので、安いのを探せば良いと思います。
【補足】 既に古い規格で書かれたものなので、最新の規格の情報には対応していませんとか問題はあります。Amazonレビューも参考に。
「Amazon.co.jp: カスタマーレビュー: プログラミング言語C 第2版 ANSI規格準拠」
http://www.amazon.co.jp/product-reviews ... ewpoints=1
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

カート

Re: 初心者です。

#9

投稿記事 by カート » 6年前

リンクまでありがとうござます。参考にしてみます。
出来ました。こちらであってるでしょうか?

コード:

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

int main(void)
{
    int human;
    
    printf("1…グー 2…チョキ 3…パー");
    scanf("%d", &human);

    if(human == 1)
    {
        puts("人間の手:グー");
    }
    if(human == 2)
    {
        puts("人間の手:チョキ");
    }
    if(human == 3)
    {
        puts("人間の手:パー");
    }
    return (0);
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#10

投稿記事 by softya(ソフト屋) » 6年前

OKですね。これをCPU側と組み合わせてましょう。
とりあえず、勝敗判定は後回しで人間の手を入力してもらって、CPUの手をランダムに決めて人間の手とCPUの手を表示するところまでです。
あと、実は人間の手の入力間違い処理も必要なのですが、それは後回しにします。

【補足】 ここまでの感じからすると、細かい部分は作れるので、全体に手を付けようとすると混乱して細かい部分に分けて考えられないのでは無いかという気がします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

カート

Re: 初心者です。

#11

投稿記事 by カート » 6年前

小さくわけて考えればいいのですね。
出来ました!あってますでしょうか。

コード:

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

int main(void)
{
    int human, cpu;
    
    printf("1…グー 2…チョキ 3…パー");
    scanf("%d", &human);


    if(human == 1)
    {
        puts("人間の手:グー");
    }
    if(human == 2)
    {
        puts("人間の手:チョキ");
    }
    if(human == 3)
    {
        puts("人間の手:パー");
    }
    
    srand((unsigned)time(NULL));

    cpu = rand() % 3 + 1;

    if(cpu == 1)
    {
       printf("CPUの手:グー\n");
    }
    if(cpu == 2)
    {
       printf("CPUの手:チョキ\n");
    }
    if(cpu == 3)
    {
      printf("CPUの手:パー\n");
    }
    
    return (0);
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#12

投稿記事 by softya(ソフト屋) » 6年前

putsとprintfをどちらかに統一しましょうか。
さて、OKですのでこれに勝敗判定を後ろに付け加えます。
ようするに、human とcpu の組み合わせをif文で分けるだけです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

カート

Re: 初心者です。

#13

投稿記事 by カート » 6年前

できました。よろしくお願いします。

コード:

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

int main(void)
{
    int human, cpu;
    
    printf("1…グー 2…チョキ 3…パー");
    scanf("%d", &human);


    if(human == 1)
    {
        puts("人間の手:グー");
    }
    if(human == 2)
    {
        puts("人間の手:チョキ");
    }
    if(human == 3)
    {
        puts("人間の手:パー");
    }
    
    srand((unsigned)time(NULL));

    cpu = rand() % 3 + 1;

    if(cpu == 1)
    {
       puts("CPUの手:グー");
    }
    if(cpu == 2)
    {
       puts("CPUの手:チョキ");
    }
    if(cpu == 3)
    {
       puts("CPUの手:パー");
    }
    
    if(human == 1 && cpu == 2 || human == 2 && cpu == 3 || human == 3 && cpu == 1)
    {
        puts("人間の勝ちです。");
    }
    if(human == 2 && cpu == 1 || human == 3 && cpu == 2 || human == 1 && cpu == 3)
    {
        puts("CPUの勝ちです。");
    }
    else
    {
        puts("あいこです。");
    }

    return (0);
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#14

投稿記事 by softya(ソフト屋) » 6年前

これ、試されましたか? もし試していたらテスト不足です。
人間が勝ちの時がバグがありますね。さて、原因はなんだと思いますか。
推測でも良いので書いてみてください。もし、分かったら直してもらっても良いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

カート

Re: 初心者です。

#15

投稿記事 by カート » 6年前

試行したんですけど、テスト不足だったみたいです。
書き直しました。

コード:

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

int main(void)
{
    int human, cpu;
    
    printf("1…グー 2…チョキ 3…パー");
    scanf("%d", &human);


    if(human == 1)
    {
        puts("人間の手:グー");
    }
    if(human == 2)
    {
        puts("人間の手:チョキ");
    }
    if(human == 3)
    {
        puts("人間の手:パー");
    }
    
    srand((unsigned)time(NULL));

    cpu = rand() % 3 + 1;

    if(cpu == 1)
    {
       puts("CPUの手:グー");
    }
    if(cpu == 2)
    {
       puts("CPUの手:チョキ");
    }
    if(cpu == 3)
    {
       puts("CPUの手:パー");
    }
    
    if(human == 1 && cpu == 2 || human == 2 && cpu == 3 || human == 3 && cpu == 1)
    {
        puts("人間の勝ちです。");
    }
    else if(human == 2 && cpu == 1 || human == 3 && cpu == 2 || human == 1 && cpu == 3)
    {
        puts("CPUの勝ちです。");
    }
    else
    {
        puts("あいこです。");
    }

    return (0);
}

ただの屍のようだ

Re: 初心者です。

#16

投稿記事 by ただの屍のようだ » 6年前

せっかくなので、もう一回コメントします。
人が直感で真っ先に思いつくことはだいたい穴だらけです。
考えることはとても大切です、それこそ思考時間≧操作時間が理想的です。

さて、勝ちの場合の人とCPUの差は-1か2、負けの場合の差は1か-2、引き分けの場合はかならず0です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#17

投稿記事 by softya(ソフト屋) » 6年前

ただの屍のようだ さんが書きました: さて、勝ちの場合の人とCPUの差は-1か2、負けの場合の差は1か-2、引き分けの場合はかならず0です
申し訳ないですが、その判定の方法はテクニカルなので直感的ではないと私は思います。
それに、あえて採用するほどのメリットを感じません。
※ 現代プログラミングにおいて、テクニカルで直感的ではないプログラミングは推奨されておりません。孤高を目指すのでもない限り愚直であることが必要なことも多いのです。[誤字修正]
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#18

投稿記事 by softya(ソフト屋) » 6年前

結構テストって大変ですよね。ゲームとかでバグが出るのは、もっとテストする所が多いからです。
さて、一応動きましたが入力ミスがチェックされていないので機能追加しましょう。
ミスがあったら入力に戻るので、scanfをループにします。
ループの終わりは、scanfの結果を見て1,2,3以外だった時はエラーと表示しましょう。
ヒント:while、if、continueなどを使うのがひとつの方法です。

※ オマケ。余力があったら。
実はscnafで%dで数字以外入力の時はscanfの戻り値が0になるので、それもエラーとして表示して欲しいです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

カート

Re: 初心者です。

#19

投稿記事 by カート » 6年前

オマケについて考えたんですけどわかりませんでした。。。
エラー表示はこのような感じでいいでしょうか?

コード:

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

int main(void)
{
    int human, cpu;
    
    do
    {
       printf("1…グー 2…チョキ 3…パー");
       scanf("%d", &human);

       if(human == 1)
       {
          puts("人間の手:グー");
       }
       else if(human == 2)
       {
          puts("人間の手:チョキ");
       }
       else if(human == 3)
       {
          puts("人間の手:パー");
       }
       else
       {
          puts("エラーです。もう一度やり直してください。");
       }
    } while (human <= 0 || human >= 4);

    srand((unsigned)time(NULL));

    cpu = rand() % 3 + 1;

    if(cpu == 1)
    {
        puts("CPUの手:グー");
    }
    if(cpu == 2)
    {
        puts("CPUの手:チョキ");
    }
    if(cpu == 3)
    {
        puts("CPUの手:パー");
    }
    
    if(human == 1 && cpu == 2 || human == 2 && cpu == 3 || human == 3 && cpu == 1)
    {
        puts("人間の勝ちです。");
    }
    else if(human == 2 && cpu == 1 || human == 3 && cpu == 2 || human == 1 && cpu == 3)
    {
        puts("CPUの勝ちです。");
    }
    else
    {
        puts("あいこです。");
    }
 
    return (0);
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#20

投稿記事 by softya(ソフト屋) » 6年前

なるほど、こうしたんですね。
OKですよ。最初は悩まれてましたが、ちゃんと自力で私のヒントだけで出来たじゃないですか。
こういう風に細かいところか順番にやっていく事が大事ですよ。

で、scanfの戻り値に関してはちょっと高度といいうか、いやらしいのでサンプルを書きます。

コード:

    do
    {
       int count;
       printf("1…グー 2…チョキ 3…パー");
       count = scanf("%d", &human);//取得できた個数
       
       if(count == 0 ) {//0なので数字がなかった。
          char dummy[256];
          puts("エラーです。もう一度やり直してください。");
          scanf("%s", dummy);//数字じゃなかったエラー部分を読み飛ばす。
          continue;//ループの頭に戻る。
       }
       if(human == 1)
       {
          puts("人間の手:グー");
       }
       else if(human == 2)
       {
          puts("人間の手:チョキ");
       }
       else if(human == 3)
       {
          puts("人間の手:パー");
       }
       else
       {
          puts("エラーです。もう一度やり直してください。");
       }
    } while (human <= 0 || human >= 4);
理解できそうでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

カート

Re: 初心者です。

#21

投稿記事 by カート » 6年前

なるほど、そうやるんですね。少し自分にとっては難しいですが、理解できました。
小さなプログラミングでも自力でできたらとても楽しいですね。
プログラミングは小さな構造の集まりだということを意識しながらコツコツ頑張っていきたいです。
ご指導ご鞭撻ありがとうございました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#22

投稿記事 by softya(ソフト屋) » 6年前

このあとは、このじゃんけんを豪華にするとか、あるいは別のゲームに挑戦てみてはどうでしょう。
ちょっと高度になりますが、トランプもありますし、三目並べ、ハイローなど色々簡単なゲームがあります。
また、わからないことが有ったら聞いてください。

※ 解決したら、投稿時に解決チェックを付けて投稿をお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: 初心者です。

#23

投稿記事 by ISLe » 6年前

1,2,3以外なら繰り返すというのは

コード:

    do {
       // (略)
    } while (human < 1 || human > 3);
と書いたほうが良いです。
細かいと言われそうですがとても重要なことです。

こういうのはセンスとしか表現しようがないと思うのですが、先天的なセンスしか認めない方が少なくないようです。

カート

Re: 初心者です。

#24

投稿記事 by カート » 6年前

私にはセンスはないので地道に努力していきたいと思います。
ありがとうございました。

アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 初心者です。

#25

投稿記事 by みけCAT » 6年前

human変数が初期化されていないので、
scanfで数値が読み込めなかった場合におかしなことが起こる可能性が(わずかでも)存在すると思います。

continue;があるので大きな問題はなさそうですね。

また、読み飛ばすところはバッファオーバーランを防ぐため、

コード:

scanf("%*s");
の方がいいのではないでしょうか?

count変数を使わずに直接if(scanf(略)==0)と判定する方がシンプルでいいと、私は思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#26

投稿記事 by softya(ソフト屋) » 6年前

みけCAT さんが書きました:human変数が初期化されていないので、
scanfで数値が読み込めなかった場合におかしなことが起こる可能性が(わずかでも)存在すると思います。

continue;があるので大きな問題はなさそうですね。

また、読み飛ばすところはバッファオーバーランを防ぐため、

コード:

scanf("%*s");
の方がいいのではないでしょうか?

count変数を使わずに直接if(scanf(略)==0)と判定する方がシンプルでいいと、私は思います。
そうですね。
"%*s"の方が良いですね。

count変数は私はどっちでも良いと思います。
※ 私はデバッグしやすさから一旦変数に入れる方が癖です。if(scanf(略)==0)としてしまうとデバッガでscanfの戻り値が見れないってのが理由ですね。
あとは読みやすさとかでしょうか。変数に入れて入れなくでも実行速度は変わりませんので。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ただの屍のようだ

Re: 初心者です。

#27

投稿記事 by ただの屍のようだ » 6年前

自分のときと違ってみなさん穏やかじゃありませんか(驚き)
それはそうと、たいぶ時間がたちましたが、自分が勝ち、負け、引き分けを数値化したのは考え方を教えようしたんです。
(つづき)
勝ち:-1、2 負け:1、-2 引き分け:0
これはどうも値をそろえそうですね。(1と-2の差はちょうどパターン数なので)
そこで 「もしhuman < cpuであれば、human+3」としたらどうなるんです?
勝ち:2 負け:1 引き分け:0となって以下の判別文で書けます。

コード:

	switch(結果の変数){
		case 0 : 引き分け;break;
		case 1 : 負け;break;
		default: 勝ち;break;
	}
これもセンスのうちという人もいるかもしれませんが、ステップを踏まえて考えればだれでもすぐ思いつきます。

アバター
usao
記事: 1573
登録日時: 6年前

Re: 初心者です。

#28

投稿記事 by usao » 6年前

ただの屍のようださんの方法は十分ありだと思いますよ.
(並びをループさせると法則性がある際によくやる感じの方法ですよね)

#私も別の方法を考えましたよ(冗談)
 グー,チョキ,パーをそれぞれ 3次元正規直行系の基底ベクトルで表して
 プレイヤの手とCPUの手の外積で判定したらどうですかね.右ねじか左ねじかで勝敗がわかるという.

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: 初心者です。

#29

投稿記事 by ISLe » 6年前

プログラムを改造してRock-paper-scissors-lizard-Spockを作りましょう、としたとき、ただの屍のようださんの方法だと勝敗判定処理をゼロから作り直す必要がありますよね。
つまり保守性が限りなくゼロだということです。

ifで条件を羅列する方法でも考え方は流用できます。

誰でもすぐ思い付くことを皆がやらないのはどうしてかに思い至らないのは論理的に欠けていると思います。
より多くの他人から共感を得る選択をするのがセンスがある/センスが良いということです。
センスという能力を使って共感を得るわけではありません。

マニアックさを競う場かどうかという点においてセンスのある選択をしてください。

ただの屍のようだ

Re: 初心者です。

#30

投稿記事 by ただの屍のようだ » 6年前

マニアックさを競う場ではないといいつつ、マニアックなゲームを話題に持ち込むことに感心しました!
センスのある選択は”スルー”であるのならば、センスのない自分はあえて”突っ込み”を入れます。

さて、Rock-paper-scissors-lizard-Spockを作るのでしたら、直接じゃんけんゲームクラスを特化して、判定関数をオーバーライドすればいいじゃありませんか?
オブジェクト指向とはそもそもそういう目的で誕生したのだと私は思います。それでもって結果を示すフラグを同じ値にすればじゃんけんクラスの結果表示関数で済みます。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: 初心者です。

#31

投稿記事 by ISLe » 6年前

カートさんの書いたじゃんけんプログラムのソースコードのどこにじゃんけんゲームクラスがあるのでしょうか。

このトピックとまったく関係のないクラスやオブジェクト指向が出てくるのはどういう論理なのでしょう。
もはや欠けているとかいうレベルではない気がしますけど。

YuO
記事: 941
登録日時: 9年前
住所: 東京都世田谷区

Re: 初心者です。

#32

投稿記事 by YuO » 6年前

ISLe さんが書きました:プログラムを改造してRock-paper-scissors-lizard-Spockを作りましょう、としたとき、ただの屍のようださんの方法だと勝敗判定処理をゼロから作り直す必要がありますよね。
つまり保守性が限りなくゼロだということです。
そうですか?
私も通常のじゃんけんであれば,単純に勝敗は手に0/1/2に割り当てて,(Aの手 - Bの手 + 3) % 3で出しますね。
手の数が5個であっても,(Aの手 - Bの手 + 5) % 5で判定できるように割り当てれば,それで条件は一緒です。
順序としては,ゲーム名のlizardとSpockが逆で,Rock, Paper, Scissors, Spock, Lizardの順に0から値をあてれば,1か3ならAの勝ち,2か4ならBの勝ちです。
N個の手があるなら円に内接する正N角形のN個の頂点に手を割り当てて,円周上を時計回りor半時計回りに数えて相手が何個目の手かを調べて,
それで勝敗を決定する形になるのであれば,(Aの手 - Bの手 + N) % Nという一般的な式で勝敗を判定できます。
# 勝敗自体はルールに依存する。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#33

投稿記事 by softya(ソフト屋) » 6年前

YuO さんが書きました:
ISLe さんが書きました:プログラムを改造してRock-paper-scissors-lizard-Spockを作りましょう、としたとき、ただの屍のようださんの方法だと勝敗判定処理をゼロから作り直す必要がありますよね。
つまり保守性が限りなくゼロだということです。
そうですか?
私も通常のじゃんけんであれば,単純に勝敗は手に0/1/2に割り当てて,(Aの手 - Bの手 + 3) % 3で出しますね。
手の数が5個であっても,(Aの手 - Bの手 + 5) % 5で判定できるように割り当てれば,それで条件は一緒です。
順序としては,ゲーム名のlizardとSpockが逆で,Rock, Paper, Scissors, Spock, Lizardの順に0から値をあてれば,1か3ならAの勝ち,2か4ならBの勝ちです。
N個の手があるなら円に内接する正N角形のN個の頂点に手を割り当てて,円周上を時計回りor半時計回りに数えて相手が何個目の手かを調べて,
それで勝敗を決定する形になるのであれば,(Aの手 - Bの手 + N) % Nという一般的な式で勝敗を判定できます。
# 勝敗自体はルールに依存する。
私の個人的な見解ですが、そういう判定方法だと理解しやすい人と混乱する人が出ると思うんですよ。
アセンブラ時代は判定処理の節約のため平気で使って来ましたが現代ではどうなんだろうって思っております。
出来るか出来ないかではなく苦手な人がいるなら避けようってスタンスですね。

まぁ、クラスに話が飛んだのは論理の飛躍なので方向違いだと思いますけど。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: 初心者です。

#34

投稿記事 by ISLe » 6年前

なるほど。
例が悪かったですかね。
ローカルルールの採用など実装に対する応用の幅を考慮したほうが現場では重宝されると考えたのですが。

いちおう断っておくと、実装に対するコードの応用なので、オーバーライドで分けるとかは論点が違います。

結論としては多数決で、処理は特化すべし、ということになりますかね。
わたし個人としては反対を表明しておきます。

pgy(改名)

Re: 初心者です。

#35

投稿記事 by pgy(改名) » 6年前

皆様の議論の中、横から失礼します。

皆様のレベルの高い?回答(自分も初心者なのでわかりませんが)が揃っていますが、少しそれらからは逸れた回答を。


私も今現在そうなのですが、じゃんけんという簡単なルールの遊びをゲームにするときでも、考え方(if文で分けたり)、段階の踏み方、すなわちアルゴリズムは頭だけで考えていると、初心者のうちは頭のなかでスパゲティになってしまいます(比喩表現)。

ですので、まず、紙とシャープペンでも用意して、段階、場合分けを絵にしてみるといいと思います。

形を目で知って、頭にインプットして、参考にして、また新たなプログラムに応用する。
このようなやり方をすれば手が、頭が覚えているので多少忘れにくくなるかと・・・自分は信じています。

回答をくださっている皆様は、このようなこと(実際に書いているとまではいいませんがw)を積み重ねてきているからこそ、頭の中だけで、即座にその仕組みが浮かぶ、反射的にわかるのだと思っております。


長文になりましたが、何が言いたいのかというと、考えを図にして「目で見てみる」といいかもしれません。


*初心者の意見なので、そこまで考える必要はありません。

M.R

Re: 初心者です。

#36

投稿記事 by M.R » 6年前

どういう方法を取るのかなんていうのは個人の自由ですね

ただこれは質問に対する回答ですから
質問者の技量に合わせて回答を選ぶのは当然の事でsoftyaさんの対応は適切だったと思いますね。

質問者は解決していますから問題はないですが、これが未解決だったら
ちょっと質問者さん入って来にくいんじゃないかと思います。

多数決かどうかではなく質問者が理解できたかどうかだと思います。

「Hey,僕はこんな事も分かるんだぜすごいだろう」という事をする場ではないです。

アバター
usao
記事: 1573
登録日時: 6年前

Re: 初心者です。

#37

投稿記事 by usao » 6年前

このスレッドって,まずは簡単なものとしてじゃんけんを題材にやってみようという雰囲気なのだと思うのですが.
(ほぼ初めてのプログラミング,というか)
作るべきものが「じゃんけん」に完全に決まっている中で
全組み合わせをifで羅列するのではない,ほんの少しだけ難解な(決して理解不能なレベルではない)別解を示したにすぎないのに
それに対して問題に特化しすぎてるとか拡張性だとかを持ち出すのはさすがにちと場違いではないかと……

M.R

Re: 初心者です。

#38

投稿記事 by M.R » 6年前

おや、誤解があってはいけないので加えますと
別解を示す事に異論はないです。

今回はsoftyaさんが真摯に対応している中で質問者をいたずらに混乱させただけだと思います。

回答は多種あってどれを参考にするのかは質問者の自由だ
といっても普通は答えてもらったら「ぜんぶやらなきゃいけないのかな?」
となりますよね。

少なくともメインで対応されている方がそういう姿勢の中で横からあーだこーだ入っても質問者は困惑するだけです。
メインでの対応に問題がある場合は別ですが、そうではなかったと思います。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: 初心者です。

#39

投稿記事 by ISLe » 6年前

もうしわけありません。
質問を読み違えてました。
じゃんけんゲームを作ることに特化した力を付けたいという話だったのですね。

プログラミングの応用力を付けたいという話だと思っていました。
将来iPhoneでもっと高度なゲームを作りたいと考えていると思ってアドバイスしてしまいました。

わたしはこの掲示板において一貫した態度をとっていますので、ここで場違いとなればすべてにおいて場違いということになりましょう。
ご意見は参考にさせていただきます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#40

投稿記事 by softya(ソフト屋) » 6年前

私は初心者でも将来的に応用が効き、仕事として使っても相応しい作法前提の話をするべきだと思います。たとえ難しい話を抜いて容易な範囲だとしてもです。
そう意味では、A-Bを使うのは仕事として良くない書き方に分類されると私は思います。それにワナにハマりやすい方法でもあると思います。
知識としては有ったほうが良いに決まっていますが、率先して使うべきではないという別の視点からの知識は必要ではないでしょうか。

[補足] 私が職場で新人がA-Bを使っていたら、止めるために理由を話して理解してもらおうとすると思います。
将来ゲームで8大魔法とかで、銀と水がどちらが強いかで計算式で作られたらバランス調整時にすごく困ると思うからです。
心配しすぎでしょうか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ただの屍のようだ

Re: 初心者です。

#41

投稿記事 by ただの屍のようだ » 6年前

なんだかにぎやかですね。
常に一貫していてコメントの上書きのついでに恥の上塗りもするお方にはこれ以上突っ込みません。

最初に言ったとおり、あくまで考え方を一つ教えることを目的としています。
自分自身も約50%のスキルをプログラミング言語Cから習得したこともあり、その難解さも身をもって味わったつもりです。
そのうえで愚直なままでは、第一章の演習問題すら突破できないと断言します。

昔なら、ハードウェアを新型に変えるだけでシステムの効率は何倍もあがるのでしょう。
これからの時代は(本当に優れた)プログラマが主役です。可能な限り柔らかい言葉で言います。優秀なサラリーマンは優秀な技術者とイコールしないのです。
そして私は今でも思います。どんなプロジェクトも優れた技術者、数人で行ったほうがいろんな意味で効率いいです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#42

投稿記事 by softya(ソフト屋) » 6年前

ただの屍のようだ さんが書きました: 昔なら、ハードウェアを新型に変えるだけでシステムの効率は何倍もあがるのでしょう。
これからの時代は(本当に優れた)プログラマが主役です。可能な限り柔らかい言葉で言います。優秀なサラリーマンは優秀な技術者とイコールしないのです。
そして私は今でも思います。どんなプロジェクトも優れた技術者、数人で行ったほうがいろんな意味で効率いいです。
すいません。
その言葉だけは世に認められる実績や実務での業績の有る人以外は思っていても言わないほうが良いと思います。
理由は考えてみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

non
記事: 1097
登録日時: 9年前

Re: 初心者です。

#43

投稿記事 by non » 6年前

2-6-2の法則ですね。
知らない人のために
http://www.independents.jp/data/column/hint/2-6-2.html
non

アバター
usao
記事: 1573
登録日時: 6年前

Re: 初心者です。

#44

投稿記事 by usao » 6年前

将来高度なものを作るのだとしても,なんで最初の練習的な今回の問題に対して示されただけの方法を
将来にわたって拡張保守して”全く別のソフトを作る”話が前提になっているのかまるで理解できないところです.
この時点から既に考えられるすべてのルールを網羅できる方法(後出しされてくる例が既にじゃんけんの拡張とは程遠いと見える)を考えないとダメなの?
(将来の拡張範囲の想定なしに拡張性の有無だけを言うならifで羅列しとくのが上策ですよね)

方法自体は
・仮にルール拡張するとしてもある(素直なルール拡張の)範囲内で拡張性(一般性,かな?)があること対しては No.32の方が示されている
・引き算.何も難しいことは言っていない.どこに罠があるのか?
・単純に手の種類をそれぞれ異なる数字で表すだけでなく,演算可能だという考え方を示したわけで,悪い例ではないと個人的には思いますけど.
 (→これは「応用力」の範疇ではない,と? うーむ…)

#ある方向で対応しているんだからいたずらに横から口を出すな という理屈はわからないでもないのですが
 それを強要するならルールにでもしてしまうべき.内容が主題から大きくずれているわけでもなく,非難される筋合いはないと思う.
#ほぼ未経験の後輩か何かが自力でこの判定方法を使ってきたら私ならむしろ褒めますけど…


[追記]
>仕事として使っても相応しい作法前提の話をするべきだと思います。
おっと… ひょっとしてこの掲示板ってそういう場所でしたか.
だとしたら私が間違ってますね.(私程度の経験ではうかつに回答できない)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#45

投稿記事 by softya(ソフト屋) » 6年前

冷静にお願いします。ルールで強制する気はありません。
で、確認させてください。
A-Bで勝敗判定する方法は、私の目から見るとテクニカルで共同作業や大きなプログラムでは危険な方法にしか見えないのですがusaoさんは違うということでしょうか?
応用性もさほど無いと思うので、使いたいと言う人がいたらおせっかいですが私は積極的に止めたいのです。
※ 私は、この仕組みを実際にアセンブラ中心で無くなってからソースコードで使ったことないんです。

それと統一ルールは作る気はないですし、その権限はありません。
フォーラムルールに書かれています通り、下記の立場です。
 本サイトの管理は4人体制ですが、Dixq以外の3名にはボランティアで、管理役の一部をお願いしているだけであり、管理人としての中立的な立場ではないことご了承下さい。
※ ちなみに、こういう将来性や拡張性の問題で過去に何度か討論に成っています。Sqliteでセーブデータに保存するのは良いのか悪いのか?等。

ソースコードに提示されている案をそのまま書いてみました。
やはり私には直感的に読めずに少し考えてします。これは可読性が低く感じられるのですが如何でしょうか。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
int main(void)
{
    int human, cpu;
    int hantei;
    
    do
    {
       printf("1…グー 2…チョキ 3…パー");
       scanf("%d", &human);
 
       if(human == 1)
       {
          puts("人間の手:グー");
       }
       else if(human == 2)
       {
          puts("人間の手:チョキ");
       }
       else if(human == 3)
       {
          puts("人間の手:パー");
       }
       else
       {
          puts("エラーです。もう一度やり直してください。");
       }
    } while (human <= 0 || human >= 4);
 
    srand((unsigned)time(NULL));
 
    cpu = rand() % 3 + 1;
 
    if(cpu == 1)
    {
        puts("CPUの手:グー");
    }
    if(cpu == 2)
    {
        puts("CPUの手:チョキ");
    }
    if(cpu == 3)
    {
        puts("CPUの手:パー");
    }
    
    // 提案のコード
    hantei = human - cpu;
    if( human < cpu ) {
        hantei += 3;
    }
    switch( hantei ) {
    case 0:
        puts( "あいこです。" );
        break;
    case 1:
        puts( "CPUの勝ちです。" );
        break;
    default:
        puts( "人間の勝ちです。" );
        break;
    }
    
    // 元の判定
    if(human == 1 && cpu == 2 || human == 2 && cpu == 3 || human == 3 && cpu == 1)
    {
        puts("人間の勝ちです。");
    }
    else if(human == 2 && cpu == 1 || human == 3 && cpu == 2 || human == 1 && cpu == 3)
    {
        puts("CPUの勝ちです。");
    }
    else
    {
        puts("あいこです。");
    }
 
    return (0);
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かずま

Re: 初心者です。

#46

投稿記事 by かずま » 6年前

別解です。可読性はあると思うんですが。

コード:

const char human_win[] = "人間の勝ちです。";
const char cpu_win[]   = "CPUの勝ちです。";
const char even[]      = "あいこです。";

const char *table[3][3] = {  // 勝敗表[人間の手][CPUの手]
 // CPUグー    CPUチョキ  CPUパー
    even,      human_win, cpu_win,    // 人間グー
    cpu_win,   even,      human_win,  // 人間チョキ
    human_win, cpu_win,   even,       // 人間パー
};
 
int main(void)
{
    // 人間の手の入力、CPUの手の計算

    puts(table[human-1][cpu-1]); 
    return (0);
}

アバター
usao
記事: 1573
登録日時: 6年前

Re: 初心者です。

#47

投稿記事 by usao » 6年前

うまく伝わらないですね……(私の文章はいつもですね.ご迷惑をおかけします)
このスレッドでやっていることがそもそも
>共同作業や大きなプログラム
ではないし,それを想定した類のものでもない と私は見ているのですが,違うのでしょうか.

 将来どうするかはともかく,このスレッドの作成目標は「じゃんけん」であって,
 そのコードを流用なり発展させて何か別のXXXを作ろう とかいう話はない.
 だから,じゃんけんの実装方法を話している.
 「その範囲内では」,拡張性も保守性もコードの応用性云々も不要.

と言っているだけなのですが,認識が間違っているでしょうか.
繰り返しになりますが,今回やっているのはプログラム作成の練習用の小さな例題にすぎません.
拡張や保守の話を持ち出すべき場なんですか?


私にはこういう流れにしか見えない↓

(質問)プログラムの作り方みたいなのがよくわかりません
→じゃあ 簡単なものとしてジャンケンを例にとってやってみましょう 問題を小さくわけで少しずつ進めればいいのです
→その方向ですすめる
→じゃんけんの判定方法ならこういう方法もありますよね
→「その方法だと拡張性も保守性もないし問題特化している!使うべきでない勧められない!」  ← えっ!?
→「その方法だと例えばこういうゲームをつくろうとしたら対応できない」 ← え?え?


>可読性が低く感じられる
今回のように 数式で表せる性質のある問題 をその性質を利用して実装した場合,
その実装コードだけを予備知識なしに見た場合には得てして処理の意図がわかりにくいものになる という話はわかります.
だから「コードで採用した考え方や,今回ならばその数式の意味」等を注釈に書く等するんだと思うんですけどね.

M.R

Re: 初心者です。

#48

投稿記事 by M.R » 6年前

単に経験年度数による境界があるだけですね

8bitアセンブラでプログラムしていた時などはテクニカルな技法を追求した時期が
私にも確かにありました。

長い目で見ると「ああこれではダメなんだな」と悟る経験をしているだけです。

別解の紹介をするのは全く問題はないですが、基本的な事を解説している最中に挟み込む事で
理解が円滑に進んだのか、という基準の意見でないと平行線です。
「この別解のどこに問題があるんだ!!」と力説されても
誰も問題だと言ってませんよね。と返すしかない。
言葉は多種多様でも要するに今やる事じゃないと言ってるんです

質問者の問題が解決した後で「こんな方法もあるんですよ」と紹介すれば何も問題はない。


個人的な意見を言うのであればここでの別解の紹介は
プログラムを自分で進めて行く過程で
「あ、こう書けばいいんじゃないか」
と発見して感動する機会を無意味に奪っているにすぎないですね。
趣味でやっているからこそ、そこは楽しみとして置いといてあげたいです。

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: 初心者です。

#49

投稿記事 by h2so5 » 6年前

最近こういうゴタゴタが多いですが、掲示板のシステムの限界もあるかもしれません。

例えばStackoverflow.comでは、回答に関する議論は別枠でコメントとして記述できるので、
回答と議論が混ざって質問者が混乱するようなことがないようになっています。

アバター
usao
記事: 1573
登録日時: 6年前

Re: 初心者です。

#50

投稿記事 by usao » 6年前

こういうのを使うのは違いますかね?
オフトピック
>「この別解のどこに問題があるんだ!!」と力説されても
>誰も問題だと言ってませんよね。と返すしかない。
危険,罠がある,拡張性がどうの と指摘されていますが.
あと,差し挟んだ時期,という点でも一度棄却された後,解決後に話をしているように見えます.(たまたまかもしれませんが)
素直な実装方法が否定されたままでは誤解を招くログになりそうかな?とか思うのですが,とりあえずやめます.

[やめますとか言っといて最後に追記]
じゃんけんのルールを説明するときに,{グー,チョキ,パー}で三角形を描いて,隣接間の勝敗関係を矢印とかで描きません?
相手の手が自分の手から見て右側か左側かで勝ち負けがわかるような.
その概念をそのまま素直にコード化しただけの形で,テクニカルなことを追い求めているかのように受け取られているのが不思議です.
(勝敗表みたいな図を考えれば素直な表現は2次元配列とかになるでしょうけど.)
最後に編集したユーザー usao on 2013年7月09日(火) 14:47 [ 編集 2 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 初心者です。

#51

投稿記事 by softya(ソフト屋) » 6年前

>繰り返しになりますが,今回やっているのはプログラム作成の練習用の小さな例題にすぎません.
>拡張や保守の話を持ち出すべき場なんですか?

私は初心者でも可読性の低いものを当たり前として受け入れてほしくないのです。これは私のスタンスです。
かずまさんの別解のほうが可読性が高く、応用範囲も広いと感じます。

hantei = human - cpu;に関して言えば、私は悪い例として書きたいぐらい良くない例に見えています。
これは私の意見ですし、一般論とはズレているかもしれません。

【補足】
そう見えない人がたくさんいると言う事実は良い勉強になりました。

【追記】
ここを読んだ人のために。
私がA-Bが良くないと思う理由は、数値がじゃんけんの状態を表すと同時に差分値自体が意味を持ってしまうことです。
そのために数値の意味合いが2面性を持つことになります。
応用が効かないと言うのは、要素が5、10と増えていくに従い複雑性を増してメンテナンス性を下げていくからです。
実際、こういうコードを書く機会は皆無と言って良いでしょう。

あとカーニハンが出ていたので引き合いに出しますが「プログラミング作法」にも書かれている事ですが、
コードよりコメントが長くなるようなら、それは良くないコードであると私も思います。
これに分かりやすくコメント書くと確実に長いコメントになると思っています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ただの屍のようだ

Re: 初心者です。

#52

投稿記事 by ただの屍のようだ » 6年前

めんどくさい論争をいつまでも続けるってことはおそらくみなさん、さぞ暇があるのでしょう。
このコメントで終止符打ちたいと思います。

さて、みなさんは大規模なコードの各部品の細かい実装まで見ますか?
私の答えはこうです。”気になれば見ます”。意味わかりますね?
結果判定が長い比較条件式ではなく0,1,2であることのメリット。
(もし、熟練の皆さんが経験を重ね、たどり着いたのが全部mainに詰め込め!というのであれば私のスタンスが崩壊的だと思ってくれればいいです)

M.R

Re: 初心者です。

#53

投稿記事 by M.R » 6年前

>>誰も問題だと言ってませんよね。と返すしかない。
>危険,罠がある,拡張性がどうの と指摘されていますが.
問題というのが「バグがある」「~年後に使えなくなる」という意味でないように言葉尻です
可読性という言葉を使ったから
「じゃ可読性がある事を証明すればいいのね」
となると平行線です。

それらは質問者に確認してほしいですね。
 このコードに危険がない事が分かりましたか?
 罠がない事が分かりましたか?
 拡張性はありますよね?
質問者がyesと言うなら私に言う事はありません。
私の考え方は古いんだなと引っ込むだけです。

質問者が自分で考えて使っている分にはsoftyaさんだって口出ししませんよ
(アドバイスはするでしょうが本人が使いたいと言う分には強要する事はできません)
あえて他人が推す事ではないという事です。

>あと,差し挟んだ時期,という点でも一度棄却された後,解決後に話をしているように見えます.(たまたまかもしれませんが)
もう見え方の問題ですね。
解決前の棄却を否定していますから、改めて別解を紹介しているようには私には見えないです。

閉鎖

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