hallo,
eine Frage zum Verständnis:
Ich habe bisher Conway's "Game of Life" nur als eine hübsche und interessante Spielerei betrachtet, wie bestimmte Muster sich schrittweise in neue Muster verwandeln und sich dadurch teilweise scheinbar bewegen oder auch zusätzliche weitere Muster erzeugen - allerdings ist "Game of Life" offenbar sogar Turing-vollständig:
Game of Life als Rechnermodell: Es ist möglich, mithilfe komplexer Startmuster eine Universelle Turing Maschine und deren Eingabe zu modellieren. Conway’s Game of Life ist damit Turing-vollständig. Theoretisch lässt sich jedes algorithmische Problem, das man mit einem Computer lösen kann, auch allein durch Game of Life berechnen
https://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens
Es wurden auch offenbar sogar schon Turing-Maschinen damit gebaut:
http://rendell-attic.org/gol/tm.htm
Hat jemand verstanden, wie solche Conway's "Game of Life" als Turing-Maschinen im Prinzip und im Detail funktionieren?
Lässt sich z.B. eine stark vereinfachte Version programmieren, die z.B. für sehr einfache Aufgaben mit variablen Inputs auf einem Arduino (z.B. ARM Cortex) verwendet werden kann? (AVRs sind ntl zu klein)
Eine kleine GoL-Version für 128x64 Felder habe ich jetzt mal portiert (ESP8266), das soll jetzt für M3/M4 mit ILI9341 etc. hochskaliert werden:
Code:
// Arduino-Game-Of-Life
// Game of life
// http://en.wikipedia.org/wiki/Conway's_Game_of_Life
// Code adapted from
// http://cboard.cprogramming.com/c-programming/128982-simple-life-game-code-near-end.html
// basic ideas courtesy of Xander Soldaat
// ported to Arduino by HaWe aka dsyleixa
// supported displays:
// OLED 128x64 SSD1306 (Adafruit_SSD1306)
// and different Afadruit-GFX-compatible ones
// (adjust libs+resolutions!)
#include <Arduino.h>
// I2C
#include <Wire.h> // Incl I2C comm, but needed for not getting compile error
//-----------------------------------------------------------------------
// display driver
//-----------------------------------------------------------------------
#include <Adafruit_GFX.h> // https://github.com/adafruit/Adafruit-GFX-Library
// Adafruit Arduino OLED driver
#include <Adafruit_SSD1306.h> // https://github.com/esp8266/arduino
Adafruit_SSD1306 display(128, 64, &Wire); // new Adafruit lib
// fonts
#include <Fonts/FreeSans9pt7b.h> // optional
#include <Fonts/FreeMono12pt7b.h> // optional
#include <Fonts/FreeMono9pt7b.h> // used here by default
//#include <Fonts/FreeMonoBold7pt7b.h> // optional, custom font
//---------------------------------------------------------------------------
// preferences and settings
//---------------------------------------------------------------------------
// The blocks are blockSize * blockSize big
// 2...6 seems to be a good value for this
int blockSize = 3;
// The size of the OLED screen
const int screenWidth = 128; // <~~~~~~~~~~~~ adjust screen dimensions !
const int screenHeight = 64;
const int frame = 10;
// Make the board larger on either side to ensure that there's an invisible border of dead cells
int yrows = (screenHeight / blockSize) + 2*frame;
int xcols = (screenWidth / blockSize) + 2*frame;
#define centeryrow (yrows/2)-1
#define centerxcol (xcols/2)-1
// two boards, one for the current generation and one for calculating the next one
char board[screenHeight + 2*frame][screenWidth + 2*frame];
char tmpboard[screenHeight + 2*frame][screenWidth + 2*frame];
//---------------------------------------------------------------------------
// GoL functions
//---------------------------------------------------------------------------
// Count thy neighbours
int countNeighbours(int yrow, int xcol)
{
int count = 0;
for (int x = -1; x <= +1; x++) {
for (int y = -1; y <= +1; y++) {
if ((board[yrow + y][xcol + x] == 1) && (x != 0 || y != 0))
count++;
}
}
return count;
}
//---------------------------------------------------------------------------
// Calculate the cells that will live and die for the next generation
void calculateGeneration()
{
int aliveNeighbours = 0;
// Clear the board for the next generation
memset(tmpboard, 0, sizeof(tmpboard));
for (int yrow = 1; yrow < (yrows-1); yrow++) {
for (int xcol = 1; xcol < (xcols-1); xcol++) {
aliveNeighbours = countNeighbours(yrow, xcol);
// Any live cell with fewer than two live neighbours dies, as if caused by under-population.
if(aliveNeighbours < 2)
tmpboard[yrow][xcol] = 0;
// Any live cell with two or three live neighbours lives on to the next calculateGeneration
if (aliveNeighbours >= 2 && aliveNeighbours <= 3 )
tmpboard[yrow][xcol] = board[yrow][xcol];
// Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction
if(aliveNeighbours == 3 && board[yrow][xcol]==0)
tmpboard[yrow][xcol] = 1;
// Any live cell with more than three live neighbours dies, as if by overcyrowding
if(aliveNeighbours > 3)
tmpboard[yrow][xcol] = 0;
}
}
// Copy the new board to the old one
memcpy(board, tmpboard, sizeof(tmpboard));
}
//---------------------------------------------------------------------------
// Draw all the cells
//---------------------------------------------------------------------------
void drawBoard()
{
// Wipe the screen
display.clearDisplay();
for (int yrow=frame; yrow <(yrows-frame); yrow++)
{
for (int xcol=frame; xcol<(xcols-frame); xcol++)
{
// Draw all the "live" cells.
if (board[yrow][xcol])
display.fillRect((xcol-frame)*blockSize, (yrow-frame)*blockSize,
blockSize, blockSize, WHITE);
}
}
display.display();
}
//---------------------------------------------------------------------------
// patterns
//---------------------------------------------------------------------------
void put_Blinker3x1(int starty, int startx) { //
board[starty][startx] = 1;
board[starty][startx+1] = 1;
board[starty][startx+2] = 1;
}
//---------------------------------------------------------------------------
void put_Block2x2(int starty, int startx) { //
board[starty][startx] = 1;
board[starty][startx+1] = 1;
board[starty+1][startx] = 1;
board[starty+1][startx+1] = 1;
}
//---------------------------------------------------------------------------
void put_Bar5x1(int starty, int startx) { //
board[starty][startx] = 1;
board[starty][startx+1] = 1;
board[starty][startx+2] = 1;
board[starty][startx+3] = 1;
board[starty][startx+4] = 1;
}
void put_Clock(int starty, int startx) { //
int x,y;
char sprite[4][4] = { //
{0,0,1,0},
{1,1,0,0},
{0,0,1,1},
{0,1,0,0},
} ;
for(x=0; x<4; ++x) {
for(y=0; y<4; ++y) {
board[starty+y][startx+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_F_Pentomino(int starty, int startx) { // == R-Pentomino
int x,y;
char sprite[3][3] = { //
{0,1,1},
{1,1,0},
{0,1,0},
} ;
for(x=0; x<3; ++x) {
for(y=0; y<3; ++y) {
board[starty+y][startx+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_Pi_Heptomino(int starty, int startx) { //
int x,y;
char sprite[3][5] = { //
{0,0,1,0,0},
{0,1,0,1,0},
{1,1,0,1,1}
} ;
for(x=0; x<5; ++x) {
for(y=0; y<3; ++y) {
board[starty+y][startx+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_23334M(int starty, int startx) { //
int x,y;
char sprite[8][5] = { //
{0,0,1,0,0},
{1,1,0,0,0},
{0,1,0,0,0},
{1,0,0,1,0},
{0,0,0,0,1},
{0,1,0,0,1},
{0,0,1,0,1},
{0,1,0,0,0},
} ;
for(x=0; x<5; ++x) {
for(y=0; y<8; ++y) {
board[starty+y][startx+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_Glider(int starty, int startx) { //
int x,y;
char sprite[3][3] = { //
{0,1,0,},
{0,0,1,},
{1,1,1,}
} ;
for(x=0; x<3; ++x) {
for(y=0; y<3; ++y) {
board[starty+y][startx+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_GliderUp(int starty, int startx) { //
int x,y;
char sprite[3][3] = { //
{0,1,1,},
{1,0,1,},
{0,0,1,}
} ;
for(x=0; x<3; ++x) {
for(y=0; y<3; ++y) {
board[starty+y][startx+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_LWSpaceship(int starty, int startx) { //
int x,y;
char sprite[4][5] = { //
{1,0,0,1,0},
{0,0,0,0,1},
{1,0,0,0,1},
{0,1,1,1,1},
} ;
for(x=0; x<5; ++x) {
for(y=0; y<4; ++y) {
board[starty+y][startx+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_HWSpaceship(int starty, int startx) { //
int x,y;
char sprite[5][7] = { //
{0,0,1,1,0,0,0},
{0,0,0,0,0,1,0},
{0,0,0,0,0,0,1},
{1,0,0,0,0,0,1},
{0,1,1,1,1,1,1},
} ;
for(x=0; x<7; ++x) {
for(y=0; y<5; ++y) {
board[starty+y][startx+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_GliderGun(int starty, int startx) {
int x,y;
char sprite[9][37] = { //
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
} ;
for(x=0; x<37; ++x) { // NXT screen (0,0) is bottom left, not top left !
for(y=0; y<9; ++y) {
board[starty+y][startx+x] = sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
// This adds some random live cells to the board
void put_randomBoard(int seedChance)
{
for (int yrow = 1; yrow < (yrows - 1); yrow++)
{
for (int xcol = 1; xcol < (xcols - 1); xcol++)
{
board[yrow][xcol] = !(rand() % seedChance);
}
}
}
//---------------------------------------------------------------------------
// setup
//---------------------------------------------------------------------------
void setup() {
Serial.begin(115200);
delay(3000); // wait for Serial()
Serial.println("Serial started");
// Start Wire (SDA, SCL)
Wire.begin();
// SSD1306 Init
//display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // old Adafruit lib
display.begin(SSD1306_SWITCHCAPVCC, 0x3C, true, false); // new Adafruit lib
display.setRotation(2);
display.clearDisplay(); // Clear the buffer.
// text display tests
display.setTextSize(1);
display.setFont();
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("This is ");
display.println("Conway's Game of Live");
display.setCursor(0,30);
display.println("yrows, xcols =");
display.println(yrows);
display.println(xcols);
display.display();
delay(3000);
srand(analogRead(A0)+millis() );
put_Blinker3x1( 10, 10 ); // blockSize = 3-4
put_Block2x2( 10, centerxcol );
put_Bar5x1( centeryrow, xcols-20 );
put_Clock( yrows-20, centerxcol-10);
//put_F_Pentomino( centeryrow+1, centerxcol ); // blockSize = 1 !!
//put_Pi_Heptomino( centeryrow+2, centerxcol ); // blockSize = 1 !!
//put_23334M( centeryrow-1, centerxcol-1 ); // blockSize = 1 !!
//put_Glider(30, 30 );
/*
// unit of 3 //
put_GliderUp(centeryrow+5, 20 ); // rec. blockSize = 2; crash with LW_Spaceship
put_LWSpaceship( (yrows/4)+5, 12 ); // rec. blockSize = 2; crash with Glider
put_HWSpaceship( yrows-19, 10 ); // rec. blockSize = 2;
*/
//put_GliderGun( 10, 10 );
//put_randomBoard(3);
drawBoard();
delay(500);
}
//---------------------------------------------------------------------------
// loop
//---------------------------------------------------------------------------
void loop()
{
calculateGeneration();
drawBoard();
delay(200);
}
- - - Aktualisiert - - -
update:
hier ist eine portierte Version für M4 mit einem TFT 3.5 480x320, das M4-RAM reicht aber nur für max. etwa ein 320x240 subscreen window:
Code:
// Arduino-Game-Of-Life
// Game of life
// http://en.wikipedia.org/wiki/Conway's_Game_of_Life
// Code adapted from
// http://cboard.cprogramming.com/c-programming/128982-simple-life-game-code-near-end.html
// basic ideas courtesy of Xander Soldaat
// ported to Arduino by dsyleixa
// MCU: Adafruit Feather M4
// supported display:
// Adafruit Featherwing TFT35
// and different Afadruit-GFX-compatible ones
// (adjust libs+resolutions!)
#include <Arduino.h>
// i2c, SPI
#include <Wire.h> // Incl I2C comm, but needed for not getting compile error
#include <SPI.h>
//-----------------------------------------------------------------------
// display driver
//-----------------------------------------------------------------------
#include <Adafruit_GFX.h> // https://github.com/adafruit/Adafruit-GFX-Library
// Adafruit TFT35 LED driver
#include <Adafruit_HX8357.h>
#include <Adafruit_STMPE610.h>
// fonts
#include <Fonts/FreeSans9pt7b.h> // optional
#include <Fonts/FreeMono12pt7b.h> // optional
#include <Fonts/FreeMono9pt7b.h> // used here by default
//#include <Fonts/FreeMonoBold7pt7b.h> // optional, custom font
// TFT pins
#ifdef ESP8266
#define STMPE_CS 16
#define TFT_CS 0
#define TFT_DC 15
#define SD_CS 2
#elif defined ESP32
#define STMPE_CS 32
#define TFT_CS 15
#define TFT_DC 33
#define SD_CS 14
#elif defined TEENSYDUINO
#define TFT_DC 10
#define TFT_CS 4
#define STMPE_CS 3
#define SD_CS 8
#elif defined ARDUINO_STM32_FEATHER
#define TFT_DC PB4
#define TFT_CS PA15
#define STMPE_CS PC7
#define SD_CS PC5
#elif defined ARDUINO_FEATHER52
#define STMPE_CS 30
#define TFT_CS 13
#define TFT_DC 11
#define SD_CS 27
#elif defined(ARDUINO_MAX32620FTHR) || defined(ARDUINO_MAX32630FTHR)
#define TFT_DC P5_4
#define TFT_CS P5_3
#define STMPE_CS P3_3
#define SD_CS P3_2
// Something else!
#elif defined (__AVR_ATmega32U4__) || defined(ARDUINO_SAMD_FEATHER_M0) || defined (__AVR_ATmega328P__) || defined(ARDUINO_SAMD_ZERO) || defined(__SAMD51__)
#define STMPE_CS 6
#define TFT_CS 9
#define TFT_DC 10
#define SD_CS 5
// default
#else
#define STMPE_CS 6
#define TFT_CS 9
#define TFT_DC 10
#define SD_CS 5
#endif
#define TFT_RST -1
// display instance
Adafruit_HX8357 display = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
// color defs
#define BLACK HX8357_BLACK
#define DARKGREY HX8357_DARKGREY
#define WHITE HX8357_WHITE
#define RED HX8357_RED
#define YELLOW HX8357_YELLOW
#define CYAN HX8357_CYAN
#define DARKCYAN HX8357_DARKCYAN
#define BLUE HX8357_BLUE
#define GREENYELLOW HX8357_GREENYELLOW
#define COLOR_BKGR BLACK
//---------------------------------------------------------------------------
// preferences and settings
//---------------------------------------------------------------------------
// The blocks are blockSize * blockSize big
// 2...6 seems to be a good value for this
int blockSize = 3;
// The size of the GoL screen window
const int screenWidth = 240; // <~~~~~~~~~~~~ adjust screen dimensions !
const int screenHeight= 240;
const int frame = 10;
// Make the board larger on either side to ensure that there's an invisible border of dead cells
int yvisrows = (screenHeight / blockSize);
int xviscols = (screenWidth / blockSize);
int yrows = yvisrows + 2*frame;
int xcols = xviscols + 2*frame;
#define centeryrow (yrows/2)-1
#define centerxcol (xcols/2)-1
// two boards, one for the current generation and one for calculating the next one
char board[screenHeight + 2*frame][screenWidth + 2*frame];
char tmpboard[screenHeight + 2*frame][screenWidth + 2*frame];
//---------------------------------------------------------------------------
// GoL functions
//---------------------------------------------------------------------------
// Count thy neighbours
int countNeighbours(int yrow, int xcol)
{
int count = 0;
for (int x = -1; x <= +1; x++) {
for (int y = -1; y <= +1; y++) {
if ((board[yrow + y][xcol + x] == 1) && (x != 0 || y != 0))
count++;
}
}
return count;
}
//---------------------------------------------------------------------------
// Calculate the cells that will live and die for the next generation
void calculateGeneration()
{
int aliveNeighbours = 0;
// Clear the board for the next generation
memset(tmpboard, 0, sizeof(tmpboard));
for (int yrow = 1; yrow < (yrows-1); yrow++) {
for (int xcol = 1; xcol < (xcols-1); xcol++) {
aliveNeighbours = countNeighbours(yrow, xcol);
// Any live cell with fewer than two live neighbours dies, as if caused by under-population.
if(aliveNeighbours < 2)
tmpboard[yrow][xcol] = 0;
// Any live cell with two or three live neighbours lives on to the next calculateGeneration
if (aliveNeighbours >= 2 && aliveNeighbours <= 3 )
tmpboard[yrow][xcol] = board[yrow][xcol];
// Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction
if(aliveNeighbours == 3 && board[yrow][xcol]==0)
tmpboard[yrow][xcol] = 1;
// Any live cell with more than three live neighbours dies, as if by overcyrowding
if(aliveNeighbours > 3)
tmpboard[yrow][xcol] = 0;
}
}
// Copy the new board to the old one
memcpy(board, tmpboard, sizeof(tmpboard));
}
//---------------------------------------------------------------------------
// Draw all the cells
//---------------------------------------------------------------------------
void drawBoard()
{
// Wipe the screen
display.fillRect(1, 1, screenWidth+1, screenHeight+1, COLOR_BKGR);
for (int yrow=frame; yrow <(yrows-frame); yrow++) {
for (int xcol=frame; xcol<(xcols-frame); xcol++) {
// Draw all the "live" cells.
if (board[yrow][xcol])
display.fillRect((xcol-frame+1)*blockSize, (yrow-frame+1)*blockSize,
blockSize, blockSize, WHITE);
}
}
//display.display();
}
//---------------------------------------------------------------------------
// patterns
//---------------------------------------------------------------------------
void put_Blinker3x1(int starty, int startx) { //
board[starty+frame][startx+frame] = 1;
board[starty+frame][startx+frame+1] = 1;
board[starty+frame][startx+frame+2] = 1;
}
//---------------------------------------------------------------------------
void put_Block2x2(int starty, int startx) { //
board[starty+frame][startx+frame] = 1;
board[starty+frame][startx+frame+1] = 1;
board[starty+frame+1][startx+frame] = 1;
board[starty+frame+1][startx+frame+1] = 1;
}
//---------------------------------------------------------------------------
void put_Bar5x1(int starty, int startx) { //
board[starty+frame][startx+frame] = 1;
board[starty+frame][startx+frame+1] = 1;
board[starty+frame][startx+frame+2] = 1;
board[starty+frame][startx+frame+3] = 1;
board[starty+frame][startx+frame+4] = 1;
}
void put_Clock(int starty, int startx) { //
int x,y;
char sprite[4][4] = { //
{0,0,1,0},
{1,1,0,0},
{0,0,1,1},
{0,1,0,0},
} ;
for(x=0; x<4; ++x) {
for(y=0; y<4; ++y) {
board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_F_Pentomino(int starty, int startx) { // == R-Pentomino
int x,y;
char sprite[3][3] = { //
{0,1,1},
{1,1,0},
{0,1,0},
} ;
for(x=0; x<3; ++x) {
for(y=0; y<3; ++y) {
board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_Pi_Heptomino(int starty, int startx) { //
int x,y;
char sprite[3][5] = { //
{0,0,1,0,0},
{0,1,0,1,0},
{1,1,0,1,1}
} ;
for(x=0; x<5; ++x) {
for(y=0; y<3; ++y) {
board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_23334M(int starty, int startx) { //
int x,y;
char sprite[8][5] = { //
{0,0,1,0,0},
{1,1,0,0,0},
{0,1,0,0,0},
{1,0,0,1,0},
{0,0,0,0,1},
{0,1,0,0,1},
{0,0,1,0,1},
{0,1,0,0,0},
} ;
for(x=0; x<5; ++x) {
for(y=0; y<8; ++y) {
board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_Glider(int starty, int startx) { //
int x,y;
char sprite[3][3] = { //
{0,1,0,},
{0,0,1,},
{1,1,1,}
} ;
for(x=0; x<3; ++x) {
for(y=0; y<3; ++y) {
board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_GliderUp(int starty, int startx) { //
int x,y;
char sprite[3][3] = { //
{0,1,1,},
{1,0,1,},
{0,0,1,}
} ;
for(x=0; x<3; ++x) {
for(y=0; y<3; ++y) {
board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_LWSpaceship(int starty, int startx) { //
int x,y;
char sprite[4][5] = { //
{1,0,0,1,0},
{0,0,0,0,1},
{1,0,0,0,1},
{0,1,1,1,1},
} ;
for(x=0; x<5; ++x) {
for(y=0; y<4; ++y) {
board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_HWSpaceship(int starty, int startx) { //
int x,y;
char sprite[5][7] = { //
{0,0,1,1,0,0,0},
{0,0,0,0,0,1,0},
{0,0,0,0,0,0,1},
{1,0,0,0,0,0,1},
{0,1,1,1,1,1,1},
} ;
for(x=0; x<7; ++x) {
for(y=0; y<5; ++y) {
board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
void put_GliderGun(int starty, int startx) {
int x,y;
char sprite[9][37] = { //
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
} ;
for(x=0; x<37; ++x) { // NXT screen (0,0) is bottom left, not top left !
for(y=0; y<9; ++y) {
board[starty+frame+y][startx+frame+x] = sprite[y][x] ;
}
}
}
bool put_GliderEater(int starty, int startx, int V) {
int x,y;
char sprite[4][4] = { //
{1 ,1 ,0 ,0 },
{1 ,0 ,0 ,0 },
{V ,1 ,1 ,1 },
{0 ,0 ,0 ,1 },
} ;
for(x=0; x<4; ++x) {
for(y=0; y<4; ++y) {
board[starty+frame+y][startx+frame+x]=sprite[y][x] ;
}
}
}
//---------------------------------------------------------------------------
// This adds some random live cells to the board
void put_randomBoard(int seedChance)
{
for (int yrow = 1; yrow < (yrows - 1); yrow++)
{
for (int xcol = 1; xcol < (xcols - 1); xcol++)
{
board[yrow][xcol] = !(rand() % seedChance);
}
}
}
//---------------------------------------------------------------------------
// setup
//---------------------------------------------------------------------------
void setup() {
Serial.begin(115200);
delay(3000); // wait for Serial()
Serial.println("Serial started");
// Start Wire (SDA, SCL)
Wire.begin();
// TFT
display.begin(HX8357D);
display.setRotation(1);
display.fillScreen(COLOR_BKGR); // Clear Screen
// text display tests
display.setTextSize(1);
display.setFont();
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("This is ");
display.println("Conway's Game of Live");
display.setCursor(0,30);
display.print("xcols="); display.println(xviscols);
display.print("yrows="); display.println(yvisrows);
//display.display();
delay(1000);
srand(analogRead(A0)+millis() );
display.drawRect(0, 0, screenWidth+3, screenHeight+3, WHITE);
// test
// put_Glider(yvisrows-20, centerxcol);
// put_GliderUp(10, centerxcol);
int x=1, y=1;
put_GliderGun( y, x );
bool vanish=1;
int deltaXY=10;
put_GliderEater( 10 +y+deltaXY, 24 +x+deltaXY, vanish);
vanish=0;
deltaXY=33;
put_GliderEater( 10 +y+deltaXY, 24 +x+deltaXY, vanish);
drawBoard();
delay(50);
}
//---------------------------------------------------------------------------
// loop
//---------------------------------------------------------------------------
void loop()
{
calculateGeneration();
drawBoard();
delay(100);
}
(Die "GliderGun" (s. Code) kann ja als Generator eines Bit-Streams verstanden werden, unklar ist mir aber, wie man sie a) mit Inputs moduliert, b) liest und c) Ergebnisse ermittelt und ausgibt)
edit:
habe jetzt einen Artikel gefunden:
http://www.rennard.org/alife/english...tml#LCellFcnmt
Lesezeichen