Hi all … Last week I got great help here with my beginner steps with object oriented programming, and my app works well now.
Now I am adding the famous “game of life” simulation to my program.
For this, I have a class called Dot, which handles each cell in a simple grid. These dots have properties like _lit which determines if that cell is “on” or “off” … Then I have a 2x2 matrix of them, which is dots… for example, I have a method “toggle”… dots[4][8].toggle() will toggle _lit on or off.
My problem arose when I tried to make a method called countneighbors(). The hope is that if I call dots[5][4].countneighbors() then it will check all of the 8 cells that are adjacent to that one cell… and simply return the count. For example if that cell is totally surrounded on all 8 sides, it will return 8.
But to write this, I have the countneighbors() method call another method, namely dots.look(). (look() just returns whether that one is lit or not.)
→ When I compile this, it highlights the place where countneighbors() calls look(), and it says:
error: ‘dots’ was not declared in this scope
Is it a problem to call one method from inside another? Can you tell me how I would correct this?
- Below is my entire code (with chunks omitted that were only related to other little games in the program.) See the method countneighbors() … you can see that I have commented with ERROR ERROR ERROR one of the lines that cr
- eates the error I’ve discussed…
- Huge thanks for any help you can give! --Eric
/* huzzah and 240 x 320 ili9341... a match made in heaven */
#include <Adafruit_GFX.h> // Include core graphics library
#include <Adafruit_ILI9341.h> // Include Adafruit_ILI9341 library to drive the display
// Declare pins for the display:
#define TFT_DC 16 // WAS ORIG 9
#define TFT_RST 12 // WAS ORIG 8~ // You can also connect this to the Arduino reset in which case, set this #define pin to -1!
#define TFT_CS 15 // WAS ORIG 10~
// The rest of the pins are pre-selected as the default hardware SPI for Arduino Uno (SCK = 13 and SDA = 11)
// Create display:
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
//#include <Fonts/FreeSerif24pt7b.h> // Add a custom font
const int screenwidth = 240;
const int screenheight = 320;
//const int numdotrows = 40, numdotcols = 30;
//const int numdotrows = 4, numdotcols = 3;
const int numdotrows = 320/10, numdotcols = 240/10;
const int dotwidth = screenwidth / numdotcols;
const int dotheight = screenheight / numdotrows;
const int maxmenu = 5;
int menuitem=0;
bool firstrun = true;
String menunames[] = {"a poem ", "rocket circuit ", "dot circuit ", "linear division ","sparkle ","ballbot "};
uint16_t colorof(uint8_t r, uint8_t g, uint8_t b) {
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
}
// CLASS DOT
class Dot {
public:
//constructor
Dot(int x, int y, bool lit, bool _tobelit);
// methods
void light(bool currentnotfuture);
void douse(bool currentnotfuture);
void toggle();
void draw();
bool look(bool currentnotfuture);
void shift();
int countneighbors();
private:
int _x;
int _y;
bool _lit;
bool _tobelit;
};
// DOT METHODS
Dot::Dot(int x, int y, bool lit, bool tobelit) {
_x = x;
_y = y;
_lit = lit;
_tobelit = tobelit;
}
void Dot::light(bool currentnotfuture) {
if (currentnotfuture) {
_lit = true;
}
else {
_tobelit = true;
}
}
void Dot::douse(bool currentnotfuture) {
if (currentnotfuture) {
_lit = false;
}
else {
_tobelit = false;
}
}
void Dot::toggle() {
_lit = not(_lit);
}
void Dot::draw() {
uint16_t color;
int drawx = (dotwidth) * _x;
int drawy = (dotheight) * _y;
if (_lit) {
color=0xFFFF;
}
else {
color=0x0000;
}
tft.fillRect(drawx,drawy,dotwidth,dotheight,color);
}
bool Dot::look(bool currentnotfuture) {
if (currentnotfuture) {
return _lit;
}
else {
return _tobelit;
}
}
void Dot::shift() {
_lit = _tobelit;
}
int Dot::countneighbors() { // COUNT THE EIGHT NEIGHBOR DOTS TO THIS DOT... THREE ABOVE, TWO ON SAME ROW, AND THREE BELOW.
int hstart = max(_x, 0);
int hend = max(_x+1, numdotcols);
int count = 0;
// the three TOP LAYER cells
if (_y-1 > 0) {
for (int xscan = hstart; xscan<hend+1; xscan++) {
if (dots[scan][_y-1]->look(true)) { // THIS IS ONE OF THE ERROR ERROR ERROR ERROR ERROR ERROR ONES
count++;
}
}
}
// the two MIDDLE LAYER cells
if (_x-1 >= 0) {
if (dots[_x-1][_y]->look(true)) {
count++;
}
}
if (_x+1 < numdotcols) {
if (dots[_x+1][_y]->look(true)) {
count++;
}
}
// the two BOTTOM LAYER cells
if (_y+1 < numdotrows) {
for (int xscan = hstart; xscan<hend+1; xscan++) {
if (dots[scan][_y+1]->look(true)) {
count++;
}
}
}
return count;
} // end of countneighbors
//INSTANTIATE DOTS
Dot *dots[numdotcols][numdotrows];
void waitbutton(int pin, bool shouldclear) {
while (digitalRead(pin) != HIGH ) {
delay(50);
};
if (shouldclear) {
tft.fillScreen(0x0000);
}
}
// [[DELETED CODE RELATED TO OTHER GAMES ]]
// [[DELETED CODE RELATED TO OTHER GAMES ]]
// [[DELETED CODE RELATED TO OTHER GAMES ]]
// [[DELETED CODE RELATED TO OTHER GAMES ]]
// [[DELETED CODE RELATED TO OTHER GAMES ]]
// [[DELETED CODE RELATED TO OTHER GAMES ]]
// [[DELETED CODE RELATED TO OTHER GAMES ]]
void g3place(int x, int y, uint16_t color) { // THIS PROCEDURE JUST PLAYING AROUND, NOT RELEVANT TO REAL GAME
int drawx = (dotwidth) * x;
int drawy = (dotheight) * y;
tft.fillRect(drawx,drawy,dotwidth,dotheight,color);
}
void g3pretty() { // THIS PROCEDURE JUST PLAYING AROUND, NOT RELEVANT TO REAL GAME
for (int xscan=0; xscan<numdotcols;xscan++) {
for (int yscan=0; yscan<numdotrows;yscan++) {
g3place(xscan,yscan,colorof((xscan+yscan % 2)*128+90, xscan*(255/numdotcols),yscan*(255/numdotrows) ));
}
}
}
void g3drawfield() {
for (int xscan=0; xscan<numdotcols;xscan++) {
for (int yscan=0; yscan<numdotrows;yscan++) {
dots[xscan][yscan]->draw();
}
}
}
void g3shiftall() {
for (int xscan=0; xscan<numdotcols;xscan++) {
for (int yscan=0; yscan<numdotrows;yscan++) {
dots[xscan][yscan]->shift();
}
}
}
void g3liferulepass() {
for (int xscan=0; xscan<numdotcols;xscan++) {
for (int yscan=0; yscan<numdotrows;yscan++) {
int c = dots[xscan][yscan]->countneighbors();
if (c<2 or c>3) {
dots[xscan][yscan]->douse(false);
}
if (c=3) {
dots[xscan][yscan]->light(false);
}
}
}
}
void game3() { //=====three=====three=====three=====three=====three=====three=====three=====three=====three=====three
bool quitter = false;
Serial.println("*** STARTING GAME3");
g3pretty();
waitbutton(4,true);
g3drawfield(); // should show all white
waitbutton(4,true);
for (int xscan=0; xscan<numdotcols;xscan++) { // fill nextbuffer with random
for (int yscan=0; yscan<numdotrows;yscan++) {
int randall = random(0,2);
if (randall == 1) {
dots[xscan][yscan]->light(false);
}
else {
dots[xscan][yscan]->douse(false);
}
}
}
g3drawfield(); // should still show all white
waitbutton(4,true);
g3shiftall(); // shift phase bringing next phase into reality
g3drawfield(); // should show the randoms AND WE ARE SEEDED AND READY TO START
waitbutton(4,true);
while (not quitter) {
g3liferulepass();
g3shiftall();
g3drawfield();
if (digitalRead(5) == HIGH ){ // BUTTON 4 QUITS
quitter = true;
}
waitbutton(4,true);
}
}
void setup() // Start of setup
{
Serial.begin(9600);
randomSeed(analogRead(0));
//SET UP GRID OF DOTS
for(int y=0;y<numdotrows;y++) {
for (int x=0;x<numdotcols;x++) {
dots[x][y] = new Dot(x,y,true, true);
}
}
pinMode(4,INPUT);
pinMode(5,INPUT);
// Display setup:
tft.begin(); // Initialize display
tft.fillScreen(0x0000); // Fill screen with black
//tft.setRotation(0); // Set orientation of the display. Values are from 0 to 3. If not declared, orientation would be 0,
// which is portrait mode.
} // End of setup
void loop() {
if (firstrun) {
firstrun = false;
//game1(2,5,20,7,true);
game3();
}
//HAD TO DELETE OTHER CODE
//HAD TO DELETE OTHER CODE
//HAD TO DELETE OTHER CODE
}
}