前些天抽空看了点人工生命相关的书(http://book.douban.com/subject/1255928/),模仿着尝试一些著名的图案(http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life)。重看这段代码,才发现原来写的有错误,惭愧啊[s:18],希望没有误导大家。遂改进如下:
<br />
run_life <- function(file, generation = 1000, fg = "black", bg = "white", speed = 100, wrap = TRUE) {</p>
<p> load_life <- function(file) {<br />
s <- readLines(file)<br />
n <- as.integer(strsplit(s[1], " ")[[1]])<br />
w <- n[1]; h <- n[2]; x <- n[3]; y <- n[4]<br />
s <- strsplit(s[-1], "")<br />
m <- matrix(0, w, h)<br />
for (i in seq_along(s)) {<br />
for (j in seq_along(s[[i]])) {<br />
yy <- y + i - 1<br />
xx <- x + j - 1<br />
if (yy > 0 && yy < h && xx > 1 && xx < w) {<br />
m[xx, yy] <- (s[[i]][j] != ' ')<br />
}<br />
}<br />
}<br />
return (m)<br />
}</p>
<p> next_generation <- function(m) {<br />
if (wrap) {<br />
m <- m[c(ncol(m), 1:ncol(m), 1), c(nrow(m), 1:nrow(m), 1)]<br />
} else {<br />
m <- cbind(0, rbind(0, m, 0), 0)<br />
}<br />
x0 <- c(-2, -1)<br />
x1 <- c(-1, -ncol(m))<br />
x2 <- c(-(ncol(m) - 1), -ncol(m))<br />
y0 <- c(-2, -1)<br />
y1 <- c(-1, -nrow(m))<br />
y2 <- c(-(nrow(m) - 1), -nrow(m))<br />
f <- function(a, b) { b == 3 | (b == 2 & a == 1) }<br />
m <- f(m[y1, x1],<br />
m[y0, x0] + m[y0, x1] + m[y0, x2] +<br />
m[y1, x0] + m[y1, x2] +<br />
m[y2, x0] + m[y2, x1] + m[y2, x2])<br />
return(m)<br />
}</p>
<p> draw_life <- function(m, add) {<br />
image(m, col = c(bg, fg), axes = FALSE, add = add)<br />
}</p>
<p> m <- load_life(file)<br />
for (i in 1:generation) {<br />
draw_life(m, i != 1)<br />
m <- next_generation(m)<br />
Sys.sleep(1 / speed)<br />
}<br />
}<br />
</p>
附上几个数据文件(数据文件第一行分别是:宽、高,图案X坐标,图案Y坐标):
slider.txt
[data]
100 100 50 50
111
1
1
[/data]
slider_gun.txt
[data]
100 100 5 5
*
* *
** ** **
* * ** **
** * * **
** * * ** * *
* * *
* *
**
[/data]
train.txt
[data]
200 200 50 50
* *
*
* *
****
*
**
*
*
*
* *
*
* *
****
[/data]
这样设置初始图案就比较容易了(相比simecol包而言,就是比较简单),修改数据文件后,执行下面命令即可:
<br />
run_life("数据文件名")<br />
</p>