2013年2月8日金曜日

開発環境

『初めてのプログラミング 第2版』(Chris Pine 著、長尾 高弘 訳、オライリー・ジャパン、2010年、ISBN978-4-87311-469-9)の 13章(新しいクラスの作成と既存のクラスの変更), 13.6(練習問題の続き)対話的ベビードラゴン を解いてみる。

その他参考書籍

対話的ベビードラゴン

コード(BBEdit)

sample.rb

#!/usr/bin/env ruby1.9
#-*- coding: utf-8 -*-

class Dragon
    def initialize name
        @name = name
        @asleep = false
        @stuff_in_belly = 10
        @stuff_in_intestine = 0
        puts "#{@name}が生まれました"
    end
    def feed
        puts "#{@name}にご飯をあげます。"
        @stuff_in_belly = 10
        passage_of_time
    end
    def walk
        puts "#{@name}をトイレに連れていきます"
        @stuff_in_intestine = 0
        passage_of_time
    end
    def put_to_bed
        puts "#{@name}を寝かしつけます。"
        @asleep = true
        3.times do
            if @asleep
                passage_of_time
            end
            if @asleep
                puts "#{@name}がいびきをかいて、部屋が煙だらけです。"
            end
        end
        if @asleep
            @asleep = false
            puts "#{@name}はゆっくり目覚めます。"
        end
    end
    def toss
        puts "#{@name}に高い高いをします。"
        puts "#{@name}が笑ってあなたの眉毛が焦げます。"
        passage_of_time
    end
    def rock
        puts "#{@name}をやさしくあやします。"
        @asleep = true
        puts "#{@name}は少し居眠りをします。"
        passage_of_time
        if @asleep
            @asleep = false
            puts "しかし、やめると起きてしまいます。"
        end
    end
    
    private
    
    def hungry?
        @stuff_in_belly <= 2
    end
    def poopy?
        @stuff_in_intestine >= 8
    end
    def passage_of_time
        if @stuff_in_belly > 0
            @stuff_in_belly -= 1
            @stuff_in_intestine += 1
        else
            if @asleep
                @asleep = false
                puts "#{@name}が突然目を覚まします!"
            end
            puts "#{@name}がお腹を空かせています。我慢できなくてあなたを食べました。"
            exit
        end
        if @stuff_in_intestine >= 10
            @stuff_in_intestine = 0
            puts "うわっ、#{@name}がおもらしを・・・・・・"
        end
        if hungry?
            if @asleep
                @asleep = false
                puts "#{@name}が突然目を覚まします!"
            end
            puts "#{@name}のお腹が鳴っています。"
        end
        if poopy?
            if @asleep
                @asleep = false
                puts "#{@name}が突然目を覚まします!"
            end
            puts "#{@name}がうんちのためにしゃがみ込みます。"
        end
    end
end

print "名前を入力: "
name = gets.chomp
name = "匿名" if name =~ /^\s*$/
pet = Dragon.new name
while true
    print "コマンド(f/w/p/t/r)を入力(空白で終了): "
    command = gets.chomp
    break if command =~ /^\s*$/
    case command
        when 'f' then pet.feed
        when 'w' then pet.walk
        when 'p' then pet.put_to_bed
        when 't' then pet.toss
        when 'r' then pet.rock
        else puts "コマンドを確認してください。"
    end
end

入出力結果(Terminal)

$ ./sample.rb
名前を入力: ノーバート
ノーバートが生まれました
コマンド(f/w/p/t/r)を入力(空白で終了): f
ノーバートにご飯をあげます。
コマンド(f/w/p/t/r)を入力(空白で終了): t
ノーバートに高い高いをします。
ノーバートが笑ってあなたの眉毛が焦げます。
コマンド(f/w/p/t/r)を入力(空白で終了): w
ノーバートをトイレに連れていきます
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートがいびきをかいて、部屋が煙だらけです。
ノーバートがいびきをかいて、部屋が煙だらけです。
ノーバートがいびきをかいて、部屋が煙だらけです。
ノーバートはゆっくり目覚めます。
コマンド(f/w/p/t/r)を入力(空白で終了): r
ノーバートをやさしくあやします。
ノーバートは少し居眠りをします。
しかし、やめると起きてしまいます。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートのお腹が鳴っています。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートのお腹が鳴っています。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートのお腹が鳴っています。
ノーバートがうんちのためにしゃがみ込みます。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートがお腹を空かせています。我慢できなくてあなたを食べました。
$

ちなみにJavaScriptの場合。

コード(BBEdit)

