第0回講義: Scratch
ようこそ!
このクラスは、単なるコンピュータプログラミング以上のものです。このクラスで学ぶ実用的なスキルは、コンピュータサイエンスをはるかに超えて、あなたの人生や学びに影響を与えるかもしれません。
実際、このクラスは非常に力強い方法での問題解決について学ぶものです。ここで学ぶ問題解決の手法は、このコースを超えた仕事や、あなたのキャリア全体において、即座に応用できる可能性が高いでしょう。
しかし、それは簡単なことではありません。このコースの間、あなたは知識の「消火用ホース(firehose)から水を飲む」ような体験をすることになるでしょう。今後数週間で、自分が何を成し遂げられるようになるかに驚くはずです。
このコースは、想像上の標準に到達することよりも、「今日のあなた」から「あなた自身」を前進させることに重点を置いています。
これが初めてのコンピュータサイエンスのクラスであっても、怖がらないでください。あなたの仲間のほとんどにとっても、これが初めてのコンピュータサイエンスのクラスです。さらに、ティーチング・フェロー、コース・アシスタント、そして仲間のコミュニティがあなたを助けるためにここにいます!
コミュニティ!
あなたは、ハーバード大学、ハーバード・エクステンション・スクール、そしてedX.orgを通じてこのコースを受講している人々のコミュニティの一員です。
直接であれバーチャルであれ、CS50 Puzzle DayやCS50 Fairにぜひ参加してください。
ハーバードのキャンパスにいる学生であれば、CS50 LunchesやCS50 Hackathonに参加することもできます。
コンピュータサイエンスと問題解決
本質的に、コンピュータプログラミングとは、ある入力を受け取り、ある出力を生成すること、つまり問題を解決することです。入力と出力の間で何が起こるか、いわゆる「ブラックボックス」がこのコースの焦点です。
例えば、クラスの出席を取る必要があるとします。1進法(unary または base-1 とも呼ばれます)というシステムを使って、指を1本ずつ数えることができます。
今日のコンピュータは、2進法(binary)と呼ばれるシステムを使って数えます。「2進数字(binary digit)」という言葉から、私たちがよく知っている「ビット(bit)」という用語が生まれました。ビットは0か1、つまりオフかオンの状態を指します。
コンピュータは0と1という言葉しか話せません。0は「オフ」、1は「オン」を表します。コンピュータは、オンとオフを切り替える何百万、おそらく何十億ものトランジスタでできています。
電球を想像してみてください。1つの電球では、0から1までしか数えることができません。
しかし、3つの電球があれば、より多くの選択肢が開かれます。
iPhoneの中には、「トランジスタ」と呼ばれる何百万もの電球のようなものがあり、私たちが毎日当たり前のように使っている活動を可能にしています。
ヒューリスティックとして、2進数字(binary digit)の各桁が以下の値を表すと想像してみましょう。
4 2 1
3つの電球を使うと、以下のように0を表すことができます。
4 2 1
0 0 0
同様に、以下は1を表します。
4 2 1
0 0 1
この論理によれば、以下は2に等しいと言えます。
4 2 1
0 1 0
さらにこの論理を拡張すると、以下は3を表します。
4 2 1
0 1 1
4は以下のようになります。
4 2 1
1 0 0
実際、3つの電球だけで7まで数えることができます!
4 2 1
1 1 1
コンピュータは数えるのに2進法(base-2)を使用します。これは以下のように描くことができます。
2^2 2^1 2^0
4 2 1
- したがって、7までの数字を表すには3ビット(4の位、2の位、1の位)が必要であると言えます。
同様に、8までの数字を数える場合、値は次のように表されます。
8 4 2 1
1 0 0 0
コンピュータは通常、数字を表すのに8ビット(「バイト」としても知られています)を使用します。例えば、00000101は2進法の5です。11111111は255を表します。0は以下のようにイメージできます。
128
64
32
16
8
4
2
1
0
0
0
0
0
0
0
0
ASCII
数字が1と0の2進法パターンであるのと同様に、文字も1と0を使って表されます。
数字と文字を表す1と0に重なりがあるため、特定の文字を特定の数字に対応させるために「ASCII」規格が作成されました。
例えば、文字 A は数字65に対応することが決定されました。01000001 は2進法で65を表します。これは以下のように視覚化できます。
128
64
32
16
8
4
2
1
0
1
0
0
0
0
0
1
テキストメッセージを受け取った場合、そのメッセージの背後にある2進法は、72、73、33という数字を表しているかもしれません。これらをASCIIにマッピングすると、メッセージは以下のようになります。
H I !
72 73 33
- これらの値について合意することを可能にしてくれるASCIIのような規格に感謝しましょう!
以下はASCII値の拡張マップです。
0
NUL
16
DLE
32
SP
48
0
64
@
80
P
96
`
112
p
1
SOH
17
DC1
33
!
49
1
65
A
81
Q
97
a
113
q
2
STX
18
DC2
34
”
50
2
66
B
82
R
98
b
114
r
3
ETX
19
DC3
35
#
51
3
67
C
83
S
99
c
115
s
4
EOT
20
DC4
36
$
52
4
68
D
84
T
100
d
116
t
5
ENQ
21
NAK
37
%
53
5
69
E
85
U
101
e
117
u
6
ACK
22
SYN
38
&
54
6
70
F
86
V
102
f
118
v
7
BEL
23
ETB
39
’
55
7
71
G
87
W
103
g
119
w
8
BS
24
CAN
40
(
56
8
72
H
88
X
104
h
120
x
9
HT
25
EM
41
)
57
9
73
I
89
Y
105
i
121
y
10
LF
26
SUB
42
*
58
:
74
J
90
Z
106
j
122
z
11
VT
27
ESC
43
+
59
;
75
K
91
[
107
k
123
{
12
FF
28
FS
44
,
60
<
76
L
92
\
108
l
124
13
CR
29
GS
45
-
61
=
77
M
93
]
109
m
125
}
14
SO
30
RS
46
.
62
>
78
N
94
^
110
n
126
~
15
SI
31
US
47
/
63
?
79
O
95
_
111
o
127
DEL
詳しく知りたい場合は、ASCIIについて学ぶことができます。
2進法では255までしか数えられないため、ASCIIで表現できる文字数には制限があります。
Unicode
時代が進むにつれ、テキストを介してコミュニケーションする方法はますます増えています。
人間が表現できる多様な文字をすべて表すには2進法の桁数が足りなかったため、「Unicode」規格により、コンピュータで送受信・理解できるビット数が拡張されました。Unicodeには特殊文字だけでなく、絵文字も含まれています。
あなたが毎日使っているであろう絵文字があります。以下は見覚えがあるかもしれません。
😀 😃 😄 😁 😆 😅 😂 🙂 🙃 😉 😊 😇 😍 😘 😗 😙 😚 😋 😛 😜 😝 🤑 🤓 😎 🤗 😏 😶 😐 😑 😒 🙄 😬 😕 ☹️ 😟 😮 😯 😲 😳 😦 😧 😨
0と1のパターンはUnicode内で標準化されていますが、デバイスメーカーごとに各絵文字の表示が他のメーカーと若干異なる場合があります。
さらなる文字や絵文字を表現するために、より多くの機能がUnicode規格に追加され続けています。
詳しく知りたい場合は、Unicodeについて学ぶことができます。
詳しく知りたい場合は、絵文字について学ぶことができます。
RGB
- 0と1は色を表すためにも使用できます。
赤、緑、青(「RGB」と呼ばれます)は、3つの数字の組み合わせです。
先ほど使った72、73、33という数字は、テキストでは HI! となりますが、画像リーダーでは明るい黄色として解釈されます。赤の値は72、緑の値は73、青の値は33になります。
赤、青、緑(RGB)のさまざまな色を表現するために必要な3バイトが、デジタル画像の各「ピクセル」(点)を構成します。画像は単純にRGB値の集まりです。
0と1は、画像、ビデオ、音楽を表すためにも使用できます!
ビデオは、パラパラ漫画のように、一緒に保存された多くの画像の連続です。
音楽も同様に、バイトのさまざまな組み合わせを使用して表現できます。
アルゴリズム
問題解決はコンピュータサイエンスとコンピュータプログラミングの中心です。「アルゴリズム」とは、問題を解決するための段階的な指示のセットです。
電話帳で特定の名前を探すという基本的な問題を考えてみましょう。
どのようにすればいいでしょうか?
1つの方法は、最後のページに到達するまで、1ページ目から次へ次へと読み進めることです。
別の方法は、一度に2ページずつ探すことです。
そしておそらくもっと良い方法は、電話帳の真ん中を開いて、「探している名前は左側にあるか、それとも右側にあるか?」と問いかけることです。そして、このプロセスを繰り返し、問題を半分、また半分と切り捨てていきます。
これらのアプローチはそれぞれアルゴリズムと呼ぶことができます。これらのアルゴリズムの速度は、「ビッグオー記法(big-O notation)」と呼ばれるもので次のように表すことができます。
赤色で示された最初のアルゴリズムは、ビッグオーが n です。電話帳に100の名前がある場合、正しい名前を見つけるのに最大100回かかる可能性があるためです。2ページずつ検索した2番目のアルゴリズムは、ページを2倍の速さで検索したため、ビッグオーは n/2 になります。最後のアルゴリズムのビッグオーは log2n です。問題を2倍にしても、問題を解決するためのステップは1つしか増えないためです。
- プログラマーは、テキストベースの人間向けの指示をコードに変換します。
疑似コード (Pseudocode)
指示をコードに変換するこのプロセスを「疑似コード(pseudocode)」と呼びます。
疑似コードを作成する能力は、このクラスとコンピュータプログラミングの両方で成功するために不可欠です。
疑似コードは、コードを人間が読めるようにしたものです。例えば、上記の3番目のアルゴリズムを考えると、次のように疑似コードを作成できます。
1 電話帳を手に取る
2 電話帳の真ん中を開く
3 ページを見る
4 もしその人がページにいれば
5 その人に電話する
6 そうでなく、もしその人が本の前の方にいれば
7 本の左側半分の真ん中を開く
8 3行目に戻る
9 そうでなく、もしその人が本の後ろの方にいれば
10 本の右側半分の真ん中を開く
11 3行目に戻る
12 そうでなければ
13 終了する
疑似コード化が重要なスキルである理由は、少なくとも2つあります。第一に、正式なコードを作成する前に疑似コード化することで、問題の論理を事前に考えることができます。第二に、疑似コード化しておけば、後であなたのコーディングの決定やコードの仕組みを理解しようとする他の人に情報を提供できます。
疑似コード内の言語には、いくつかのユニークな特徴があることに注目してください。まず、いくつかの行は「手に取る」「開く」「見る」といった動詞で始まっています。後に、これらを「関数(functions)」と呼びます。
第二に、いくつかの行には
もしやそうでなく、もしといった文が含まれていることに注目してください。これらは「条件分岐(conditionals)」と呼ばれます。第三に、「その人が本の前の方にいる」といった「真(true)」か「偽(false)」で述べることができる表現があることに注目してください。これらを「ブール式(boolean expressions)」と呼びます。
最後に、「3行目に戻る」といった文に注目してください。これを「ループ(loops)」と呼びます。
これらの構成要素はプログラミングの基礎です。
以下で説明する Scratch の文脈では、上記のプログラミングの各基本構成要素を使用します。
人工知能
上記の構成要素を活用して、独自の人工知能を作り始める方法を考えてみましょう。次の疑似コードを見てください。
もし学生が「こんにちは」と言ったら
「こんにちは」と言う
そうでなく、学生が「さようなら」と言ったら
「さようなら」と言う
そうでなく、学生が「元気?」と尋ねたら
「元気です」と言う
そうでなく、学生が「なぜ2進法の111は10進法の7なのですか?」と尋ねたら
...
ほんの一握りの対話をプログラミングするだけでも、何行ものコードが必要になることに注目してください。何千、何万もの対話を可能にするには、何行のコードが必要になるでしょうか?
上記のような対話型AIをプログラミングする代わりに、AIプログラマーは大規模なデータセットで「大規模言語モデル(LLM)」をトレーニングします。
LLMは、言語の大きな塊の中にあるパターンを見ます。このような言語モデルは、ある言葉の後に、あるいは隣に、どのような言葉が来るかを最適に予測しようとします。
AIベースのソフトウェアは人生や仕事の多くの場面で非常に有用ですが、CS50独自のもの以外のAIベースのソフトウェアを使用することは「合理的ではない(not reasonable)」と規定しています。
CS50.aiと呼ばれるCS50独自のAIベースのソフトウェアツールは、このコース中に使用できるAIヘルパーです。それはあなたを助けますが、コースの問題に対する答えをすべて教えてしまうことはありません。
このコースでは、CS50.ai 以外のAIを使用することは許可されていません。
今後の予定
- 今週は、ビジュアルプログラミング言語である Scratch について学びます。
その後、数週間後には C について学びます。それは次のようなものになります。
#include
int main(void)
{
printf("hello, world\n");
}
Cを学ぶことで、Python のような他のプログラミング言語での将来の学習に向けた準備がはるかに整います。
さらに、週が進むにつれて、アルゴリズムについても学んでいきます。
Cが非常に難しいのは、句読点(記号)のせいです。今日はその記号や構文(シンタックス)は置いておいて、Scratch というプログラミング言語でアイデアだけを扱っていきます。
Scratch
Scratch は、MITによって開発されたビジュアルプログラミング言語です。
Scratch は、この講義の前半で扱ったのと同じ基本的なコーディングの構成要素を利用しています。
Scratch は、波括弧、セミコロン、括弧などの構文を気にすることなく、視覚的な方法でこれらの構成要素を操作できるため、コンピュータプログラミングを始めるのに最適な方法です。
Scratch の IDE(統合開発環境)は以下のようになります。
左側には、プログラミングに使用できる「ビルディングブロック」のパレットがあります。ビルディングブロックのすぐ右側には、プログラムを構築するためにブロックをドラッグできるエリアがあります。その右側には、猫が立っている「ステージ」があります。ステージは、あなたのプログラミングが形になるところです。
Scratch は、次のような座標系で動作します。
ステージの中心は座標 (0,0) です。現在、猫の位置はその中心にあります。
Hello World
まず、「緑の旗が押されたとき」というビルディングブロックをプログラミングエリアにドラッグします。次に、と言う ビルディングブロックをプログラミングエリアにドラッグし、前のブロックに取り付けます。
when green flag clicked
say [hello, world]
ステージ上の緑の旗をクリックすると、猫が「hello, world」と言います。
これは、プログラミングに関して先ほど話し合った内容を非常によく表しています。
入力 hello, world が関数 say に渡され、その関数が実行されることの「副作用(side effect)」として猫が hello, world と言うのです。
Hello, You
特定の誰かに「こんにちは」と言うようにして、プログラムをよりインタラクティブにすることができます。次のようにプログラムを修正してください。
when green flag clicked
ask [What's your name?] and wait
say (join [hello,] (answer))
緑の旗がクリックされると、尋ねて待つ という関数が実行されます。プログラムはユーザーであるあなたに What's your name? と促します。そして、その名前を 答え という「変数(variable)」に保存します。次に、プログラムはその 答え を、2つのテキスト(hello と提供された名前)を組み合わせる 連結する(join) という特別な関数に渡します。文字通り、答え は値を 連結する に返します。これらはまとめて と言う 関数に渡されます。猫は Hello, と名前を言います。これでプログラムはインタラクティブになりました。
このコースを通して、アルゴリズムに入力を与え、出力(または副作用)を得ることになります。これは、上記のプログラムに当てはめると次のように描けます。
入力 hello, と 答え が 連結する に与えられ、その副作用として hello, David と言われます。
同様に、次のようにプログラムを修正できます。
when green flag clicked
ask [What's your name?] and wait
speak (join [hello,] (answer))
このプログラムは、緑の旗がクリックされると、同じ変数を hello と連結して、話す という関数に渡します。
ニャーと抽象化 (Meow and Abstraction)
疑似コード化と並んで、「抽象化(abstraction)」はコンピュータプログラミングにおける不可欠なスキルであり概念です。
抽象化とは、問題をより小さな問題へと単純化する行為です。
例えば、友人のために盛大なディナーを催すとしたら、食事全体を料理しなければならないという「問題」は、かなり圧倒されるかもしれません!しかし、料理を作るというタスクをより小さなタスク(問題)に分解すれば、この美味しい食事を作るという大きなタスクは、それほど難しく感じられないかもしれません。
プログラミング、そして Scratch の中でも、抽象化が働いているのを見ることができます。プログラミングエリアで、次のようにプログラミングしてください。
when green flag clicked
play sound (Meow v) until done
wait (1) seconds
play sound (Meow v) until done
wait (1) seconds
play sound (Meow v) until done
同じことを何度も繰り返していることに注目してください。実際、同じ文を繰り返しコードしていることに気づいたら、それはおそらく、より巧妙にプログラミングできる、つまり繰り返しのコードを「抽象化」できる可能性が高いです。
次のようにコードを修正できます。
when green flag clicked
repeat (3)
play sound (Meow v) until done
wait (1) seconds
このループは、前のプログラムとまったく同じことを行います。しかし、コードを「繰り返す」ブロックに繰り返しを抽象化することで、問題が単純化されています。
さらに、定義 ブロックを使用して独自のブロック(独自の関数)を作成することで、これをさらに進めることができます!次のようにコードを書いてください。
define meow
play sound (Meow v) until done
wait (1) seconds
when green flag clicked
repeat (3)
meow
meow という独自のブロックを定義していることに注目してください。この関数は「ニャー」という音を鳴らし、1秒待ちます。その下では、緑の旗がクリックされたときに、この meow 関数が3回繰り返されるようになっています。
さらに、関数が入力 n を受け取り、指定された回数繰り返すようにすることもできます。
define meow n times
repeat (n)
play sound [meow v] until done
wait (1) seconds
n が「meow n times」から取得される仕組みに注目してください。n は 定義 ブロックを通じて meow 関数に渡されます。
- 全体として、この洗練のプロセスが、より優れた設計のコードにつながったことに注目してください。さらに、問題を解決するために独自のアルゴリズムを作成したことにも注目してください。このコースを通して、これらのスキルの両方を練習していくことになります。
条件分岐 (Conditionals)
「条件分岐(conditionals)」はプログラミングの不可欠な構成要素であり、プログラムが特定の条件が満たされたかどうかを確認します。条件が満たされた場合、プログラムは何かを実行します。
条件分岐を説明するために、次のようにコードを書いてください。
when green flag clicked
forever
if then
play sound (Meow v) until done
ずっと(forever) ブロックが使用されているため、もし(if) ブロックが何度も繰り返され、猫がマウスのポインターに触れているかどうかを継続的にチェックできることに注目してください。
ビデオセンシングを統合するために、プログラムを次のように修正できます。
when video motion > (10)
play sound (Meow v) until done
- プログラミングはしばしば試行錯誤のプロセスであることを忘れないでください。イライラしたら、時間をかけて目の前の問題を自分自身に説明してみてください。今取り組んでいる具体的な問題は何ですか?何がうまくいっていますか?何がうまくいっていませんか?
Oscartime
Oscartime は David 自身の Scratch プログラムの1つです。このプログラムを作成している間、何時間もその音楽を聴いていたため、彼にとっては忘れられないものかもしれません。数分間、自分でゲームをプレイしてみてください。
自分で Oscartime を構築する場合、まず街灯を追加します。
次に、次のようにコードを書きます。
when green flag clicked
switch costume to (oscar1 v)
forever
if then
switch costume to (oscar2 v)
else
switch costume to (oscar1 v)
マウスをオスカーの上に動かすと、彼のコスチュームが変わることに注目してください。これらのコードブロックを探索することで、より詳しく学ぶことができます。
次に、次のようにコードを修正して、落ちてくるゴミを作成します。
when green flag clicked
go to x: (pick random (-240) to (240)) y: (180)
forever
if (0)> then
change y by (-3)
ゴミのy軸の位置が常に180から始まることに注目してください。xの位置はランダム化されます。ゴミが床より上にある間は、一度に3ピクセルずつ下がります。これらのコードブロックを探索することで、より詳しく学ぶことができます。
次に、ゴミをドラッグできるようにコードを修正します。
when green flag clicked
forever
if and > then
go to (mouse-pointer v)
これらのコードブロックを探索することで、より詳しく学ぶことができます。
次に、次のようにスコア変数を実装できます。
when green flag clicked
forever
if then
change (score) by (1)
go to x: (pick random (-240) to (240)) y: (180)
これらのコードブロックを探索することで、より詳しく学ぶことができます。
- フルゲームの Oscartime を試してみてください。
Ivy’s Hardest Game
Oscartime から Ivy’s Hardest Game(アイビーの最高に難しいゲーム)に移り、プログラム内での動きをどのように実装するかを考えてみましょう。
私たちのプログラムには、主に3つのコンポーネントがあります。
まず、次のようにコードを書きます。
when green flag clicked
go to x: (0) y: (0)
forever
listen for keyboard
feel for walls
緑の旗がクリックされると、スプライトが座標 (0,0) のステージ中央に移動し、その後、キーボードをリッスン(入力待ち)し、壁がないかずっとチェックし続けることに注目してください。
次に、2番目のコードブロックのグループを追加します。
define listen for keyboard
if then
change y by (1)
end
if then
change y by (-1)
end
if then
change x by (1)
end
if then
change x by (-1)
end
カスタムの listen for keyboard スクリプトを作成したことに注目してください。キーボードの各矢印キーに対して、画面上でスプライトを移動させます。
最後に、このコードブロックのグループを追加します。
define feel for walls
if then
change x by (1)
end
if then
change x by (-1)
end
カスタムの feel for walls スクリプトもあることに注目してください。スプライトが壁に触れると、安全な位置に戻し、画面外に出てしまうのを防ぎます。
これらのコードブロックを探索することで、より詳しく学ぶことができます。
Scratch では、多くのスプライトを一度に画面に出すことができます。
別のスプライトを追加し、プログラムに次のコードブロックを追加します。
when green flag clicked
go to x: (0) y: (0)
point in direction (90)
forever
if or > then
turn right (180) degrees
end
move (1) steps
end
エール(Yale)のスプライトが、前後に移動することでハーバード(Harvard)のスプライトの邪魔をしているように見えることに注目してください。壁にぶつかると、再び壁にぶつかるまで向きを変えます。これらのコードブロックを探索することで、より詳しく学ぶことができます。
スプライトが別のスプライトを追いかけるようにすることもできます。別のスプライトを追加し、プログラムに次のコードブロックを追加します。
when green flag clicked
go to (random position v)
forever
point towards (Harvard v)
move (1) steps
MITのロゴがハーバードのロゴを追いかけているように見えることに注目してください。これらのコードブロックを探索することで、より詳しく学ぶことができます。
- フルゲームの Ivy’s Hardest Game を試してみてください。
まとめ
このレッスンでは、このコースがコンピュータサイエンスとプログラミングの広い世界の中でどのような位置づけにあるかを学びました。あなたが学んだことは……
以前にプログラミング経験がある学生は、このクラスにはほとんどいないこと!
あなたは一人ではありません!あなたはコミュニティの一員です。
問題解決こそがコンピュータ科学者の仕事の本質であること。
このコースは単にプログラミングに関するものではなく、人生のほぼすべての分野に応用できる新しい学習方法を紹介するものであること。
数字、テキスト、画像、音楽、ビデオがコンピュータによってどのように理解され、表現されるか。
疑似コード化という基本的なプログラミングスキル。
このコースにおける、AIを活用する上での合理的、あるいは不合理な方法。
抽象化がこのコースの将来の学習においてどのような役割を果たすか。
関数、条件分岐、ループ、変数を含むプログラミングの基本的な構成要素。
Scratch でプロジェクトを構築する方法。
これが CS50 でした!ようこそ!また次回お会いしましょう!