sp-11. 構造体とグラフィックス
1
金子邦彦
Scheme プログラミング)
URL: https://www.kkaneko.jp/pro/scheme/index.html
トライン
11-1 define による変数定義
11-2 DrScheme でのグラフィックス
11-3 パソコン演習
11-4 課題
2
11-1 define による変数定義
3
変数には,名前がある
(define PI 3.14)
(define A (list 15 8 6))
例)
名前
変数
4
(define A (list 15 8 6))
変数名 リストの本体
リストの変数定義
5
「オブジェクト」に名前を付けたもの
オブジェクトとは,数値,文字列,リス
トなど.「値」を持つ
コンピュータは,変数の値と名前の関
係を記憶している
変数とは
6
11-2 DrScheme でのグラフィックス
7
DrScheme のグラフィックス機能である draw.ss
teachpack
start: 「描画用インド」を開く
draw-solid-line:
draw-solid-rect: 四角形
draw-solid-disk: 塗りつぶされた円
clear-solid-disk: 一度描いた「塗りつぶされた円」を
draw-circle:
stop: 「描画用インド」を閉じる
DrScheme でのグラフィックス
8
11-3 パソコン演習
9
資料を見ながら,「例題」を行ってみ
各自,「課題」に挑戦する
遠慮なく質問してください
自分のペースで先に進んで構いません
パソコン演習の進め方
10
DrScheme の起動
プログラム PLT Scheme → DrScheme
今日の演習では「Intermediate Student
に設定
Language
→ Choose Language
→ Intermediate Student
→ Execute ボタン
DrScheme の使用
11
DrScheme の描画機能である draw.ss teachpack を使ために,
draw.ss teach pack をロードせよ
この操作は1回だけでよい
(次回からは自動的にロードされるよ
なる)
draw.ss teach pack のロード
12
Language
Add Teachpack
→ htdp ディレクトリを選択
→ draw.ss を選択
→ Execute ボタン
draw.ss teach pack のロード
13
DrScheme の描画機能である draw.ss teachpack
使って,簡単な絵を描く
start: 「描画用インド」を開く
draw-solid-line:
draw-solid-rect: 四角形
draw-solid-disk: 塗りつぶされた円
clear-solid-disk: 一度描いた「塗りつぶされた円」を
draw-circle:
stop: 「描画用インド」を閉じる
例題1.簡単な絵を描く
14
1. 次を「実行用インド」で実行しなさい
次は,例題2に進んでください
(start 100 100)
(draw-solid-line (make-posn 0 0) (make-posn 80 80) 'red)
(draw-solid-rect (make-posn 50 50) 50 20 'green)
(draw-circle (make-posn 20 20) 20 'blue)
(draw-solid-disk (make-posn 70 70) 10 'red)
stop)
「例題1.簡単な絵を描く」の手
15
16
17
例題1の実行結果
描画用インド
現れる
(start 100 100)
描画用のインドを開く
描画の実行
描画用インドを閉じる
(draw-solid-line (make-posn 0 0) (make-posn 80 80) 'red)
(draw-solid-rect (make-posn 50 50) 50 20 'green)
(draw-circle (make-posn 20 20) 20 'blue)
(draw-solid-disk (make-posn 70 70) 10 'red)
(stop)
例題1のまとめ
18
19
ball 構造体を使って,(x, y) の位置に円を描くプ
ログラム draw-ball を書く
構造体とグラフィックス処理の組み合わせ
ball 構造体の属性値を設定するために make-ball (コ
ンストラクタ)を使
属性 x, y を取り出すために ball-x, ball-y (セレクタ)
を使
位置
速度
x
y
delta-x
delta-y
例題2.ball 構造体を描く
20
1. 次を「定義用インド」で,実行しなさい
入力した後に,Execute ボタンを押す
(define-struct ball
(x y delta-x delta-y))
;; draw-ball: a ball -> none
;; draw a solid disk at (x,y)
(define (draw-ball a-ball)
(draw-solid-disk (make-posn
(ball-x a-ball)
(ball-y a-ball))
5 'red))
2. その後,次を「実行用ンド」で実行しなさい
次は,例題3に進んでください
(start 100 100)
(draw-ball (make-ball 10 10 0 0))
(stop)
「例題2.ball 構造体を描く」の手順
21
まず,ball 構造体を
定義している
22
次に,関数 draw-ball
定義している
23
24
描画用インド
現れる
25
ball は,x, y, delta-x, delta-y から構成する
位置
速度
x
y
delta-x
delta-y
(define-struct ball
(x y delta-x delta-y))
名前
属性の並び
ball 構造体
26
(define-struct ball
(x y delta-x delta-y))
;; draw-ball: a ball -> none
;; draw a solid disk at (x,y)
(define (draw-ball a-ball)
(draw-solid-disk (make-posn
(ball-x a-ball)
(ball-y a-ball))
5 'red))
(start 100 100)
(draw-ball (make-ball 10 10 0 0))
(stop) 27
リスト (list 15 8 6) を値として持つ
変数Aを定義する
変数を定義するために define を使
リストを作るために cons を使
例題3.リストの変数定義
28
1. 次を「定義用インド」で,実行しなさい
入力した後に,Execute ボタンを押す
(define A (list 15 8 6))
2. その後,次を「実行用インド」で実行しなさい
次は,例題4に進んでください
A
(first A)
(rest A)
「例題3.リストの変数定義」の手順
29
まず,
(define A (list 15 8 6))
と書いて,変数Aの定義
を行っている
30
A
と実行すると,Aの値である
(list 15 8 6)
が表示される 31
(first A), (rest A)
実行している
32
次のプログラムを実行し,「(name-list book)
から「(list "Mike" "Bill" "Ken")」に至る過程の
を見る
(define-struct address-record
(name age address))
(define book (list
(make-address-record "Mike" 10 "Fukuoka")
(make-address-record "Bill" 20 "Saga")
(make-address-record "Ken" 30 "Nagasaki")))
(define (name-list a-book)
(cond
[(empty? a-book) empty]
[else
(cons (address-record-name (first a-book))
(name-list (rest a-book)))]))
例題4.構造体のリスト
33
1. 次を「定義用インド」で,実行しなさい
入力した後に,Execute ボタンを押す
(define-struct address-record
(name age address))
(define book (list
(make-address-record "Mike" 10 "Fukuoka")
(make-address-record "Bill" 20 "Saga")
(make-address-record "Ken" 30 "Nagasaki")))
2. その後,次を「実行用インドで実行しなさい
次は,例題5に進んでください
book
(first book)
(address-record-address (first book))
「例題4.構造体のリスト」の手
34
AddressNote 構造体の定義
変数 book の定義
AddressNote 構造体のリスト
変数 book の操作
35
「頂点」のリストを値として持つ変
P を定義する
変数を定義するために define を使
1つの頂点 posn 構造体
make-posn を使用
リストを作るために cons を使
例題5.頂点のリストを値とする
変数の定義
36
1. 次を「定義用インド」で,実行しなさい
入力した後に,Execute ボタンを押す
(define P
(cons (make-posn 0 0)
(cons (make-posn 10 70)
(cons (make-posn 100 30) empty))))
2. その後,次を「実行用インドで実行しなさい
次は,例題6に進んでください
P
(first P)
(rest P)
「例題5.頂点のリストを値とする
変数の定義」の手順
37
0x
y
(0, 0)
(10, 70)
(100, 100)
38
まず,変数Pの定義
を行っている
39
Pの値が表示されている
40
(first P), (rest P)
実行している
41
(define P
(cons (make-posn 0 0)
(cons (make-posn 10 70)
(cons (make-posn 100 30)
empty))))
変数名
リストの本体
変数定義
42
posn 構造体は,すでに DrScheme に組み込み済
(define-struct 構造名) を実行していなくても,
posn 構造体を使ことができる
posn 構造体
43
折れ線を描くプログラム draw-
polyline を作り,実行する
1つの「頂点」 構造体
折れ線 「頂点」のリスト
例題6.折れ線
44
1. 次を「定義用インド」で,実行しなさい
入力した後に,Execute ボタンを押
2. その後,次を「実行用インド」で実行しなさい
次は,例題7に進んでください
(start 100 100)
(draw-polyline P)
(stop)
例題5と同じ
(define P
(cons (make-posn 0 0)
(cons (make-posn 10 70)
(cons (make-posn 100 30) empty))))
(define (draw-polyline a-poly)
(cond
[(empty? (rest a-poly)) true]
[else (and
(draw-solid-line (first a-poly)
(first (rest a-poly)))
(draw-polyline (rest a-poly)))]))
「例題6.折れ線」の手順
45
46
draw-polyline
true
入力 出力
a-poly の値:
(cons (make-posn 0 0)
(cons (make-posn 10 70)
(cons (make-posn 100 30) empty)))
入力は posn 構造体
のリスト
出力は常に true
入力と出力
47
(define (draw-polyline a-poly)
(cond
[(empty? (rest a-poly)) true]
[else (and
(draw-solid-line (first a-poly)
(first (rest a-
poly)))
(draw-polyline (rest a-poly)))]))
自明な解
終了条件
48
1. (rest a-poly) が空ならば終了条件
true 自明な解
2. で無ければ
2点: (first a-poly) (first (rest a-poly))
を使って,線分を書き,その後
(draw-polyline (rest a-poly))
を実行
結局,すべての点について,線分を描くことを
繰り返す
折れ線 draw-polyline
49
(empty? (rest a-poly))
(and
(draw-solid-line (first a-poly)
(first (rest a-poly)))
(draw-polyline (rest a-poly)))
Yes
No
true が自明の解
折れ線の終了条件
50
(and
(draw-solid-line (first a-poly)
(first (rest a-poly)))
(draw-polyline (rest a-poly)))
描画命令 draw-solid-line
animation とを and でつないでいる
描画命令と他の命令を並べるときは「and
でつなぐ
51
描画命令と他の命令
が並んでいるのだが、
and」を
書き忘れている
エラーが出て,
実行できない
よくある間違い
52
(draw-polyline P) から
true が得られる過程の概略 (1/2)
(draw-polyline P)
= (draw-polyline (list (make-posn 0 0) (make-posn 10 70)
(make-posn 100 30)))
= ...
= (and
(draw-solid-line (makeposn 0 0) (make-posn 10 70))
(draw-polyline (rest (list (make-posn 0 0) (make-posn 10
70) (make-posn 100 30)))))
= …
= (draw-polyline (rest (list (make-posn 0 0) (make-posn 10
70) (make-posn 100 30))))
= (draw-polyline (list (make-posn 10 70) (make-posn 100
30)))
最初の式
コンピュータ内部での計算 53
(draw-polyline P) から
true が得られる過程の概略 (2/2)
= ...
= (and
(draw-solid-line (makeposn 10 70) (make-posn 100
30))
(draw-polyline (rest (list (make-posn 10 70) (make-
posn 100 30)))))
= …
= (draw-polyline (rest (list (make-posn 10 70) (make-
posn 100 30))))
= (draw-polyline (list (make-posn 100 30)))
= ...
= true
終了条件が
成立
コンピュータ内部での計算
実行結果
54
折れ線を描くプログラム draw-
polygon を作り,実行する
1つの「頂点」 構造体
折れ線 「頂点」のリスト
終点と始点を結ぶ(これが,例題
6との違い)
例題7.多角形
55
1. 次を「定義用インド」で,実行しなさい
入力した後に,Execute ボタンを押す
例題6と同じ
(define P
(cons (make-posn 0 0)
(cons (make-posn 10 70)
(cons (make-posn 100 30) empty))))
(define (draw-polyline a-poly)
(cond
[(empty? (rest a-poly)) true]
[else (and
(draw-solid-line (first a-poly)
(first (rest a-poly)))
(draw-polyline (rest a-poly)))]))
(define (last a-poly)
(cond
[(empty? (rest a-poly)) (first a-poly)]
[else (last (rest a-poly))]))
(define (draw-polygon a-poly)
(draw-polyline (cons (last a-poly) a-poly)))
「例題7.多角形」の手 (1/2)
56
2. その後,次を「実行用ンド」で実行しなさい
次は,課題に進んでください
(start 100 100)
(draw-polygon P)
(stop)
「例題7.多角形」の手 (2/2)
57
58
draw-polygon
true
入力 出力
a-poly の値:
(cons (make-posn 0 0)
(cons (make-posn 10 70)
(cons (make-posn 100 30) empty)))
入力は posn 構造体
のリスト
出力は常に true
入力と出力
59
draw-polygon
true
入力 出力
入力は posn 構造体
のリスト
出力は常に true
draw-polyline
(例題5と同じプログラム)
(cons (last a-poly) a-poly))
draw-polyling の入力
として与える
a-poly
draw-polygon の中で行っていること
60
(define (draw-polyline a-poly)
(cond
[(empty? (rest a-poly)) true]
[else (and
(draw-solid-line (first a-poly)
(first (rest a-poly)))
(draw-polyline (rest a-poly)))]))
(define (last a-poly)
(cond
[(empty? (rest a-poly)) (first a-poly)]
[else (last (rest a-poly))]))
(define (draw-polygon a-poly)
(draw-polyline (cons (last a-poly) a-poly))) 61
(draw-polygon P)
= (draw-polygon (list (make-posn 0 0) (make-posn 10
70) (make-posn 100 30)))
= ...
= (draw-polyline (list (make-posn 100 30) (make-posn
0 0) (make-posn 10 70) (make-posn 100 30)))
以下省略
(cons (last a-poly) a-poly)) 実行結果
(draw-polygon P) からの過程の概略
62
例題1との関係
draw_function: 入力: 折れ線のリスト
draw_接線
draw_小区画
折れ線のリストからの描画
63
11-4 演習課題
64
次の式を順に実行し,実行結果を報告せよ.
1. (start 300 300)
2. (draw-solid-line (make-posn 100 100) (make-
posn 200 200) ’red)
3. (draw-circle (make-posn 200 100) 50 ’red)
4. (draw-solid-disk (make-posn 100 200) 50 ’green)
5. (stop)
課題1
65
ball 造体(授業の例題2)についての問題
ball のデータ a-ball から,ボールの速さを求める関
数を作成し,実行結果を報告しなさい
ボールの速さは: √δx2+ δy2
課題2
66
ball 構造体(授業の例題2)についての問題
ball のデータ a-ball について,「x < 0 または y < 0
または x > 100 または y > 100 のときのみ true を出
力し,そでなければfalseを出力」 するよな関数
を作成し,実行結果を報告しなさい
課題3
67
x-y 平面上の2点 abから,その間の距離を求
める関数 distance を作成し,実行結果を報告しな
さい
2点 a, bのための構造体を定義すること
課題4
68
複数のball を描画するプログラムの作成.
次の関数 draw-ball は, ball のデータ a-ball から
1つのballを描くプログラムである.
これを参考にして,複数のballを描く関数 draw-
all-balls を作成しなさい.draw-all-balls の入力
ball構造体のリストである.
複数の ball を扱ので,ball 構造体のリストを扱
ことになる
必ず動作確認まで行こと.
(define (draw-ball a-ball)
(draw-solid-disk (make-posn
(ball-x a-ball) (ball-y a-ball)) 5 'red))
課題5
69
複数のball を消すプログラムの作成.
次の関数 clear-ball は, ball のデータ a-ball から
1つのballを消すプログラムである.
これを参考にして,複数のballを描く関数 clear-
all-balls を作成しなさい.clear-all-balls の入力
ball構造体のリストである.
必ず動作確認まで行こと.
(define (clear-ball a-ball)
(clear-solid-disk (make-posn
(ball-x a-ball) (ball-y a-ball)) 5))
課題6
70
さらに勉強したい人へ
補足説明資料
DrScheme のアニメーション
71
Dr Scheme でのタイマー機能とアニメー
ション
内容
72
ball 構造体(授業の例題2)を使って,(x, y) の位置
に,ball を1秒だけ描くための関数 draw-and-clear
を作り,実行する
円を描く関数: draw-solid-disk 関数を使
円を消す関数: clear-solid-disk 関数を使
円を書いた後に, sleep-for-a-while 関数を使って1秒待ち
円を消す
and 文を使いdraw-solid-disk, sleep-for-a-while, clear-
solid-disk 順次実行する
例題8.ball を1秒描く
73
1. 次を「定義用インド」で,実行しなさい
入力した後に,Execute ボタンを押す
(define-struct ball
(x y delta-x delta-y))
(define DELAY 1)
;;draw-and-clear: ball -> true
;;draw, sleep, clear a disk from the canvas
;;structural design, Scheme knowledge
(define (draw-and-clear a-ball)
(and
(draw-solid-disk (make-posn (ball-x a-ball) (ball-y a-ball)) 5 'red)
(sleep-for-a-while DELAY)
(clear-solid-disk (make-posn (ball-x a-ball) (ball-y a-ball)) 5 'red)))
2. その後,次を「実行用インド」で実行しなさい
(start 100 100)
(draw-and-clear (make-ball 10 10 0 0))
(stop)
例題2と同じ
「例題8.ball を1秒描く」の手順
74
75
(draw-and-clear (make-ball 10 10 0 0))
の実行時に,「描画用インド
に,赤い円が現れて消えるので,確
認すること
ball を1秒描く
76
(define DELAY 1)
(define-struct ball (x y delta-x delta-y))
;;draw-and-clear:a-ball->true
;;draw, sleep, clear a disk from the canvas
;;structural design, Scheme knowledge
(define (draw-and-clear a-ball)
(and
(draw-solid-disk (make-posn (ball-x a-ball) (ball-y a-ball)) 5 'red)
(sleep-for-a-while DELAY)
(clear-solid-disk (make-posn (ball-x a-ball) (ball-y a-ball)) 5 'red)))
(strart 100 100)
(draw-and-clear (make-ball 10 10 0 0))
(stop)
変数 DELAY の定義
関数 draw-and-clear
draw-and-clear
使っている部分
ball 構造
77
(and
(draw-solid-disk (make-posn (ball-x a-ball) (ball-y a-ball)) 5 'red)
(sleep-for-a-while DELAY)
(clear-solid-disk (make-posn (ball-x a-ball) (ball-y a-ball)) 5 'red))
3つの描画命
draw-solid-disk, sleep-for-a-while, clear-solid-disk
and つないでいる
複数の描画命令を並べるときは
and」でつなぐ
78
複数の描画命令
が並んでいるのだが、
and」を
書き忘れている
エラーが出て,
実行できない
よくある間違い
79
ball 構造体(授業の例題2)を使って,動く
ボールのアニメーションのプログラム animation
を作る
ボールを動かすための関数 move-ball を作る
動くボールのアニメーションの関数 animation は,
move-ball draw-and-clear(授業の例題8) を呼
び出すと共に,animation(自分自身) を再帰的に呼
び出す
例題9.動く ball を描く
80
1. 次を「定義用インド」で,実行しなさい
入力した後に,Execute ボタンを押す
(define-struct ball
(x y delta-x delta-y))
(define DELAY 1)
(define (draw-ball a-ball)
(draw-solid-disk (make-posn
(ball-x a-ball) (ball-y a-ball)) 5 'red))
(define (clear-ball a-ball)
(clear-solid-disk (make-posn
(ball-x a-ball) (ball-y a-ball)) 5))
(define (move-ball a-ball)
(make-ball
(+ (ball-x a-ball) (ball-delta-x a-ball))
(+ (ball-y a-ball) (ball-delta-y a-ball))
(ball-delta-x a-ball) (ball-delta-y a-ball)))
(define (animation a-ball)
(and
(draw-ball a-ball)
(sleep-for-a-while DELAY)
(clear-ball a-ball)
(animation (move-ball a-ball))))
「例題9.動く ball を描く」の手順 (1/2)
81
2. その後,次を「実行用インド」で実行しなさい
(start 100 100)
(animation (make-ball 0 0 10 5))
(stop)
「例題9.動く ball を描く」の手順 (2/2)
82
83
「描画用インド」に,赤い円が動く様子を確
認すること
満足したら「(stop)」を実行して,「描画用
ンド」を閉じる
84
動く ball を描く
(define-struct ball
(x y delta-x delta-y))
(define DELAY 1)
(define (draw-ball a-ball)
(draw-solid-disk (make-posn
(ball-x a-ball) (ball-y a-ball)) 5 'red))
(define (clear-ball a-ball)
(clear-solid-disk (make-posn
(ball-x a-ball) (ball-y a-ball)) 5))
(define (move-ball a-ball)
(make-ball
(+ (ball-x a-ball) (ball-delta-x a-ball))
(+ (ball-y a-ball) (ball-delta-y a-ball))
(ball-delta-x a-ball) (ball-delta-y a-ball)))
(define (animation a-ball)
(and
(draw-ball a-ball)
(sleep-for-a-while DELAY)
(clear-ball a-ball)
(animation (move-ball a-ball))))
変数 DELAY の定義
ball 構造
draw-ball 関数
move-ball 関数
animation 関数
clear-ball 関数
85
(define (animation a-ball)
(and
(draw-ball a-ball)
(sleep-for-a-while DELAY)
(clear-ball a-ball)
(animation (move-ball a-ball))))
描画命令の1種である sleep-for-a-while
他の式を and でつないでいる
描画命令と他の命令を並べるときは「and」で
つなぐ
86
複数のball を動かすプログラムの作成.
次の関数 move-ball は,1つの ball を動かすプ
ログラムである.速度からの位置の計算を行って
いる
これを参考にして,複数のballを動かす関数
move-all-balls を作成しなさい.move-all-balls
の入力はball構造体のリストである.
必ず動作確認まで行こと.
(define (move-ball a-ball)
(make-ball
(+ (ball-x a-ball) (ball-delta-x a-ball))
(+ (ball-y a-ball) (ball-delta-y a-ball))
(ball-delta-x a-ball) (ball-delta-y a-ball)))
課題7
87
課題5で作成したプログラムを変更して,
ballが「描画用インドの外にあれば
「描画用インド」を閉じるよにしなさ
い.
また,「描画用インド」の外にあるボー
ルについては,draw-solid-disk を実行しない
にしなさい
描画用インドを閉じるには「(stop)」を用いる
課題8
88
例題9を参考にして,複数のballのアニメー
ションのプログラムを作成し,実行結果を報
告しなさい
作成したアニメーションプログラムが,全ての
ball が「描画用インド」の外に出たら,アニ
メーションが終わるよになっていることを確認
すること
もし,アニメーションが終わらないのなら,必ず
終わるよに変更すること
課題9
89
課題9についての問
動いている間に大きさや色が変るよにプログラ
ムを変更しなさい
課題10
90
課題9についての問
「描画用インド」の境界まで達したら,跳ね
返りの角度や速度などを変えて,跳ね返るよ
プログラムを変更しなさい
課題11
91