みなくんの日記

やる気が皆無で自由気ままに生きてる人のブログ

プログラムよ、とにかく動け ~4桁のヒット&ブローゲーム「4Numbers」を作ろう~その1

今回の目標

毎回この講座的なアレは目標を最初に書いてからやって行こうと思います。というのも、自分の性格上冗長になりやすい性質があって話が無限に脱線してしまうからです。
あとは最初の所をみてもらえば何をやってるかが理解してもらえるかな、と。

目標

  • 「4Numbers」で実際に行われている処理を明確にして(または処理したいことを盛り込んで)「設計図」の作成
  • [Chapter.1] ランダムで重複のない数字の生成

はじめの一歩-設計図の作成-

まずは今回の処理を大まかに説明できるような設計図を簡単に作成したいと思います。私もこれがないとコードが書けなくなってしまうので、アイデア保管庫的な意味合いも込めてこのセクションを入れています。
今回の設計図はこちら。(汚くてすみません) f:id:minamint:20170618160330p:plain
まずは流れを書き、「どんなことをするのか」を明確に。次に「それを実現するにはどんな処理が必要なのか」を端的に。これさえ見れば、書かずとも少しはイメージが浮かぶのではないでしょうか。
今回のプログラミング講座では、この設計図を基にプログラムを作成していきたいと思います。
なんでわざわざ設計図なんて書いたんだ、とかそういう諸々については「蛇足ですが」に長々と。

Chapter.1 ランダムで重複のない数字の生成をしよう

では早速設計図の1番目に書いてある「重複のないランダム4桁の生成」を行いましょう。実はこれとても簡単で、pythonに準備されている関数を使うだけで簡単に出来ちゃうわけです。
それは、randomモジュールのsampleメソッド。これを用いるだけで簡単に重複のないランダム数字が生成できてしまいます。インタプリタで軽く例題として出力してみると…

>>>import random
>>>test=random.sample(range(10),4)
>>>test
[2,4,9,5] 
>>>#複数回ランダムに数字を生成してみる
...for i in range(5):
...    test=random.sample(range(10),4)
...    test
...
[8,2,5,4]
[6,4,8,9]
[7,4,2,1]
[8,1,7,2]
[1,4,0,8]
>>>exit()

といったように、たった1文(importするので2文ですが)だけ書けばすぐに正解桁は作れてしまうわけです。ではこれを実際にパーツとして組み込んでいきますが、より分かり易くするために、今回はクラスを用いて以下のように書いていこうと思います。

import random

class create_random:
    @staticmethod #インスタンス化を行わずに使用するための処理
    def create_num():
        return random.sample(range(10),4) #0-9のなかで4桁をランダム&重複なしに設定

#---test section---

number=create_random.create_num()
print(number)

#---test end---

実行結果

[6,2,0,8]

test sectionはちゃんと動作してくれるかを確かめているメモ書きみたいなものなので、本作成時には使いません。このコードを動かすと、ランダムな数字が表示され、ちゃんと動作していることが確認できます。
これで正解桁の準備ができましたね!次はユーザの入力処理を行っていきましょう!

まとめ

  • 設計図を書いて大まかな動きを理解した
  • ランダム数字生成はrandom.sample()で簡単に行えた!
    以上、案外あっさり終わってしまって少し困惑したみなくんでした。

蛇足ですが

初めてプログラミングというものに触れ、少しずつ自身でプログラミングを作り始めたとき、私の経験上比較的多くの人が「思いついたままコードを書いている」という感じでした。
例えば、「Push “1” to say “hello"」という文章を表示し、ユーザーに「1」と入力された場合に「Hello!」と返す単純なプログラムを書くとしましょう。
この例題をあなたがお好きな言語でコードを書いて解くとき、どうやって解いているでしょうか。感覚で解きますか?それとも「あれがこうなって…」と脳内で考えながらその場でパパっと書きますか?
今回の例題は動かすことだけを考えた場合実に簡単です。以下にcとpythonでの例題に沿ったコードを乗せてみます。
test.c(c言語)

#include<stdio.h>

int main(void){
    int i;
    printf("Push \"1\" to say \"hello\"\n");
    scanf("%d",&i); //ユーザからのキーボード入力を受け付ける
    if(i==1) //もし1だったら
        printf("hello!\n");

    return 0;
}

test.py(python言語)

print("Push \"1\" to say \"hello\"")
test=input() #ユーザからのキーボード入力を受け付ける
if test=='1': #もし1だったら
    print("hello!")

これで半角数字「1」を入力された場合、仕様通りの動作をするプログラムが完成します。
さて、この例題は簡単だったので、感覚で解くというのは容易だったと思います。python3系使いの方で感覚で解いた方は、恐らく「「Push “1” to say “hello"」という文章を表示("print()"で一発)し、ユーザーに「1」と入力された場合("input()"で一発)に「Hello!」と返す("print()"で一発)」と脳内で考えてコードを書いたことでしょう。 もっと簡単に言えば「喋って入力させて喋ったら終わりでしょ?簡単じゃん」――仰る通りです。
じゃあ、こんな例題はどうでしょうか。「スタックを用いてユーザの入力したデータを保存し、それを最後に結果として出すプログラムを作ってよ」と言われた場合。
最初の例題と同じく動作説明は明確に行われていますが、文章を見ただけでコードが見えるでしょうか。少し難しいのではないかと思います。
つまり脳内だけで処理してしまうと記憶保持や順序がバラバラになってしまうといった事態が発生しかねないので、アウトプットする意味で設計図を書く必要があるわけです。あとは誰かに説明したいとき、手伝ってほしいときに理解してもらえる、というメリットもあります。具体的な処理内容は後から記述する際にまとめていけばいいので、まずは大まかな動作図を示しましょう。「こうしたいんだよ」というイメージが明確でないと、コードは書けません。
ではスタックの例題で設計図を作ってみましょう!
1. スタックを用いて → データ格納(pushメソッド)とデータ取り出し(popメソッド)が必要
2. ユーザの入力した → キーボード入力を受け付けないと
3. データを保存し  → キーボード入力を受け付けて、それからpushさせるのか!
4. 最後に結果で出す → すべて終わったら、全部popすれば良いわけだ

と、全4段階に区切って考えることができます。そして区切った後に「どのような処理をさせると良いのか」を書いています。これを少し書くだけで、どんなコードを書けばいいのか理解しやすいですね。 初心者の方で「この仕様通りの動きにしたいけど、どうやったらいいか分からない」と言いながら仕様文だけ読んでじーっと考えてる人がたまにいます。ぜひ考える前に、大まかな動作が分かる設計図を作ってください。そうすれば、コードは見えずともどういう処理をすればいいのかは分かるはずですから。
上から順番にプログラムを書くのではなく、大まかな形を作りながら書く、といったように。枠を作ってから後で中身を詳しく書いていく、というスタイルにしてみると随分書きやすくなるかと思います。今まで考えたこともなかったと言う人がいたら、是非トライしてみてください!