Lost with Game of Life project

Hey all,
I’ve spent a couple of hours now working on my game of life project. I have a strong foundation, and I’ve thought of a good way to create one individual cell, but I don’t really know where to go from here. Here is what I’m currently working with: https://codepen.io/njanne19/pen/BZOJmq maybe someone can give me a hint to put me in the right direction from here.

This is the advice I gave recently:

I think I followed this:

  • plan out the React component architecture
  • create the grid and make sure I could activate individual cells
  • create a starting grid and see if I could take it through an iteration
  • set up the repeated iteration
  • add bells and whistles

OK, so you’ve got a grid.

Can you toggle the life of a cell by clicking on it? Then I’d see if I could run a single iteration and have it accurately calculate life/death. Then I’d go from there.

@ksjazzguitar

I was able to do that but now I’m stuck on the next step. I’m trying to get my “clear” button to work, as I have an array of JSX elements (cells), and I’m trying to set the state of all of them to {active: false}. is it even possible to set the state of every element in an array?

Sure, wherever you’re holding state, you copy state, use some for loops to set the flags, then call setState

@ksjazzguitar

I was able to figure out that part. Now I just gotta figure out how to make one iteration go, and then how to make multiple iterations go. I think I’m gonna take the day off from the project and just think it through. I’m having trouble thinking about how I can access the state of one cell from another. Currently the cells are being called as

<Cell cells={this.state.cells} id={i} key={i}/>. this.state.cells is an array that contains the element (as seen above) for every cell of every id from 1-1000. What I am getting stuck at however, is that if I can access the array of cells from the properties of one individual cell, is there any way to access the state of cells in an array?

“Now I just gotta figure out how to make one iteration go, …”

I don’t to give too much away, but first I had to right a function to calculate how many neighbors a cell had. Then I had to create a dummy array where I could put the next version of the array (you can’t change it directly or you could affect current cell calculations). Then I just setState with that new array.

What I am getting stuck at however, is that if I can access the array of cells from the properties of one individual cell, is there any way to access the state of cells in an array?

OK, you’re doing this differently than I did. I kept the state of each cell in the array I held in state in the Game component. You seem to be keeping it in the state of Cells - I’m still new to React, but that seems like it’s going to be a problem. I was advised to keep state in one parent component and that is what finally worked for me. Really, my cells didn’t have to hold any data except for their status. That’s where I kept it. You have to learn how to pass data back and forth between components, but that’s part of React.

