『10才からはじめるプログラミング図鑑』のコード

[『10才からはじめるプログラミング図鑑』](http://amzn.to/2wvr9Rf) という本がとても良い本だったので，
この本で学ぶ子供，親向けに，Python と JavaScript のコードを写経する．
詰んだ時などに参考にしてもらえたら嬉しい．

ちなみに，表紙の見た目からは，スクラッチとPythonの入門書に見えるが，
それ以外にも，

* 論理ゲート (pp.186-187)
* プロセッサとメモリ (pp.188-189)
* コンパイラとインタプリタ (p.191)
* インターネットのポート (p.195)
* スマートフォンのアプリの説明 (pp.206-207)
* JavaScript (pp.208-211)
* Raspberry Pi, Arduino (p.214) 

等についてもわかりやすく書かれていて驚いた．10才のころに読みたかったし，この本から学ぶことができる子供達がとても羨ましい．もちろん，ステマではない．

では早速，写経する．

# 3 パイソンで遊ぼう
## プロジェクト4 : ゆうれいゲーム

```python:ゆうれいゲーム.py
# p.96 ゆうれいゲーム
# Ghost Game

from random import randint
print('ゆうれいゲーム')
feeling_brave = True
score = 0
while feeling_brave:
    ghost_door = randint(1, 3)
    print('ドアが3つある。')
    print('そのうち1つのドアの向こうにゆうれいがいる。')
    print('さあ、何番のドアを開ける?')
    door = input('1、2、それとも3?')
    door_num = int(door)
    if door_num == ghost_door:
        print('ゆうれいだ!')
        feeling_brave = False
    else:
        print('ゆうれいはいなかった!')
        print('となりの部屋に入れたよ。')
        score = score + 1
print('逃げろ!')
print('ゲームオーバー! スコアは', score, 'です。')
```
## 分岐

```python:
# p.121 いくつかの処理のうち1つを選ぶ

a = int(input('a = '))
b = int(input('b = '))
op = input('たす/ひく/かける/わる:')
if op == 'たす':
    c = a + b
elif op == 'ひく':
    c = a - b
elif op == 'かける':
    c = a * b
elif op == 'わる':
    c = a / b
else:
    c = 'エラー'
print('答え = ',c)
```
## パイソンでのくり返し
```python:
# p.122 パイソンでのくり返し

from turtle import *
forward(100)
right(120)
forward(100)
right(120)
forward(100)
right(120)
```

```python:
for i in range(3):
    forward(100)
    right(120)
```
```python:
# p.123 入れ子構造 (ネスティング)のループ

n = 3
for a in range(1, n + 1):
    for b in range(1, n + 1):
        print(b, 'x', a, '=', b * a)
```
## 関数
```python:
# p.130 関数の作り方とよび出し方

def greeting():
    print('こんにちは!')

greeting()
```

```python:
# p.131 関数にデータをわたす

def height(m, cm):
    total = (100 * m) + cm
    print(total, 'センチの高さだね')

height(1,45)
```

```python:
# p.131 関数からデータを返す

def num_input(prompt):
    typed = input(prompt)
    num = int(typed)
    return num

a = num_input('a を入力して下さい')
b = num_input('b を入力して下さい')
print('a + b =', a + b)
```

## プロジェクト5 : 自動作文マシン
```python:
# pp.132-133 自動作文マシン

# 文章を自動的に作る
name = ['タカシが', 'ニュートンが', 'パスカルが']
noun = ['ライオンを', '自転車を', '飛行機を']
verb = ['買う', '乗り回す', 'たたく']

from random import randint
def pick(words):
    num_words = len(words)
    num_picked = randint(0, num_words - 1)
    word_picked = words[num_picked]
    return word_picked

print(pick(name), pick(noun), pick(verb), end='。\n')
```
```python:
#  文章を作り続ける
while True:
    print(pick(name), pick(noun), pick(verb), end='。\n')
    input()
```

## プロジェクト6 : 作図マシン
```python:
# p.140

from turtle import *
reset()
left(90)
forward(100)
right(45)
forward(70)
right(90)
forward(70)
right(45)
forward(100)
right(90)
forward(100)
```
## 関数「turtle_controller」

```python:
# p.142
from turtle import *

def turtle_controller(do, val):
    do = do.upper()
    if do == 'F':
        forward(val)
    elif do == 'B':
        backward(val)
    elif do == 'R':
        right(val)
    elif do == 'L':
        left(val)
    elif do == 'U':
        penup()
    elif do == 'D':
        pendown()
    elif do == 'N':
        reset()
    else:
        print('不明な命令がありました')
```
```python:
turtle_controller('F' , 100)
turtle_controller('R' , 90)
turtle_controller('F' , 50)
```
## 関数「string_artist」を作る
```python:
# p.144 
program = 'N-L90-F100-R45-F70-R90-F70-R45-F100-R90-F100'
cmd_list = program.split('-')
cmd_list
```
次のソースコードを142ページのソースコードの下に続けて書こう．

```python:
def string_artist(program):
    cmd_list = program.split('-')
    for command in cmd_list:
        cmd_len = len(command)
        if cmd_len == 0:
            continue
        cmd_type = command[0]
        num = 0
        if cmd_len > 1:
            num_string = command[1:]
            num = int(num_string)
        print(command, ':', cmd_type, num)
        turtle_controller(cmd_type, num)
```

```python:
# p.145
string_artist('N-L90-F100-R45-F70-R90-F70-R45-F100-R90-F100')
```
## ユーザー用の入力画面を作る
142ページと144ページのソースコードに続けて入力してね．

```python:
# p.146
instructions = '''タートルへの指示を入力して下さい:
例　F100-R45-U-F100-L45-D-F100-R90-B50
N = 新しくかき始める
U/D = ペンを下げる / 上げる
F100 = 前方へ100歩進む
B50 = 後方へ50歩進む
R90 = 右へ90度回転する
L45 = 左へ45度回転する'''
screen = getscreen()
while True:
    t_program = screen.textinput('作図マシン', instructions)
    print(t_program)
    if t_program == None or t_program.upper() == 'END':
        break
    string_artist(t_program)
```

```python:
# p.147
N-L90-F100-R45-F70-R90-F70-R45-F100-R90-F100-
B10-U-R90-F10-D-F30-R90-F30-R90-F30-R90-F3
```

ちなみに，プロジェクト6 : 作図マシン のコードを続けて書くと

```python:
# p.142 関数「turtle_controller」
from turtle import *
def turtle_controller(do, val):
    do = do.upper()
    if do == 'F':
        forward(val)
    elif do == 'B':
        backward(val)
    elif do == 'R':
        right(val)
    elif do == 'L':
        left(val)
    elif do == 'U':
        penup()
    elif do == 'D':
        pendown()
    elif do == 'N':
        reset()
    else:
        print('不明な命令がありました')

# p.144 関数「string_artist」を作る
def string_artist(program):
    cmd_list = program.split('-')
    for command in cmd_list:
        cmd_len = len(command)
        if cmd_len == 0:
            continue
        cmd_type = command[0]
        num = 0
        if cmd_len > 1:
            num_string = command[1:]
            num = int(num_string)
        print(command, ':', cmd_type, num)
        turtle_controller(cmd_type, num)

# p.146 ユーザー用の入力画面を作る
instructions = '''タートルへの指示を入力して下さい:
例　F100-R45-U-F100-L45-D-F100-R90-B50
N = 新しくかき始める
U/D = ペンを下げる / 上げる
F100 = 前方へ100歩進む
B50 = 後方へ50歩進む
R90 = 右へ90度回転する
L45 = 左へ45度回転する'''
screen = getscreen()
while True:
    t_program = screen.textinput('作図マシン', instructions)
    print(t_program)
    if t_program == None or t_program.upper() == 'END':
        break
    string_artist(t_program)
```
## バグとデバッグ

```python:
# p.148

top_num = 5
total = 0
for n in range(top_num):
    total = total + n
print('1から', top_num, 'までの合計は', total)
```

```python:
# p.149

top_num = 5
total = 0
for n in range(top_num):
    total = total + n
    print('デバッグ: n=', n, 'total=', total)
    input()
print('1から', top_num, 'までの合計は', total)
```

```python:
# p.149

top_num = 5
total = 0
for n in range(1, top_num + 1):
    total = total + n
    print('デバッグ: n=', n, 'total=', total)
    input()
print('1から', top_num, 'までの合計は', total)
```

## ウィンドウを作る

```python:
# p.154　かんたんなウィンドウ
from tkinter import *
window = Tk()
```

```python:
# p.154　ウィンドウにボタンを足す

from tkinter import *
def bAaction():
    print('ありがとう!')
def bBaction():
    print('いたい!ひどいじゃないか!')
window = Tk()
buttonA = Button(window, text='押して!', command=bAaction)
buttonB = Button(window, text='押さないでよ!', command=bBaction)
buttonA.pack()
buttonB.pack()
```

```python:
# p.155　サイコロをふる

from tkinter import *
from random import randint
def roll():
    text.delete(0.0, END)
    text.insert(END, str(randint(1, 6)))
window = Tk()
text = Text(window, width=1, height=1)
buttonA = Button(window, text='ここを押してサイコロをふろう', command=roll)
text.pack()
buttonA.pack()
```

## 色と座標

```python:
# p.157
from random import *
from tkinter import *
size = 500
window = Tk()
canvas = Canvas(window, width=size, height=size)
canvas.pack()
while True:
    col = choice(['pink', 'orange', 'purple', 'yellow'])
    x0 = randint(0, size)
    y0 = randint(0, size)
    d = randint(0, size/5)
    canvas.create_oval(x0, y0, x0 + d, y0 + d,  fill=col)
    window.update()
```

## 図形をかく

```python:
# p.158 基本的な図形をかく
>>> from tkinter import *
>>> window = Tk()
>>> drawing = Canvas(window, height=500, width=500)
>>> drawing.pack()
>>> rect1 = drawing.create_rectangle(100, 100, 300, 200)
>>> square1 = drawing.create_rectangle(30, 30, 80, 80)
>>> oval1 = drawing.create_oval(100, 100, 300, 200)
>>> circle1 = drawing.create_oval(30, 30, 80, 80)
```

```python:
# p.158 座標を使ってかく
>>> drawing.create_rectangle(50, 50, 250, 350)
```

```python:
# p.159 図形に色をつける
>>> drawing.create_oval(30, 30, 80, 80, outline='red', fill='blue')
```

```python:
# p.159 エイリアンをかこう

from tkinter import *
window = Tk()
window.title('エイリアン')
c = Canvas(window, height=300, width=400)
c.pack()
body = c.create_oval(100, 150, 300, 250, fill='green')
eye = c.create_oval(170, 70, 230, 130, fill='white')
eyeball = c.create_oval(190, 90, 210, 110, fill='black')
mouth = c.create_oval(150, 220, 250, 240, fill='red')
neck = c.create_oval(200, 150, 200, 130)
hat = c.create_polygon(180, 75, 220, 75, 200, 20, fill='blue')
```

## グラフィックスを変化させる

```python:
# p.160 図形を動かす
>>> c.move(eyeball, -10,0)
>>> c.move(eyeball, 10,0)
```
p.159 のソースコードに続けて入力してね．

```python:
# 色を変えてみる
def mouth_open():
    c.itemconfig(mouth, fill='black')
def mouth_close():
    c.itemconfig(mouth, fill='red')
```

```python:
>>> mouth_open()
>>> mouth_close()
```
p.160 のソースコードに続けて入力してね．

```python:
# p.161 図形をかくす
def blink():
    c.itemconfig(eye, fill='green')
    c.itemconfig(eyeball, state=HIDDEN)
def unblink():
    c.itemconfig(eye, fill='white')
    c.itemconfig(eyeball, state=NORMAL)
```

```python:
>>> blink()
>>> unblink()
```

```python:
# p.161 しゃべらせる
words = c.create_text(200, 280, text='私はエイリアンだ!')
def steal_hat():
    c.itemconfig(hat, state=HIDDEN)
    c.itemconfig(words, text='ぼうしをかえしてよ!')
```


```python:
>>> steal_hat()
```

## イベントに反応する

```python:
# p.162 マウスのイベント

window.attributes('-topmost', 1)
def burp(event):
    mouth_open()
    c.itemconfig(words, text='げっぷ!')
c.bind_all('<Button-1>', burp)
```

```python:
# p.163 キーボードのイベント

def blink2(event):
    c.itemconfig(eye, fill='green')
    c.itemconfig(eyeball, state=HIDDEN)
def unblink2(event):
    c.itemconfig(eye, fill='white')
    c.itemconfig(eyeball, state=NORMAL)
c.bind_all('<KeyPress-a>', blink2)
c.bind_all('<KeyPress-z>', unblink2)
```


```python:
# p.163 キーの操作で動かす

def eye_control(event):
    key = event.keysym
    if key == "Up":
        c.move(eyeball, 0, -1)
    elif key == "Down":
        c.move(eyeball, 0, 1)
    elif key == "Left":
        c.move(eyeball, -1, 0)
    elif key == "Right":
        c.move(eyeball, 1, 0)
c.bind_all('<Key>', eye_control)
```
## プロジェクト6 : せん水かんゲーム

```python:
# p.165 ウィンドウとせん水かんを作る

from tkinter import *
HEIGHT = 500
WIDTH = 800
window = Tk()
window.title('せん水かんゲーム')
c = Canvas(window, width=WIDTH, height=HEIGHT, bg='darkblue')
c.pack()
```

```python:
ship_id = c.create_polygon(5, 5, 5, 25, 30, 15, fill='red')
ship_id2 = c.create_oval(0, 0, 30, 30, outline='red')
SHIP_R = 15
MID_X = WIDTH / 2
MID_Y = HEIGHT / 2
c.move(ship_id, MID_X, MID_Y)
c.move(ship_id2, MID_X, MID_Y)
```

```python:
# p.166 せん水かんを動かす

SHIP_SPD = 10
def move_ship(event):
    if event.keysym == 'Up':
        c.move(ship_id, 0, -SHIP_SPD)
        c.move(ship_id2, 0, -SHIP_SPD)
    elif event.keysym == 'Down':
        c.move(ship_id, 0, SHIP_SPD)
        c.move(ship_id2, 0, SHIP_SPD)
    elif event.keysym == 'Left':
        c.move(ship_id, -SHIP_SPD, 0)
        c.move(ship_id2, -SHIP_SPD, 0)
    elif event.keysym == 'Right':
        c.move(ship_id, SHIP_SPD, 0)
        c.move(ship_id2, SHIP_SPD, 0)
c.bind_all('<Key>', move_ship)
```

```python:
# p.167 「あわ」を用意する

from random import randint
bub_id = list()
bub_r = list()
bub_speed = list()
MIN_BUB_R = 10
MAX_BUB_R = 30
MAX_BUB_SPD = 10
GAP = 100
def create_bubble():
    x = WIDTH + GAP
    y = randint(0, HEIGHT)
    r = randint(MIN_BUB_R, MAX_BUB_R)
    id1 = c.create_oval(x - r, y - r, x + r, y + r, outline='white')
    bub_id.append(id1)
    bub_r.append(r)
    bub_speed.append(randint(1, MAX_BUB_SPD))
```

```python:
# p.168 あわを動かす

def move_bubbles():
    for i in range(len(bub_id)):
        c.move(bub_id[i], -bub_speed[i], 0)
```

```python:
from time import sleep, time
BUB_CHANCE = 10
# メインのループ
while True:
    if randint(1, BUB_CHANCE) == 1:
        create_bubble()
    move_bubbles()
    window.update()
    sleep(0.01)
```


```python:
def get_coords(id_num):
    pos = c.coords(id_num)
    x = (pos[0] + pos[2])/2
    y = (pos[1] + pos[3])/2
    return x, y
```

```python:
# p.169 あわをわる方法

def del_bubble(i):
    del bub_r[i]
    del bub_speed[i]
    c.delete(bub_id[i])
    del bub_id[i]
```

```python:
def clean_up_bubs():
    for i in range(len(bub_id) -1, -1, -1):
        x, y = get_coords(bub_id[i])
        if x < -GAP:
            del_bubble(i)
```
* 10 のコードは省略しました．


```python:
# p.170 2つの点の間の距離をはかる

from math import sqrt
def distance(id1, id2):
    x1, y1 = get_coords(id1)
    x2, y2 = get_coords(id2)
    return sqrt((x2 - x1)**2 + (y2 - y1)**2)
```


```python:
# あわをわる

def collision():
    points = 0
    for bub in range(len(bub_id)-1, -1, -1):
        if distance(ship_id2, bub_id[bub]) < (SHIP_R + bub_r[bub]):
            points += (bub_r[bub] + bub_speed[bub])
            del_bubble(bub)
    return points
```

* 13 のコードは省略しました．

```python:
# p.172 ゲームを完成させる

c.create_text(50, 30, text='タイム', fill='white' )
c.create_text(150, 30, text='スコア', fill='white' )
time_text = c.create_text(50, 50, fill= 'white' )
score_text = c.create_text(150, 50, fill='white')
def show_score(score):
    c.itemconfig(score_text, text=str(score))
def show_time(time_left):
    c.itemconfig(time_text, text=str(time_left))
```

```python:
from time import sleep, time
BUB_CHANCE = 10
TIME_LIMIT = 30 # P.172
BONUS_SCORE = 1000 # P.172
score = 0 # p.171
bonus = 0 # P.172
end = time() + TIME_LIMIT  # P.172
```

```python:
# p.173

# メインのループ
while time() < end: # P.173
    if randint(1, BUB_CHANCE) == 1:
        create_bubble()
    move_bubbles()
    clean_up_bubs()  # p.169
    score += collision()  # p.171
    if (int(score / BONUS_SCORE)) > bonus:  # p.173
        bonus += 1  # p.173
        end += TIME_LIMIT  # p.173
    show_score(score)  # p.173
    show_time(int(end - time()))  # p.173
    window.update()
    sleep(0.01)
```

```python:
# p.173
c.create_text(MID_X, MID_Y, \
    text='ゲームオーバー', fill='white', font=('Helvetica', 30))
c.create_text(MID_X, MID_Y + 30, \
              text='スコア'+ str(score),  fill='white')
c.create_text(MID_X, MID_Y + 45,
              text='ボーナスタイム' + str(bonus*TIME_LIMIT),  fill='white')

```
これで完成です．
下記は完成したプログラムです．


```python:
# p.165 ウィンドウとせん水かんを作る

from tkinter import *
HEIGHT = 500
WIDTH = 800
window = Tk()
window.title('せん水かんゲーム')
c = Canvas(window, width=WIDTH, height=HEIGHT, bg='darkblue')
c.pack()

ship_id = c.create_polygon(5, 5, 5, 25, 30, 15, fill='red')
ship_id2 = c.create_oval(0, 0, 30, 30, outline='red')
SHIP_R = 15
MID_X = WIDTH / 2
MID_Y = HEIGHT / 2
c.move(ship_id, MID_X, MID_Y)
c.move(ship_id2, MID_X, MID_Y)

# p.166 せん水かんを動かす

SHIP_SPD = 10
def move_ship(event):
    if event.keysym == 'Up':
        c.move(ship_id, 0, -SHIP_SPD)
        c.move(ship_id2, 0, -SHIP_SPD)
    elif event.keysym == 'Down':
        c.move(ship_id, 0, SHIP_SPD)
        c.move(ship_id2, 0, SHIP_SPD)
    elif event.keysym == 'Left':
        c.move(ship_id, -SHIP_SPD, 0)
        c.move(ship_id2, -SHIP_SPD, 0)
    elif event.keysym == 'Right':
        c.move(ship_id, SHIP_SPD, 0)
        c.move(ship_id2, SHIP_SPD, 0)
c.bind_all('<Key>', move_ship)

# p.167 「あわ」を用意する

from random import randint
bub_id = list()
bub_r = list()
bub_speed = list()
MIN_BUB_R = 10
MAX_BUB_R = 30
MAX_BUB_SPD = 10
GAP = 100
def create_bubble():
    x = WIDTH + GAP
    y = randint(0, HEIGHT)
    r = randint(MIN_BUB_R, MAX_BUB_R)
    id1 = c.create_oval(x - r, y - r, x + r, y + r, outline='white')
    bub_id.append(id1)
    bub_r.append(r)
    bub_speed.append(randint(1, MAX_BUB_SPD))

def get_coords(id_num):
    pos = c.coords(id_num)
    x = (pos[0] + pos[2])/2
    y = (pos[1] + pos[3])/2
    return x, y

# あわを動かす
def move_bubbles():
    for i in range(len(bub_id)):
        c.move(bub_id[i], -bub_speed[i], 0)

# p.169 あわをわる方法

def del_bubble(i):
    del bub_r[i]
    del bub_speed[i]
    c.delete(bub_id[i])
    del bub_id[i]

def clean_up_bubs():
    for i in range(len(bub_id) -1, -1, -1):
        x, y = get_coords(bub_id[i])
        if x < -GAP:
            del_bubble(i)

# p.170 2つの点の間の距離をはかる

from math import sqrt
def distance(id1, id2):
    x1, y1 = get_coords(id1)
    x2, y2 = get_coords(id2)
    return sqrt((x2 - x1)**2 + (y2 - y1)**2)

# あわをわる

def collision():
    points = 0
    for bub in range(len(bub_id)-1, -1, -1):
        if distance(ship_id2, bub_id[bub]) < (SHIP_R + bub_r[bub]):
            points += (bub_r[bub] + bub_speed[bub])
            del_bubble(bub)
    return points

# p.172 ゲームを完成させる

c.create_text(50, 30, text='タイム', fill='white' )
c.create_text(150, 30, text='スコア', fill='white' )
time_text = c.create_text(50, 50, fill= 'white' )
score_text = c.create_text(150, 50, fill='white')
def show_score(score):
    c.itemconfig(score_text, text=str(score))
def show_time(time_left):
    c.itemconfig(time_text, text=str(time_left))

from time import sleep, time
BUB_CHANCE = 10
TIME_LIMIT = 30 # P.172
BONUS_SCORE = 1000 # P.172
score = 0 # p.171
bonus = 0 # P.172
end = time() + TIME_LIMIT  # P.172
# メインのループ
while time() < end: # P.173
    if randint(1, BUB_CHANCE) == 1:
        create_bubble()
    move_bubbles()
    clean_up_bubs()  # p.169
    score += collision()  # p.171
    if (int(score / BONUS_SCORE)) > bonus:  # p.173
        bonus += 1  # p.173
        end += TIME_LIMIT  # p.173
    show_score(score)  # p.173
    show_time(int(end - time()))  # p.173
    window.update()
    sleep(0.01)

# p.173
c.create_text(MID_X, MID_Y, \
    text='ゲームオーバー', fill='white', font=('Helvetica', 30))
c.create_text(MID_X, MID_Y + 30, \
              text='スコア'+ str(score),  fill='white')
c.create_text(MID_X, MID_Y + 45,
              text='ボーナスタイム' + str(bonus*TIME_LIMIT),  fill='white')
```

# 5 現実の世界でのプログラミング
## JavaScriptを使う

```javascript:
// p.210 ユーザーに入力してもらう

<script>
var name = prompt("名前を入れてね ");
var greeting = "こんにちは" + name + "!";
document.write(greeting);
alert("Hello World!");
</script>
```

```javascript:
// p.211 イベント

<button onclick="tonguetwist()">さあ言ってみよう!</button>
<script>
 function tonguetwist()
 {
  document.write("なまむぎなまごめなまたまご");  
 }
</script>
```

```javascript:
// p.211 JavaScript でのループ

<script>
for  (var x=0; x<6; x++)
{
 document.write("ループ回数: "+x+"<br>");
}
</script>
```

# おつかれさまでした．これからもプログラミングを楽しみましょう :thumbsup: