僕の作っている人間頭脳型ロボットを、Qiitaで、@shiracamusと言う方とともに共同開発中です。
以下は、そのログのコピーです。
@schwarz1009 - 2017年04月12日に更新
僕の作ったロボットのコードまとめ。コードだけですみません。
ホームページでも公開しています。
一号機。
robot1.c
#include <stdio.h> #include <stdlib.h> int getlp(int *p){ *p = rand()%2; return 1; } void action(int *p){ if(*p==0){ printf("はらが減った。\n"); } else if(*p==1){ printf("はらは減っていない。\n"); } } int main(void){ int p; while(getlp(&p)){ action(&p); } }
二号機。
robot2.c
#include <stdio.h> #include <stdlib.h> struct _obj { int p; int hara; }; int getlp(struct _obj *obj){ obj->p = rand()%4; return 1; } void action(struct _obj *obj){ if(obj->p==0){ printf("はらは"); if(obj->hara==0){ printf("減った。\n"); } else{ printf("減っていない。\n"); } } else if(obj->p==1){ printf("楽しい。\n"); } else if(obj->p==2){ printf("はらが減る\n"); obj->hara=0; } else if(obj->p==3){ printf("おいしいごはんを食べた\n"); obj->hara=1; } } int main(void){ struct _obj obj; obj.hara=1; while(getlp(&obj)){ action(&obj); } }
三号機。
robot3.c
#include <stdio.h> #include <stdlib.h> struct _obj { int p; int w; int t; }; int getlp(struct _obj *obj){ obj->p = rand()%5; return 1; } void action(struct _obj *obj){ if(obj->p==0){ printf("ここは"); if(obj->w==1){ printf("日本です。\n"); } else if(obj->w==2){ printf("ドイツです。\n"); } } else if(obj->p==1){ printf("日本にやってきました。\n"); obj->w=1; } else if(obj->p==2){ printf("ドイツにやってきました。\n"); obj->w=2; } else if(obj->p==3){ printf("想像力を使います。"); printf("りんごは赤い。\n"); obj->t=1; } else if(obj->p==4){ printf("想像力を使います。"); printf("りんごは白い。\n"); obj->t=0; } if(obj->p==3||obj->p==4){ if(obj->t==1){ printf("正しい。\n"); } else{ printf("間違っている。\n"); } } } int main(void){ struct _obj obj; obj.w=1; obj.t=1; while(getlp(&obj)){ action(&obj); } }
四号機。
robot4.c
#include <stdio.h> #include <stdlib.h> struct _obj { int o; int n; }; void action(int* p, struct _obj *obj){ if(*p==0){ printf("[1] テレビは、つまらない\n"); } else if(*p==1){ printf("[2] テレビは、面白い\n"); } else if(*p==2){ printf("[3] パソコンは、つまらない\n"); } else if(*p==3){ printf("[4] パソコンは、面白い\n"); } else if(*p==4){ printf("[5] テレビやパソコンは、機械だ。\n"); } else if(*p==5){ printf("[6] テレビやパソコンは、生き物ではない。\n"); } else if(*p==6){ printf("[7] テレビって何なのだろう。\n"); } else if(*p==7){ printf("[8] テレビとパソコンは好きだ。\n"); } else if(*p==8){ printf("[9] テレビとパソコンは嫌いだ。\n"); } else if(*p==9){ if(obj->n==0){ printf("[10] 比較すると、テレビの方が普通だ。\n"); } else if(obj->n==1){ printf("[11] 比較すると、パソコンの方が普通だ。\n"); } } else if(*p==10){ if(obj->n==0){ printf("[12] テレビよりパソコンの方が普通かな。\n"); obj->n=1; } else if(obj->n==1){ printf("[13] パソコンよりテレビの方が普通かな。\n"); obj->n=0; } } else if(*p==11){ if(obj->o==0){ printf("[14] リンゴが好きです。\n"); } else if(obj->o==1){ printf("[15] みかんが好きです。\n"); } } else if(*p==12){ if(obj->o==0){ printf("[16] リンゴより、みかんが好きになりました。\n"); obj->o=1; } else if(obj->o==1){ printf("[17] みかんより、リンゴが好きになりました。\n"); obj->o=0; } } } int main(void){ int p; struct _obj obj; p=0; obj.o=0; obj.n=0; while(1){ p=rand()%13; action(&p, &obj); } }
このロボットは、改善点として、普通の人工知能を乗せる、思考を覚えて思い出す、マルチスレッドにして複数にする、などが考えられる。
僕は、何をすべきなのか、自分の力で考えるコンピュータを作るべきだと思う。
robot5.c
#include <stdio.h> struct _obj { int p; }; int check1 (struct _obj *obj) { if (obj->p == 0) { return 1; } return 0; } int check2 (struct _obj *obj) { if (obj->p == 1) { return 1; } return 0; } void action1 (struct _obj *obj) { printf("ここではアクション1をやります。\n"); } void action2 (struct _obj *obj) { printf("ここではアクション2をやります。\n"); } int main (void) { struct _obj obj; obj.p = 0; if (check1(&obj)){ action1(&obj); } if (check2(&obj)){ action2(&obj); } }
いちいちif文を書くのは大変でしょうから、配列にしてはいかがでしょう?
それと、インデントが失われているコードは、vimで gg=G するか indentコマンドで整形するといいですよ。インデント幅を指定して(vimなら :set shiftwidth=2 expandtab とか)。
#include <stdio.h> struct _obj { int p; }; int check1 (struct _obj *obj) { if (obj->p == 0) { return 1; } return 0; } int check2 (struct _obj *obj) { if (obj->p == 1) { return 1; } return 0; } void action1 (struct _obj *obj) { printf("ここではアクション1をやります。\n"); } void action2 (struct _obj *obj) { printf("ここではアクション2をやります。\n"); } struct brain { int (*check)(struct _obj *obj); void (*action)(struct _obj *obj); } brain[] = { { check1, action1 }, { check2, action2 }, { NULL, NULL } }; int main (void) { struct _obj obj = { .p = 0 }; for (struct brain *b = brain; b->check; b++) { if (b->check(&obj)){ b->action(&obj); } } }
shiracamusさん、素晴らしいです。改善ありがとうございます。
コードを良く分かっていないので、トンチンカンなことを言っているかもしれないのですが、無限ループでないと人間の頭脳のような思考ロボットにならないような気がします。ただ、コードが美しくなっているので、本当に嬉しいです。
こうすれば良いのだと思います。
robot7.c
#include <stdio.h> struct _obj { int p; }; int check1 (struct _obj *obj) { if (obj->p == 0) { return 1; } return 0; } int check2 (struct _obj *obj) { if (obj->p == 1) { return 1; } return 0; } void action1 (struct _obj *obj) { printf("ここではアクション1をやります。\n"); } void action2 (struct _obj *obj) { printf("ここではアクション2をやります。\n"); } struct brain { int (*check)(struct _obj *obj); void (*action)(struct _obj *obj); } brain[] = { { check1, action1 }, { check2, action2 }, { NULL, NULL } }; int main (void) { struct _obj obj = { .p = 0 }; while(1){ for (struct brain *b = brain; b->check; b++) { if (b->check(&obj)){ b->action(&obj); } } } }
なんか、ループの中がおかしくバグっている気がします。変数定義をループ外に追い出して、ポインタと配列をなんとかした方が良いかもしれません。
バグを直すと、こんな風になりました。
robot8.c
#include <stdio.h> struct _obj { int p; }; int check1 (struct _obj *obj) { if (obj->p == 0) { return 1; } return 0; } int check2 (struct _obj *obj) { if (obj->p == 1) { return 1; } return 0; } void action1 (struct _obj *obj) { printf("ここではアクション1をやります。\n"); } void action2 (struct _obj *obj) { printf("ここではアクション2をやります。\n"); } void doing (struct _obj *obj) { struct brain { int (*check)(struct _obj *obj); void (*action)(struct _obj *obj); } brain[] = { { check1, action1 }, { check2, action2 }, { NULL, NULL } }; struct brain *b; for (b = brain; b->check; b++) { if (b->check(obj)){ b->action(obj); } } } int main (void) { struct _obj obj = { .p = 0 }; struct _obj obj2 = { .p = 1 }; while(1){ doing(&obj); doing(&obj2); } }
すみません。今度はメモリリークしているような気がします。
メモリリークの直し方が分からないです。すみません。
静的データしかないのでメモリリークはしません。
無限ループして出力が山ほどたまってメモリ消費してるというオチじゃありませんか?
sleep(1); でも入れてゆっくり無限ループしてみてはいかがでしょう?
すみません。メモリリークしていないのかも知れないです。
自分の技術力の無さを反省します。
結局こんな感じになりました。
robot9.c
#include <stdio.h> struct _obj { int p; }; int check1 (struct _obj *obj) { if (obj->p == 0) { return 1; } return 0; } int check2 (struct _obj *obj) { if (obj->p == 1) { return 1; } return 0; } void action1 (struct _obj *obj) { printf("ここではアクション1をやります。\n"); } void action2 (struct _obj *obj) { printf("ここではアクション2をやります。\n"); } struct brain { int (*check)(struct _obj *obj); void (*action)(struct _obj *obj); } brain[] = { { check1, action1 }, { check2, action2 }, { NULL, NULL } }; void doing (struct _obj *obj) { struct brain *b; for (b = brain; b->check; b++) { if (b->check(obj)){ b->action(obj); } } } int main (void) { struct _obj obj = { .p = 0 }; struct _obj obj2 = { .p = 1 }; while(1){ doing(&obj); doing(&obj2); } }
mainをこう変更してみてはいかがですか?
#include <unistd.h> int main (void) { struct _obj obj = { .p = 0 }; struct _obj obj2 = { .p = 1 }; while(1){ doing(&obj); doing(&obj2); sleep(1); } }
sleep(1);の必要性はちょっと分からないです。ただ、ちょっと表示が速すぎるような気はします。
今度のロボットは、永遠に次の思考と主題に反応して、良いか悪いかを表示します。
robot10.c
#include <stdio.h> struct _obj { int tf; int sbj; }; void next_subject (struct _obj *obj){ if (obj->sbj == 0){ obj->tf = 0; } if (obj->sbj == 1){ obj->tf = 1; } } void mind (struct _obj *obj){ if (obj->tf == 0){ printf("それはきっと正しい\n"); } if (obj->tf == 1){ printf("それはきっと間違っている\n"); } } int main(void){ struct _obj obj = { .tf = 0 }; while(1){ obj.sbj=0; next_subject(&obj); mind(&obj); obj.sbj=1; next_subject(&obj); mind(&obj); } }
void next_subject (struct _obj *obj){ if (obj->sbj == 0){ obj->tf = 0; } if (obj->sbj == 1){ obj->tf = 1; } }
これって、こうしてはだめなんでしょうか?
void next_subject (struct _obj *obj){ obj->tf = obj->sbj; }
そもそも、sbj って何? tf って何? 0 って何? 1 って何?
sbjは主題です。tfは真偽値です。理解出来ないかもしれないです。ごめんなさい。
主題と真偽値は今のところ0と1になっていますが、これを追加して、たとえば主題2の時は正しい、3の時は間違っている、などとすることを想定しています。
主題と言うのは、数値になっているのは計算しやすくするためで、「猫は動物である」の時に正しい、「猫は植物である」の時に間違っている、などとすることを想定しています。
説明しないと、分からなかったかもしれないです。
0 とか 1 はマジックナンバーと呼ばれ、プログラムの可読性、保守性が低下します。
enum を使うようにしましょう。
変数名はできる限り省略せず、変数に格納される値の「意味」を表す名前にしましょう。
こんなことをしたいのかな? と考えてみた例を示しておきます。参考になれば幸いです。
#include <stdio.h> #include <unistd.h> typedef const char *String; typedef enum { TRUE = (0 == 0), FALSE = (0 != 0) } Boolean; typedef enum { CORRECT, WRONG, UNKNOWN } Judge; typedef enum { NONE, ROBOT, CAT, DOG, MACHINE, HUMAN, ANIMAL, PLANT, PEACE, WAR } Object; typedef struct { Object object; Object type; } Category; Category categorize[] = { { ROBOT, MACHINE }, { CAT, ANIMAL }, { DOG, ANIMAL }, { NONE, NONE } }; Boolean Object_is(Object object, Object complement) { if (object == complement) return TRUE; for (Category *category = categorize; category->object != NONE; category++) { if (category->object == object && category->type == complement) return TRUE; } return FALSE; } typedef struct { Object object; Judge judge; } Mind; typedef struct { String name; Object type; Mind *mind; } Robot; void Robot_areYou(Robot *robot, Object complement) { if (Object_is(robot->type, complement)) { printf("%s: はい、そうです\n", robot->name); } else { printf("%s: いいえ、違います\n", robot->name); } } void Robot_isThis(Robot *robot, Object object, Object complement) { if (Object_is(object, complement)) { printf("%s: はい、そうです\n", robot->name); } else { printf("%s: いいえ、違います\n", robot->name); } } void Robot_judge(Robot *robot, Object object) { for (Mind *mind = robot->mind; mind->object != NONE; mind++) { if (mind->object != object) continue; switch (mind->judge) { case CORRECT: printf("%s: それはきっと正しい\n", robot->name); return; case WRONG: printf("%s: それはきっと間違っている\n", robot->name); return; default: printf("%s: それは分かりません\n", robot->name); return; } } printf("%s: それは分かりません\n", robot->name); } int main(void) { Mind mind_of_robot[] = { { PEACE, CORRECT }, { WAR, WRONG }, { NONE, UNKNOWN }, }; Robot robot = { .name = "Mr.Robot", .type = ROBOT, .mind = mind_of_robot, }; while(1){ Robot_areYou(&robot, ROBOT); Robot_areYou(&robot, MACHINE); Robot_areYou(&robot, HUMAN); Robot_isThis(&robot, CAT, ANIMAL); Robot_isThis(&robot, CAT, PLANT); Robot_isThis(&robot, CAT, DOG); Robot_judge(&robot, PEACE); Robot_judge(&robot, WAR); sleep(1); } }
実行結果
Mr.Robot: はい、そうです Mr.Robot: はい、そうです Mr.Robot: いいえ、違います Mr.Robot: はい、そうです Mr.Robot: いいえ、違います Mr.Robot: いいえ、違います Mr.Robot: それはきっと正しい Mr.Robot: それはきっと間違っている
ありがとうございます。すごいです。感謝します!
shiracamusさん。本当に嬉しいです。こちらのページに、コードの引用を載せさせていただきました。
良かったら、また教えてください。感謝します。
列挙型から文字列の配列を作る を使って改良してみました。
#include <stdio.h> #include <unistd.h> typedef const char *String; typedef enum { YES = (0 == 0), NO = (0 != 0) } Boolean; typedef enum { CORRECT, WRONG, UNKNOWN } Judge; #define WORD(T) \ T(ROBOT), T(CAT), T(DOG), \ T(MACHINE), T(HUMAN), T(ANIMAL), T(PLANT), \ T(PEACE), T(WAR), \ T(NONE) #define toEnum(name) name #define toString(name) #name typedef enum { WORD(toEnum) } Word; String name[] = { WORD(toString) }; typedef struct { Word word; Word group; } Category; Category categories[] = { { ROBOT, MACHINE }, { CAT, ANIMAL }, { DOG, ANIMAL }, { NONE, NONE } // terminator (Don't remove) }; Boolean is(Word subject, Word complement) { // S+V+C if (subject == complement) return YES; for (Category *category = categories; category->word != NONE; category++) { if (subject == category->word && complement == category->group) return YES; } return NO; } typedef struct { Word object; Judge judge; } Mind; typedef struct { String name; Word type; Mind *mind; } Robot; void Robot_areYou(Robot *robot, Word complement) { if (is(robot->type, complement)) { printf("%s: はい、私は %s です\n", robot->name, name[complement]); } else { printf("%s: いいえ、私は %s ではありません\n", robot->name, name[complement]); } } void Robot_isThis(Robot *robot, Word object, Word complement) { if (is(object, complement)) { printf("%s: はい、%s は %s です\n", robot->name, name[object], name[complement]); } else { printf("%s: いいえ、%s は %s ではありません\n", robot->name, name[object], name[complement]); } } void Robot_judge(Robot *robot, Word object) { for (Mind *mind = robot->mind; mind->object != NONE; mind++) { if (mind->object != object) continue; switch (mind->judge) { case CORRECT: printf("%s: %s はきっと正しい\n", robot->name, name[object]); return; case WRONG: printf("%s: %s はきっと間違っている\n", robot->name, name[object]); return; default: printf("%s: %s は分かりません\n", robot->name, name[object]); return; } } printf("%s: %s は分かりません\n", robot->name, name[object]); } int main(void) { Mind mind_of_robot[] = { { PEACE, CORRECT }, { WAR, WRONG }, { NONE, UNKNOWN }, // terminator (Don't remove) }; Robot robot = { .name = "Mr.Robot", .type = ROBOT, .mind = mind_of_robot, }; for (;;) { Robot_areYou(&robot, ROBOT); Robot_areYou(&robot, MACHINE); Robot_areYou(&robot, HUMAN); Robot_isThis(&robot, CAT, ANIMAL); Robot_isThis(&robot, CAT, PLANT); Robot_isThis(&robot, CAT, DOG); Robot_judge(&robot, PEACE); Robot_judge(&robot, WAR); sleep(1); } }
実行結果
Mr.Robot: はい、私は ROBOT です Mr.Robot: はい、私は MACHINE です Mr.Robot: いいえ、私は HUMAN ではありません Mr.Robot: はい、CAT は ANIMAL です Mr.Robot: いいえ、CAT は PLANT ではありません Mr.Robot: いいえ、CAT は DOG ではありません Mr.Robot: PEACE はきっと正しい Mr.Robot: WAR はきっと間違っている
言葉を覚えるたびにプログラムをコンパイルするのは馬鹿げているので、いずれ言葉辞書やカテゴリー辞書を外部から読み込むことになると思います。
文章の構造を分析して単語抽出や品詞分類するライブラリもありますから、そういったライブラリを使って入力された文章を解釈して答えるロボットにするのもいいと思います。
自分としては、作り方や解決方法を考えたり、批判や同意をするようにすると、人間らしくなるのかな、と言う気がします。
あるいは、感情表現や要求、願望などがあると良いと思います。
ただし、ただ考えているように見えて、本当は表示しているだけ、となってしまうと、ロボットとは言えないかもしれません。
指示した動作を疲れ知らずで正確に繰り返す産業ロボットもロボットですよね。
人間らしくするとなると、AI(人工知能)や機械学習を取り入れると良さそうですね。
Pythonのライブラリが充実してるので、C言語よりもPythonを学んだ方が楽できると思います。
ロボットをPythonで書いてみました。
robot.py
import random class Robot: def __init__(self): self.p = 0 self.n = 0 self.o = 0 def action(self): if self.p == 0: print("[1] テレビは、つまらない\n") if self.p == 1: print("[2] テレビは、面白い\n") if self.p == 2: print("[3] パソコンは、つまらない\n") if self.p == 3: print("[4] パソコンは、面白い\n") if self.p == 4: print("[5] テレビやパソコンは、機械だ。\n") if self.p == 5: print("[6] テレビやパソコンは、生き物ではない。\n") if self.p == 6: print("[7] テレビって何なのだろう。\n") if self.p == 7: print("[8] テレビとパソコンは好きだ。\n") if self.p == 8: print("[9] テレビとパソコンは嫌いだ。\n") if self.p == 9: if self.n == 0: print("[10] 比較すると、テレビの方が普通だ。\n") if self.n == 1: print("[11] 比較すると、パソコンの方が普通だ。\n") if self.p == 10: if self.n == 0: print("[12] テレビよりパソコンの方が普通かな。\n") self.n = 1 elif self.n == 1: print("[13] パソコンよりテレビの方が普通かな。\n") self.n = 0 if self.p == 11: if self.o == 0: print("[14] リンゴが好きです。\n") if self.o == 1: print("[15] みかんが好きです。\n") if self.p == 12: if self.o == 0: print("[16] リンゴより、みかんが好きになりました。\n") self.o = 1 elif self.o == 1: print("[17] みかんより、リンゴが好きになりました。\n") self.o = 0 if __name__ == "__main__": rb = Robot() while True: rb.p=random.randint(0,12) rb.action()
これを何をもってロボットと呼んでいるのか理解できませんが、とりあえずelif使いましょう。
すみません。人間のように考えるロボットのつもりです。
以下のようにしてみました。
robot2.py
import random class Robot: def __init__(self): self.p = 0 self.n = 0 self.o = 0 def action(self): if self.p == 0: print("[1] テレビは、つまらない\n") if self.p == 1: print("[2] テレビは、面白い\n") if self.p == 2: print("[3] パソコンは、つまらない\n") if self.p == 3: print("[4] パソコンは、面白い\n") if self.p == 4: print("[5] テレビやパソコンは、機械だ。\n") if self.p == 5: print("[6] テレビやパソコンは、生き物ではない。\n") if self.p == 6: print("[7] テレビって何なのだろう。\n") if self.p == 7: print("[8] テレビとパソコンは好きだ。\n") if self.p == 8: print("[9] テレビとパソコンは嫌いだ。\n") if self.p == 9: if self.n == 0: print("[10] 比較すると、テレビの方が普通だ。\n") if self.n == 1: print("[11] 比較すると、パソコンの方が普通だ。\n") if self.p == 10: if self.n == 0: print("[12] テレビよりパソコンの方が普通かな。\n") self.n = 1 elif self.n == 1: print("[13] パソコンよりテレビの方が普通かな。\n") self.n = 0 if self.p == 11: if self.o == 0: print("[14] リンゴが好きです。\n") if self.o == 1: print("[15] みかんが好きです。\n") if self.p == 12: if self.o == 0: print("[16] リンゴより、みかんが好きになりました。\n") self.o = 1 elif self.o == 1: print("[17] みかんより、リンゴが好きになりました。\n") self.o = 0 def mainloop(): while True: self.p=random.randint(0,12) self.action() if __name__ == "__main__": rb = Robot() rb.mainloop()
いや、こういうことです。
元のコードだと毎回12回の比較が生じるので、実行時間が大いに無駄になります。
robot2.py
import random class Robot: def __init__(self): self.p = 0 self.n = 0 self.o = 0 def action(self): if self.p == 0: print("[1] テレビは、つまらない\n") elif self.p == 1: print("[2] テレビは、面白い\n") elif self.p == 2: print("[3] パソコンは、つまらない\n") elif self.p == 3: print("[4] パソコンは、面白い\n") elif self.p == 4: print("[5] テレビやパソコンは、機械だ。\n") elif self.p == 5: print("[6] テレビやパソコンは、生き物ではない。\n") elif self.p == 6: print("[7] テレビって何なのだろう。\n") elif self.p == 7: print("[8] テレビとパソコンは好きだ。\n") elif self.p == 8: print("[9] テレビとパソコンは嫌いだ。\n") elif self.p == 9: if self.n == 0: print("[10] 比較すると、テレビの方が普通だ。\n") else: print("[11] 比較すると、パソコンの方が普通だ。\n") elif self.p == 10: if self.n == 0: print("[12] テレビよりパソコンの方が普通かな。\n") self.n = 1 else: print("[13] パソコンよりテレビの方が普通かな。\n") self.n = 0 elif self.p == 11: if self.o == 0: print("[14] リンゴが好きです。\n") else: print("[15] みかんが好きです。\n") elif self.p == 12: if self.o == 0: print("[16] リンゴより、みかんが好きになりました。\n") self.o = 1 else: print("[17] みかんより、リンゴが好きになりました。\n") self.o = 0 def mainloop(): while True: self.p=random.randint(0,12) self.action() if __name__ == "__main__": rb = Robot() rb.mainloop()
『ランダムに意思を表明する』ことをロボットの要件とするならば、
サイコロの各面にメッセージを張ればそれでロボットと呼べることになります。
そして、そもそもこのコードは動かないです。self.oとself.nを定義する前に参照していますから。
動かないのを承知で、こんな風にしたらどうですか?
robot3.py
class Robot: def __init__(self): self.p = 0 self.n = 0 self.o = 0 def action(self): if self.p == 0: print("[1] テレビは、つまらない\n") elif self.p == 1: print("[2] テレビは、面白い\n") elif self.p == 2: print("[3] パソコンは、つまらない\n") elif self.p == 3: print("[4] パソコンは、面白い\n") elif self.p == 4: print("[5] テレビやパソコンは、機械だ。\n") elif self.p == 5: print("[6] テレビやパソコンは、生き物ではない。\n") elif self.p == 6: print("[7] テレビって何なのだろう。\n") elif self.p == 7: print("[8] テレビとパソコンは好きだ。\n") elif self.p == 8: print("[9] テレビとパソコンは嫌いだ。\n") elif self.p == 9: if self.n == 0: print("[10] 比較すると、テレビの方が普通だ。\n") else: print("[11] 比較すると、パソコンの方が普通だ。\n") elif self.p == 10: if self.n == 0: print("[12] テレビよりパソコンの方が普通かな。\n") self.n = 1 else: print("[13] パソコンよりテレビの方が普通かな。\n") self.n = 0 elif self.p == 11: if self.o == 0: print("[14] リンゴが好きです。\n") else: print("[15] みかんが好きです。\n") elif self.p == 12: if self.o == 0: print("[16] リンゴより、みかんが好きになりました。\n") self.o = 1 else: print("[17] みかんより、リンゴが好きになりました。\n") self.o = 0 def mainloop(): while True: self.p=kanjou() self.action() def kanjou(): .... return nanika if __name__ == "__main__": rb = Robot() rb.mainloop()
感情を一次元、しかも離散的に扱う時点でおかしいのでは。
「なんかうまい具合にする」って意味では、以下のコードとあんまりレベル変わらないですよ。
print(nanika)
すごい!笑える。
まあ確かに、ここでkanjou()はおかしいかもしれないですね。
感情をわざわざ数値に変換して、それを別のところで思考にするのはおかしいと思います。
そもそも、このようなコードから思いついたので、仕方ありません。
main { while(getlp(p)) { if(1==getkj(p)){ action(); } } }
最初のコードもかなり冗長ですけどね。以下で充分です。
ポインタを使う必要は全くないです。
#include <stdio.h> #include <stdlib.h> int getlp(void){ return rand()%2; } void action(int p){ if(p==0) { printf("はらが減った。"); } else { printf("はらは減っていない。"); } } int main(void){ while(1){ action(getlp()); } return 0; }
むしろ、勝手に改良してもらって全然構わないので、よろしくお願いします。
if文を使わない書き方はいかが?
import random class Robot: def __init__(self): self.mind = { False: { False: '質問がわかりません', }, 'って何': { True: '{what}は{mind}です', False: '知りません', 'テレビ': '機械', 'パソコン': '機械', }, 'はどう': { True: '{what}は{mind}です', False: '{what}はどうでもいい', 'テレビ': 'どうでもいい', 'パソコン': '面白い', }, 'どっちが普通': { True: '{mind}の方が普通です', False: 'わからない', 'テレビとパソコン': 'テレビ', }, 'どっちが好き': { True: '{mind}の方が好きです', False: '決められない', 'テレビとパソコン': 'パソコン', }, 'は何が好き': { True: '{mind}が好き', False: '特にない', '食べ物': 'りんご', }, } def ask(self, question): words = question.strip().rstrip("??").split() what, how = words[0], ''.join(words[1:]) mind = self.mind.get(how, False) or self.mind[False] return mind[what in mind].format(what=what, mind=mind.get(what, '')) if __name__ == "__main__": robot = Robot() print('ロボットに質問しましょう。') while True: question = input('質問: ') print(robot.ask(question))
実行結果
ロボットに質問しましょう。 質問: パソコン 質問がわかりません 質問: パソコン って何? パソコンは機械です 質問: テレビとパソコン どっちが好き? パソコンの方が好きです 質問: テレビとパソコン どっちが普通 テレビの方が普通です 質問: 食べ物 は何が好き? りんごが好き
動くようにしたバージョンを作りました。手元の環境(Fedora 26)では動いています。
robot4.py
#!/usr/bin/python # -*- coding: utf-8 -*- import random class Robot: def __init__(self): self.p = 0 self.n = 0 self.o = 0 def action(self): if self.p == 0: print("[1] テレビは、つまらない") elif self.p == 1: print("[2] テレビは、面白い") elif self.p == 2: print("[3] パソコンは、つまらない") elif self.p == 3: print("[4] パソコンは、面白い") elif self.p == 4: print("[5] テレビやパソコンは、機械だ。") elif self.p == 5: print("[6] テレビやパソコンは、生き物ではない。") elif self.p == 6: print("[7] テレビって何なのだろう。") elif self.p == 7: print("[8] テレビとパソコンは好きだ。") elif self.p == 8: print("[9] テレビとパソコンは嫌いだ。") elif self.p == 9: if self.n == 0: print("[10] 比較すると、テレビの方が普通だ。") else: print("[11] 比較すると、パソコンの方が普通だ。") elif self.p == 10: if self.n == 0: print("[12] テレビよりパソコンの方が普通かな。") self.n = 1 else: print("[13] パソコンよりテレビの方が普通かな。") self.n = 0 elif self.p == 11: if self.o == 0: print("[14] リンゴが好きです。") else: print("[15] みかんが好きです。") elif self.p == 12: if self.o == 0: print("[16] リンゴより、みかんが好きになりました。") self.o = 1 else: print("[17] みかんより、リンゴが好きになりました。") self.o = 0 def mainloop(self): while True: self.p=self.kanjou() self.action() def kanjou(self): return random.randint(0,12) if __name__ == "__main__": rb = Robot() rb.mainloop()
単純なランダムではロボットらしくないので、こんな感じにしてみました。
robot5.py
#!/usr/bin/python # -*- coding: utf-8 -*- import random class Robot: def __init__(self): self.nanisuru = 0 self.tabetai = 0 self.yaritai = 0 self.suki = 0 self.change_tabetai = 0 self.change_yaritai = 0 self.change_suki = 0 self.ima_tabetai = 0 self.ima_yaritai = 0 self.ima_suki = 0 def action(self): if self.nanisuru == 0: if self.ima_tabetai == 1: if self.tabetai == 0: print("カツ丼が食べたい") elif self.tabetai == 1: print("ステーキが食べたい") if self.change_tabetai == 1: if self.tabetai == 0: print("やっぱりステーキが良い") self.tabetai = 1 elif self.tabetai == 1: print("やっぱりカツ丼が良い") self.tabetai = 0 elif self.nanisuru == 1: if self.ima_yaritai == 1: if self.yaritai == 0: print("サッカーがしたい") elif self.yaritai == 1: print("野球がしたい") if self.change_yaritai == 1: if self.yaritai == 0: print("やっぱり野球が良い") self.yaritai = 1 elif self.yaritai == 1: print("やっぱりサッカーが良い") self.yaritai = 0 elif self.nanisuru == 2: if self.ima_suki == 1: if self.suki == 0: print("Windowsが好き") elif self.suki == 1: print("Linuxが好き") if self.change_suki == 1: if self.suki == 0: print("やっぱりLinuxが良い") self.suki = 1 elif self.suki == 1: print("やっぱりWindowsが良い") self.suki = 0 def kanjou(self): if self.nanisuru < 3: self.nanisuru = self.nanisuru + 1 else: self.nanisuru = 0 self.ima_tabetai = random.randint(0,1) self.ima_yaritai = random.randint(0,1) self.ima_suki = random.randint(0,1) self.change_tabetai = random.randint(0,1) self.change_yaritai = random.randint(0,1) self.change_suki = random.randint(0,1) def mainloop(self): while True: self.kanjou() self.action() if __name__ == "__main__": rb = Robot() rb.mainloop()
if文で処理するのは大変なので、リストや辞書にして楽してはいかがですか?
#!/usr/bin/python # -*- coding: utf-8 -*- import random class Robot: selection = ( ("食べたい", ("かつ丼", "ステーキ", "カレー", "ハンバーガー")), ("したい", ("野球", "サッカー")), ("好き", ("Windows", "Linux", "MacOS")), ) mind = 0 def action(self): want, selection = self.selection[self.mind] select = random.choice(selection) print("%sが%s" % (select, want)) change = random.choice(selection) if select != change: print("やっぱり%sが良い" % change) def select(self): self.mind = (self.mind + 1) % len(self.selection) def mainloop(self): while True: self.select() self.action() if __name__ == "__main__": rb = Robot() rb.mainloop()
最近こんな感じになりました。
robot_ng.py
#!/usr/bin/python # -*- coding: utf-8 -*- class Robot: def __init__(self): self.x = 0 # ここで状態記憶 def action(self): # ここで反応 if self.x == 0: print("考える") elif self.x == 1: print("寝る") def kanjou(self): # ここでイベントループ self.x = self.getEvent() def getEvent(self): # ここでパターン認識(viewは見た景色の情報を返す。eは数値で、0は光、1は暗闇) e = view() return e def mainloop(self): while True: self.kanjou() self.action() if __name__ == "__main__": rb = Robot() rb.mainloop()
実際のところ、上のコードは以下と等価です。
robot_ng_r.py
#!/usr/bin/python # -*- coding: utf-8 -*- while True: e = view() if e == 0: print("考える") elif e == 1: print("寝る")
しかしながら、ランダムに繰り返すよりは進歩したでしょう。
以降のログはQiitaをご覧ください。(コピーするのが面倒なため)