<pre id='pre0' ></pre>
<label id="name_label">名前を入力: <input id="dragon_name" type="text" value="ノーバート" /></label>
<input id="dragon_named" type="button" value="決定!" />
<div id="d0"></div>
<script>
var Dragon = function( name ) {
    var name = name,
        asleep = false,
        belly = 10,
        intestine = 0;
        hungry = function() {
            return belly <= 2;
        },
        poppy = function( ) {
            return intestine >= 8;
        },
        passageOfTime = function( ) {
            if (belly > 0) {
                belly -= 1;
                intestine += 1;
            } else {
                if (asleep) {
                    asleep = false;
                    $('#pre0').append(name + "が突然目を覚まします!\n");
                }
                $('#pre0').append(name + "がお腹をすかせています。" +
                    "我慢できなくてあなたを食べました。");
                $('#command').remove();
                $('#commanded').remove();
                return;
            }
            if (intestine >= 10) {
                intestine = 0;
                $('#pre0').append("うわっ、" + name + "がおもらしを・・・・・・\n");
            }
            if (hungry()) {
                if (asleep) {
                    asleep = false
                    $('#pre0').append(name + "が突然目を覚まします!\n");
                }
                $('#pre0').append(name + "のお腹が鳴っています。\n");
            }
            if(poppy()){
                if (asleep) {
                    asleep = false;
                    $('#pre0').append(name + "が突然目を覚まします!\n");
                }
                $('#pre0').append(name + "がうんちのためにしゃがみ込みます。\n");
            }
        };
    this.feed = function(  ) {
        $('#pre0').append(name + "にご飯をあげます。\n");
        belly = 10;
        passageOfTime();
    },
    this.walk = function( ) {
        $('#pre0').append(name + "をトイレに連れていきます。\n");
        intestine = 0;
        passageOfTime();
    },
    this.putToBed = function(  ) {
        $('#pre0').append(name + "を寝かしつけます。\n");
        asleep = true
        for (i = 0, max = 3; i < max; i += 1) {
            if (asleep) {
                passageOfTime();
            }
            if (asleep) {
                $('#pre0').append(name + "がいびきをかいて、部屋が煙だらけです。\n");
            }
        }
        if (asleep) {
            asleep = false;
            $('#pre0').append(name + "はゆっくり目覚めます。\n");
        }
    }
    this.toss = function( ) {
        $('#pre0').append(name + "が高い高いをします。\n");
        $('#pre0').append(name + "が笑ってあなたの眉毛が焦げます。\n");
        passageOfTime();
    }
    this.rock = function(  ) {
        $('#pre0').append(name + "をやさしくあやします。\n");
        asleep = true;
        $('#pre0').append(name + "は少し居眠りをします。\n");
        passageOfTime();
        if (asleep) {
            asleep = false;
            $('#pre0').append("しかし、やめると起きてしまいます。\n");
        }
    }
    $('#pre0').html('');
    $('#pre0').append(name + "が生まれました。\n");
},
    pet,
    named = function( ) {
        var name = $('#dragon_name').val(),
            result = '<label>' +
                '<select id="command">' +
                '<option value="feed">ご飯をあげる</option>' +
                '<option value="walk">散歩に行く</option>' +
                '<option value="put_to_bed">寝かしつける</option>' +
                '<option value="toss">遊ぶ</option>' +
                '<option value="rock">あやす</option>' +
                '</select>' +
                '</label>' +
                '<input id="commanded" type="button" value="実行" >';
        name = name ? name : "匿名";
        pet = new Dragon(name);
        $('#d0').html(result);
        $('#name_label').remove();
        $('#dragon_named').remove();
        $('#commanded').click(commanded);
        $('#command').keydown(commanded_keydown);
    },
    commanded = function(  ) {
        var $select = $('#command'),
            command = $('option:selected', $select).val();
        switch ( command ) {
            case "feed":
                pet.feed();
                break;
            case "walk":
                pet.walk();
                break;
            case "put_to_bed":
                pet.putToBed();
                break;
            case "toss":
                pet.toss();
                break;
            case "rock":
                pet.rock();
        }
    },
    named_keydowned = function(e) {
        e = e ? e : nsEvent;
        if (e.keyCode === 13) {
            named();
        }
    },
    commanded_keydown = function (e) {
        e = e ? e : nsEvent;
        if (e.keyCode === 13) {
            commanded();
        }
    };
$('#dragon_named').click(named);
$('#dragon_name').keydown(named_keydowned);
</script>




pythonの場合。

sample.py

コード(BBEdit)

#!/usr/bin/env python3.3
#-*- coding: utf-8 -*-

import re