But now I’m finding a problem in your code. To see if I could see your cells’ status in the state of Game. I put this line in the render() of your Game component:

  render() {
    console.log(this.state);
    return (
       // rest of code ...

When I looked at the output, I found that Cells was an array of 1001 cells. I clicked on that to see what data I could find. In each cell? A props object with an array of 1001 cells. In each cell? A props object with an array of 1001 cells. In each cell? A props object with an array of 1001 cells. In each cell? A props object with an array of 1001 cells. I gave up about 6 levels in.

So there is something wrong with your design. I don’t have time to weed through it right now. I would suggest reconsidering your design and keeping all of your state data in Game.

Passing data back and forth between components is tricky. I found Brad Traversy’s videos on youtube very helpful. I’m sure there are other good ones too.

@ksjazzguitar That makes a lot of sense, I’ll rethink it and start working on it tomorrow

I think I had to restart a lot of those React projects as I figured it out. But each time I did I understood React a little better. Two steps forward and one step back - we still get there.

@ksjazzguitar I now just tried using an array of 1’s and 0’s to map every element, but I’m getting an undefined error when I try to update the state if a cell is clicked.

The way I have it setup is, I made a method in my parent component called activate:

 activate(id) {
    var newLifeArray = this.state.lifeArray;
    if (newLifeArray[id] == 1) {
      newLifeArray[id] = 0;
    } else {
    newLifeArray[id] = 1;
    }
    this.setState({ lifeArray: newLifeArray });

Then I passed activate as a prop to every child cell. When they’re clicked, they’ll either be marked with a 1 or a 0 in the state of the parent component. However, this is not apparently working, and something is coming up as undefined.

I don’t have a solution, but I have noticed a couple of problems.

I notice in the browser console the error:

Uncaught TypeError: Cannot read property 'lifeArray' of undefined
    at Object.activate (VM380 pen.js:112)
    at Cells.activate (VM380 pen.js:61)
    at Object.r (VM378 react-dom.min.js:14)
    at a (VM378 react-dom.min.js:12)
    at Object.s [as executeDispatchesInOrder] (VM378 react-dom.min.js:12)
    at f (VM378 react-dom.min.js:12)
    at m (VM378 react-dom.min.js:12)
    at Array.forEach (<anonymous>)
    at r (VM378 react-dom.min.js:15)
    at Object.processEventQueue (VM378 react-dom.min.js:12)

So I go to your activate function in your Game component and add these two line at the top:

  activate(id) {
    console.log("Game.activate");
    console.log(this);
   // ... the function continues ...

When I examine the this object in the browser console, I find that there is no state property. That is a big problem.

I don’t have time to dig deeper, but that would be my first priority. Whenever I set up this kind of communication between React components, the first thing I check is if the information I want is being passed. The first order of business is to figure out why that method can’t see the state.

Also, in your Cell.render() you have the line:

    currentState = (currentState == true) ? false : true;

That can be simplified to:

    currentState = (currentState) ? false : true;

or even just:

    currentState = !currentState;

Some friendly advice. simplify.

Some suggestions:
use one array for state with just ones and zeroes
no need to store html elements in an array. redundant if you consider the DOM is also storing of the html.
use Array.map( item, index ) when you can instead of for loops

if you get stuck it usually means there are things that could to be simplified

Hi there!

Have you thought about using a two dimensional array for your state? Then you could iterate through each cell by using:

var cellArray = [];
var rows = 50;
var columns = 50;

for (var i = 0; i < rows; i++) {
  var rowToAnalyze = cellArray[i];
  for (var j = 0; j < columns; j++) {
     //code to determine cell state here
  }
}

Then if you need to lookup the state of a nearby cell, you could use this:

cellArray[i - 1][j + 1] //looks at a cell one row up and to the right

Remember: pass down to the children components only what they need. Nothing more. Review the docs!

@wwSchrader
@Monkeydogma
@ksjazzguitar
I’ve worked on it for a little bit and I think that I’ll do a 1-D array of every cell, but in order to go up and down, I can define the width of the grid. For example, if I was trying to check for neighbors of celli I could check for the life status of celli + width(directly below), i+width+1(below right), i+1(directly right), and so on so it uses math with width to find the 8 neighbors around it. Then later do the special cases(edges and corners). Or should I do the special cases first? Tell me what you think.

Yes, this was one of the trickier things. I think what I did was to create a function to convert my cell ID to cartesian coordinantes (x, y) and in that function I did error checking for edge and corner conditions. Then I created an array of 8 coordinates, each of the neighbors, for example:

      let nbArr = [
        this.getId(x, y-1),
        this.getId(x+1, y-1),
        // etc...

Of course x and y were generated by the same function, just for the actual point we were calculating.

Then I did a reduce on this array to see how many of these were “alive” and used that to determine the future status of the current cell.

I suppose you could try to do it without converting back and forth to cartesean coordinates, but the math seemed cleaner to me on that. I could just add or subtract 1 on the appropriate coord and see if it was out of bounds. If you’re going to do it without converting to coordinates, I’d go from most difficult to least difficult. I’d check corners first, then (else) I’d check sides, then (else) I’d do normal math.

@ksjazzguitar

Sounds great. I think I’ll try to do it my way because I have it all in my head conceptually as of right now. If I still have trouble I might take a look at converting them into Cartesian points. I’ll keep you posted and tell you when I finish.

I think I’ll try to do it my way because I have it all in my head conceptually as of right now.

Yeah, I’m sure it’s doable. It might even be easier - who knows. Let us know how it turns out.

@ksjazzguitar

Ok, so I’ve done a lot. I put my initial project to the side and did what you said had helped you learned better and I created the entire thing over again. Here is my new project:


My new problem is that the functions that are called to generate a new “generation” are called, but the component of the game is not re-rendered. One person on gitter suggested that this was because I had some of these global variables and they run into problematic situations, but I’m so close, and I’m wondering if my code is still salvageable. Take a look if you can. Essentially, the oneGen() function is being called, and the gameBoard array is updated with new cell info (with the logic actually working), but then my component CellGrid never gets updated.

OK, just taking a quick look, a few observations:

Now, I’m not expert on React, but …

I didn’t use any JQuery in mine. I found it odd to find so many functions wrapped in a JQuery ready function. To me, when using React, I let React handle all the functions inside of it’s lifecycle methods. This is an important part of React. React should handle all of those things. And React has it’s own Bootstrap for building buttons, etc. In a React app, you just don’t wrap your output JS in React - everything is wrapped in React. It’s a completely different way of thinking.

And if you want React to update the screen, then you update state. That is a major point of React - one-way data binding. You pass the data as props down to the components from the parent component, and then your grid is created from those props. Then when you update state, React will figure out what is affected and automatically update the screen. But that data must be changed in state and the screen must be build off data that comes to it in props from that state.

I’m swamped with work right now or I’d make up a simple program for you to see what I mean.

React is confusing if you’ve never done anything like it. I was dumbstruck as I tried to build these things. I had to take a week of and just learn React. I went to youtube and found some videos of people building things with React and built along with them and slowly began to understand how it is built. Even after that, I still got stumped on a few things (like I didn’t understand that every component had a different state and I needed to keep everything in one state in one component.)

I would really, really, really suggest that you take a step back and get to know React instead of trying to learn it piecemeal as you try to patch it on to what you’ve learned so far. React really is a different paradigm and I think it will take longer to learn the way you’re doing it and you run the risk of never quite getting it.

Like I said, youtube is wonderful. I found Brad Traversy’s stuff, like this and this. It can be a little frustrating because he’s building these locally and with multiple files, but you start to get an idea about the hierarchy of components and how things get done.

Maybe you’d want to start with simpler things that work in codepen, like this and this. Of course, I probably should have mentioned that Beau from Free Code Camp has a video.

There is a lot of material out there. I really recommend taking a step back and making sure you understand React’s way of thinking. Right now you’re swimming against the current.

@ksjazzguitar

I’ll take your suggestions, watch a few videos, and work through it. Also, by the way you linked me to a React-Native video which I assume you didn’t want to link me to. Thank you

Oops. Sorry, I was watching that the other day - I’m really looking forward to learning RN.