
宇宙飛行士が撮影した光る惑星
JavaScriptで動くライフゲームです。
初めにソースを紹介します。
配布元:http://misohena.jp/art/js_lifegame/
以下、lifegame.htmlです。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="ja">
<head>
<link rel="stylesheet" type="text/css" href="lifegame.css">
<script type="text/javascript" src="lifegame.js">
</head>
<body>
<script type="text/javascript">
game = LifeGameApp.appendLifeGameWithRecreatorAfterLastScriptNode(30, 30);
//game = LifeGameApp.appendLifeGameAfterLastScriptNode(30, 30); //再作成ボタン無しの場合
// 初期配置(必要なら)
game.model.put(10, 10,
["** ",
" **",
" * "
]);
// 開始(最初からスタートさせるなら)
game.control.start();
</script>
...
</body>
</html>
< タグは、ブログでの表示の関係上<(全角)に替えてあります。
以下、lifegame.jsです。同じフォルダ内に置きます。
var LifeGameApp = {
getLastScriptNode: function()
{
var n = document;
while(n && n.nodeName.toLowerCase() != "script") { n = n.lastChild;}
return n;
},
appendLifeGameAfterLastScriptNode: function(width, height)
{
var game = new LifeGameApp.Game(width, height);
var parent = LifeGameApp.getLastScriptNode().parentNode;
parent.appendChild(game.element);
return game;
},
appendLifeGameWithRecreatorAfterLastScriptNode: function(width, height)
{
var gameWithRecreator = new LifeGameApp.GameWithRecreator(width, height);
var parent = LifeGameApp.getLastScriptNode().parentNode;
parent.appendChild(gameWithRecreator.element);
return gameWithRecreator.game;
},
};
LifeGameApp.GameWithRecreator = function(width, height)
{
width = width || 20;
height = height || 20;
var div = document.createElement("div");
var form = document.createElement("form");
div.appendChild(form);
var inputWidth = document.createElement("input");
inputWidth.setAttribute("type", "text");
inputWidth.setAttribute("value", width);
inputWidth.setAttribute("size", "4");
form.appendChild(document.createTextNode("width:"));
form.appendChild(inputWidth);
var inputHeight = document.createElement("input");
inputHeight.setAttribute("type", "text");
inputHeight.setAttribute("value", height);
inputHeight.setAttribute("size", "4");
form.appendChild(document.createTextNode("height:"));
form.appendChild(inputHeight);
var buttonRecreate = document.createElement("input");
buttonRecreate.setAttribute("type", "button");
buttonRecreate.setAttribute("value", "Recreate");
form.appendChild(buttonRecreate);
var game = new LifeGameApp.Game(width, height);
div.appendChild(game.element);
var funcRecreate = function(){
var w = parseInt(inputWidth.value);
var h = parseInt(inputHeight.value);
if(w && h && w >= 0 && h >= 0){
div.removeChild(game.element);
game = new LifeGameApp.Game(w, h);
div.appendChild(game.element);
}
};
if(buttonRecreate.addEventListener){
buttonRecreate.addEventListener("click", funcRecreate, false);
}
else if(buttonRecreate.attachEvent){
buttonRecreate.attachEvent("onclick", funcRecreate);
}
this.game = game;
this.element = div;
}
LifeGameApp.Game = function(width, height)
{
width = width || 20;
height = height || 20;
var model = new LifeGameApp.Model(width, height);
// create simple div includes View, Control.
var div = document.createElement("div");
var view = new LifeGameApp.View(width, height);
model.funcUpdate = function(){ view.update(model.cells);}
view.addClickListener(function(x, y){ model.reverseCell(x, y);});
var control = new LifeGameApp.Control(model);
div.appendChild(view.element);
div.appendChild(control.element);
this.element = div;
this.model = model;
this.view = view;
this.control = control;
};
LifeGameApp.View = function(width, height)
{
var tbl = document.createElement("table");
tbl.className = "lifegame-table";
tbl.setAttribute("border", "1");
for(var y = 0; y < height; ++y){
var tr = document.createElement("tr");
for(var x = 0; x < width; ++x){
var td = document.createElement("td");
td.className = "lifegame-cell-dead";
tr.appendChild(td);
}
tbl.appendChild(tr);
}
this.width = width;
this.height = height;
this.tbl = tbl;
this.element = tbl;
};
LifeGameApp.View.prototype = {
update: function(cells)
{
for(var y = 0; y < this.height; ++y){
for(var x = 0; x < this.width; ++x){
var td = this.tbl.childNodes[y].childNodes[x];
td.className = (cells[x+y*this.width]) ? "lifegame-cell-live" : "lifegame-cell-dead";
}
}
},
addClickListenerToCell: function(x, y, onclick)
{
var td = this.tbl.childNodes[y].childNodes[x];
if(td.addEventListener){
td.addEventListener("click", function(){onclick(x, y);}, false);
}
else if(td.attachEvent){
td.attachEvent("onclick", function(){onclick(x, y);});
}
},
addClickListener: function(onclick)
{
for(var y = 0; y < this.height; ++y){
for(var x = 0; x < this.width; ++x){
this.addClickListenerToCell(x, y, onclick);
}
}
}
};
LifeGameApp.Model = function(width, height)
{
this.width = width;
this.height = height;
this.cells = new Array(width*height);
this.cellsTmp = new Array(width*height);
this.generation = 0;
this.funcUpdate = null;
this.clear();
};
LifeGameApp.Model.prototype = {
step: function()
{
var i = 0;
for(var y = 0; y < this.height; ++y){
var up = (y == 0)
? this.width*(this.height-1) : -this.width;
var down
= (y == this.height-1)
? -this.width*(this.height-1) : this.width;
for(var x = 0; x < this.width; ++x, ++i){
var left = (x == 0) ? ( this.width-1) : -1;
var right = (x == this.width-1) ? (-this.width+1) : 1;
var numLiveCells
= this.cells[i+left+up] + this.cells[i+up] + this.cells[i+right+up]
+ this.cells[i+left] + this.cells[i+right]
+ this.cells[i+left+down] + this.cells[i+down] + this.cells[i+right+down];
this.cellsTmp[i] = (this.cells[i] && numLiveCells >= 2 && numLiveCells <= 3)
|| (!this.cells[i] && numLiveCells == 3);
}
}
var old = this.cells;
this.cells = this.cellsTmp;
this.cellsTmp = old;
++this.generation;
this.notifyChanged();
},
clear: function()
{
for(var i = 0; i < this.cells.length; ++i){
this.cells[i] = false;
}
this.generation = 0;
this.notifyChanged();
},
reverseCell: function(x, y)
{
if(x >= 0 && x < this.width && y >= 0 && y < this.height){
var i = x+y*this.width;
this.cells[i] = !this.cells[i];
this.notifyChanged();
}
},
put: function(left, top, arr)
{
for(var y = 0; y < arr.length; ++y){
var row = arr[y];
for(var x = 0; x < row.length; ++x){
this.cells[(left+x)+(top+y)*this.width] = (row.charAt(x) == "*");
}
}
this.notifyChanged();
},
notifyChanged: function()
{
if(this.funcUpdate){
this.funcUpdate();
}
}
};
LifeGameApp.Control = function(model)
{
var self = this;
var form = document.createElement("form");
var buttonPlay = this.createButton("Start", function(){self.onClickPlay()});
form.appendChild(buttonPlay);
var buttonClear = this.createButton("Clear", function(){self.onClickClear()});
form.appendChild(buttonClear);
this.element = form;
this.buttonPlay = buttonPlay;
this.timer = null;
this.model = model;
};
LifeGameApp.Control.prototype = {
createButton: function(value, onclick)
{
var button = document.createElement("input");
button.setAttribute("type", "button");
button.setAttribute("value", value);
if(button.addEventListener){
button.addEventListener("click", onclick, false);
}
else if(button.attachEvent){
button.attachEvent("onclick", onclick);
}
return button;
},
onClickPlay: function()
{
if(this.timer){
this.stop();
}
else{
this.start();
}
},
start: function()
{
if(!this.timer){
var self = this;
this.timer = setInterval(function(){self.onTime();}, 200);
this.buttonPlay.setAttribute("value", "Stop");
}
},
stop: function()
{
if(this.timer){
clearInterval(this.timer);
this.timer = null;
this.buttonPlay.setAttribute("value", "Start");
}
},
onTime: function()
{
this.model.step();
},
onClickClear: function()
{
this.stop();
this.model.clear();
},
};
以下、lifegame.cssです。同じフォルダ内に置きます。
table.lifegame-table {
border-collapse: collapse;
border: 1px solid black;
}
table.lifegame-table > tr > td {
border: 1px solid #808080;
width: 10px;
height: 10px;
padding: 0;
margin: 0;
}
td.lifegame-cell-live {
background-color: #000000;
}
td.lifegame-cell-dead {
background-color: #ffffff;
}
・・・・・・・・・・・・・・・
・・・・・・・・・・・・・・・
ライフゲームのソースの解析は次回以降行うとして、とりあえず、このソースはコピペでそのまま動きます。
・・・・・・・・
今後も恐らく人工無脳的なものを作っていくことになります。
現在契約している講師にPHPを教えてもらったら、PHPでやっていっても良いかもしれません。
人工無脳とは、知能・知性を非常に表面的に表しているものに過ぎないので、その内部状態を作っていきたいと思っています。
つまり、人間でいうところの欲求や意識、内言、感情といったものでしょうか。
もちろん、そういったものを本当に作りだすことは非常に難しいことですので、あくまでもエミュレーションをするということに過ぎません。
以前も人工無脳に機嫌値を付けたことがあります。
「バカ、死ね」などと特定のキーワードに反応して、嫌なことを言われると機嫌値が下がります。
逆に、「かわいい、かしこい」などと言われると機嫌値が上がります。
機嫌値の数値によって、発言するないようが変わったり、無視をしたりします。
本当に感情というものを実現したわけではないのです。
・・・・・・・・・
人工無脳の後ろでライフゲームを動かして何になるのかは分かりません。
恐らく何の意味も無いでしょう。
・・・・・・・・・
・・・・・・・・・
・・・・・・・・・
2045年までに「意識」を持ったコンピュータが現れる。
今、はっと、思ったのですが。
意識を持ったコンピュータは可能なのでしょうか。
なんか、途方も無く、難しいことのように、今あらためて思いました。
自己を持ち、
世界を認識し、
欲求を持ち、
自ら考え、
自己と他者を区別し、
自ら判断し、
そして行動する。
そんなことがコンピュータに可能なのでしょうか。
2029年になっても、人工知能は現れず、科学者は焦り、「こんなはずじゃなかった」と言い出し。
そして、2040年ごろに、「どうも無理なんじゃないか」と誰かが言い。
そして、2045年を迎える。
もしかしたら、意識の実現なんて、人類が存続している間には無理なのかもしれない。
なんか、そんな空想が頭をよぎりました。
・・・・・・・・
・・・・・・・・
GOOGLEは、このブログにいったい何をしたのでしょう。
全然、客が来なくなってしまった。
昨日も20人台。
また地道に記事を書いていくしかない。
というか、しっかりと面白い記事を書くことによって客を惹きつけるしか正しい方法は無い。
・・・・・・・・
・・・・・・・・
劇団に参加したいという思いがあったのだが、
現在の仕事と並行するには、荷が重すぎる。
ということで、朗読会に参加することはできないか。
そう考えた。
朗読だったら、今の仕事と関係あることにもなるし、研修の意味も兼ねられる。
重荷にもならない。
近くで朗読サークルを探そうと思う。
・・・・・・・・
・・・・・・・・
日
朗読会
英
Public reading
韓
낭독회
ナンドクフィ
中
朗读会
lang3 du2 hui4