class Dragon:
    def __init__(self, name):
        self._name = name
        self._asleep = False
        self._belly = 10
        self._intestine = 0
        print("{0}が生まれました。".format(self._name))
    def feed(self):
        print("{0}にご飯をあげます。".format(self._name))
        self._belly = 10
        self._passage_of_time()
    def walk(self):
        print("{0}をトイレに連れていきます".format(name))
        self._intestine = 0
        self._passage_of_time()
    def put_to_bed(self):
        print("{0}を寝かしつけます。".format(name))
        self._asleep = True
        for x in range(3):
            if self._asleep:
                self._passage_of_time()
            if self._asleep:
                print("{0}がいびきをかいて、部屋が煙だらけです。".format(name))        
        if self._asleep:
            self._asleep = False
            print("{0}はゆっくり目覚めます。".format(name))
    def toss(self):
        print("{0}に高い高いをします。".format(name))
        print("{0}が笑ってあなたの眉毛が焦げます。".format(name))
        self._passage_of_time()
    
    def rock(self):
        print("{0}をやさしくあやします。".format(name))
        self._asleep = True
        print("{0}は少し居眠りをします。".format(name))
        self._passage_of_time()
        if self._asleep:
            self._asleep = False
            print("しかし、やめると起きてしまいます。".format(name))
    def _hungry(self):
        return self._belly <= 2
    def _poppy(self):
        return self._intestine >= 8
    def _passage_of_time(self):
        if self._belly > 0:
            self._belly -= 1
            self._intestine += 1
        else:
            if self._asleep:
                self._asleep = False
                print("{0}が突然目を覚まします!".format(name))
            print("{0}がお腹を空かせています。我慢できなくてあなたを食べました。".format(name))
            import sys
            sys.exit()
        if self._intestine >= 10:
            self._intestine = 0
            print("うわっ、{0}がおもらしを・・・・・・".format(name))
        if self._hungry():
            if self._asleep:
                self._asleep = False
                print("{0}が突然目を覚まします!".format(name))
            
            print("{0}のお腹が鳴っています。".format(name))
        if self._poppy():
            if self._asleep:
                self._asleep = False
                print("{0}が突然目を覚まします!".format(name))
            print("{0}がうんちのためにしゃがみ込みます。".format(name))
name = input("名前を入力: ")
if re.search(r"^\s*$", name):
    name = "匿名"
pet = Dragon(name)
commands = {'f':pet.feed, 'w':pet.walk, 'p':pet.put_to_bed, 't':pet.toss, 'r':pet.rock}
while True:
    command = input("コマンド(f/w/p/t/r)を入力(空白で終了): ")
    if re.search("^\s*$", command):
        break
    if command in commands:
        commands[command]()
    else:
        print("コマンド入力を確認してください。")

入出力結果(Terminal)

$ ./sample.py
名前を入力: ノーバート
ノーバートが生まれました。
コマンド(f/w/p/t/r)を入力(空白で終了): f
ノーバートにご飯をあげます。
コマンド(f/w/p/t/r)を入力(空白で終了): t
ノーバートに高い高いをします。
ノーバートが笑ってあなたの眉毛が焦げます。
コマンド(f/w/p/t/r)を入力(空白で終了): w
ノーバートをトイレに連れていきます
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートがいびきをかいて、部屋が煙だらけです。
ノーバートがいびきをかいて、部屋が煙だらけです。
ノーバートがいびきをかいて、部屋が煙だらけです。
ノーバートはゆっくり目覚めます。
コマンド(f/w/p/t/r)を入力(空白で終了): r
ノーバートをやさしくあやします。
ノーバートは少し居眠りをします。
しかし、やめると起きてしまいます。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートのお腹が鳴っています。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートのお腹が鳴っています。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートのお腹が鳴っています。
ノーバートがうんちのためにしゃがみ込みます。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートがお腹を空かせています。我慢できなくてあなたを食べました。
$

perlの場合。

sample.pl

コード(BBEdit)

#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use 5.016;
binmode STDIN, ":utf8";
binmode STDOUT, ":utf8";

{
    package Dragon;
    sub new {
        my($class, $name) = @_;
        $name = "匿名" unless $name;
        print "${name}が生まれました。\n";
        my $self = {Name => $name, Asleep => 0, Belly => 10, Intestine => 0};
        bless $self, $class;
    }
    sub feed {
        my $self = shift;
        print $self->{Name}, "にご飯をあげます。\n";
        $self->{Belly} = 10;
        $self->passage_of_time;
    }
    sub walk {
        my $self = shift;
        print $self->{Name}, "をトイレに連れていきます。\n";
        $self->{Intestine} = 0;
        $self->passage_of_time;
    }
    sub put_to_bed {
        my $self = shift;
        print $self->{Name}, "を寝かしつけます。\n";
        $self->{Asleep} = 1;
        for ((1..3)) {
            if ($self->{Asleep}) {
                $self->passage_of_time;
            }
            if ($self->{Asleep}) {
                print $self->{Name}, "がいびきをかいて、部屋が煙だらけです。\n";
            }
        }
        if ($self->{Asleep}) {
            $self->{Asleep} = 0;
            print $self->{Name}, "はゆっくり目覚めます。\n";
        }
    }
    sub toss {
        my $self = shift;
        print $self->{Name}, "に高い高いをします。\n";
        print $self->{Name}, "が笑ってあなたの眉毛が焦げます。\n";
        $self->passage_of_time;
    }
    sub rock {
        my $self = shift;
        print $self->{Name}, "をやさしくあやします。\n";
        $self->{Asleep} = 0;
        print $self->{Name}, "は少し居眠りをします。\n";
        $self->passage_of_time;
        if ($self->{Asleep}) {
            $self->{Asleep} = 0;
            print "しかし、やめると起きてしまいます。\n";
        }
    }
    sub hungry {
        my $self = shift;
        $self->{Belly} <= 2;
    }
    sub poopy {
        my $self = shift;
        $self->{Intestine} >= 8;
    }
    sub passage_of_time {
        my $self = shift;
        if ($self->{Belly} > 0) {
            $self->{Belly} -= 1;
            $self->{Intestine} += 1;
        } else {
            if ($self->{Asleep}) {
                $self->{Asleep} = 0;
                print $self->{Name}, "が突然目を覚まします!\n";
            }
            print $self->{Name}, "がお腹をすかせています。我慢できなくてあなたを食べました。\n";
            exit;
        }
        if ($self->{Intestine} >= 10) {
            $self->{Intestine} = 0;
            print "うわっ、", $self->{Name}, "がお漏らしを・・・・・・\n";
        }
        if ($self->hungry) {
            if ($self->{Asleep}) {
                $self->{Asleep} = 0;
                print $self->{Name}, "が突然目を覚まします!\n";
            }
            print $self->{Name}, "のお腹が鳴っています。\n";
        }
        if ($self->poopy) {
            if ($self->{Asleep}) {
                $self->{Asleep} = 0;
                print $self->{Name}, "が突然目を覚まします!\n";
            }
            print $self->{Name}, "がうんちのためにしゃがみ込みます。\n";
        }
    }
}
print "名前を入力: ";
chomp(my $name = <STDIN>);
$name = "匿名" if $name =~ /^\s*$/;
my $pet = Dragon->new($name);
while (1) {
    print "コマンド(f/w/p/t/r)を入力(空白で終了): ";
    chomp(my $command = <STDIN>);
    given( $command ) {
        when (/^\s*$/) { last; }
        when ('f') {$pet->feed;}
        when ('w') {$pet->walk;}
        when ('p') {$pet->put_to_bed;}
        when ('t') {$pet->toss;}
        when ('r') {$pet->rock;}
        default {print "コマンド入力を確認してください\n";}
    }
}

入出力結果(Terminal)

$ ./sample.pl
名前を入力: ノーバート
ノーバートが生まれました。
コマンド(f/w/p/t/r)を入力(空白で終了): f
ノーバートにご飯をあげます。
コマンド(f/w/p/t/r)を入力(空白で終了): t
ノーバートに高い高いをします。
ノーバートが笑ってあなたの眉毛が焦げます。
コマンド(f/w/p/t/r)を入力(空白で終了): w
ノーバートをトイレに連れていきます。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートがいびきをかいて、部屋が煙だらけです。
ノーバートがいびきをかいて、部屋が煙だらけです。
ノーバートがいびきをかいて、部屋が煙だらけです。
ノーバートはゆっくり目覚めます。
コマンド(f/w/p/t/r)を入力(空白で終了): r
ノーバートをやさしくあやします。
ノーバートは少し居眠りをします。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートのお腹が鳴っています。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートのお腹が鳴っています。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートのお腹が鳴っています。
ノーバートがうんちのためにしゃがみ込みます。
コマンド(f/w/p/t/r)を入力(空白で終了): p
ノーバートを寝かしつけます。
ノーバートが突然目を覚まします!
ノーバートがお腹をすかせています。我慢できなくてあなたを食べました
$

とりあえずできたけど、PerlでもRubyみたいに中だけで使えるprivateみたいの作るにはどうすればいいのかが分からないまま。。(Pythonは隠蔽はできない。意図を伝えるために属性名の先頭にアンダースコア「_」を付ける。)

0 コメント:

コメントを投稿