Javascript 中的生命游戏:检查邻居不工作
Game of Life in Javascript: Checking neighbors not working
我正在尝试实施 Conway 的生命游戏,但它运行不正常,但我找不到问题所在。目前我每次都使用 setInterval()
来获得新一代的电路板,但我尝试使用 setTimeout()
进行一些错误检查,然后使用 console.table
检查前后表,但无法弄清楚。我的 checkNeighbors 函数对某些细胞但不是所有细胞都正常工作(即识别出生到死亡和死亡到出生)。
谁能帮我找出问题所在?
(我从我在 mapDispatchToProps 函数中调用的 newBoard 函数获取新板。)
这是我的代码和 Codepen 的 link:https://codepen.io/lieberscott/pen/qxrVbE?editors=0110
// React & Redux libraries setup
const { Component } = React;
const { createStore, applyMiddleware } = Redux;
const { Provider } = ReactRedux;
const { connect } = ReactRedux;
const { combineReducers } = Redux;
let grid = [];
let width = 25;
let height = 50;
for (let i = 0; i < height; i++) {
grid.push([]);
for (let j = 0; j < width; j++) {
grid[i][j] = Math.random() > 0.85;
}
}
const initState = {
arr: grid
};
const reducer = (state = initState, action) => {
let newState;
// console.table(state.arr);
switch (action.type) {
case "NEW_ARR":
newState = {
arr: action.arr
};
// console.table(newState.arr);
return newState;
break;
default:
return state;
break;
}
}
const store = createStore(reducer);
const newBoard = (arr, newArr) => {
for (let i = 0; i < height; i++) {
for (let j = 0; j < width; j++) {
let score = checkNeighbors(arr, i, j);
if (arr[i][j] == false && score == 3) {
newArr[i][j] = true;
}
else if (arr[i][j] == true && (score > 3 || score < 2)) {
newArr[i][j] = false;
}
else { // unessential line since already set newArr = arr
newArr[i][j] = arr[i][j];
}
}
}
return newArr;
}
function checkNeighbors(array, x, y) {
let score = 0;
for (let i = -1; i <= 1; i++) {
let h = (i + x + height) % height;
for (let j = -1; j <= 1; j++) {
let w = (j + y + width) % width;
score += array[h][w];
}
}
score -= array[x][y];
return score;
}
const Cell = (props) => {
return (
<td className={props.black ? "black" : ""}>
</td>
);
}
class App extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
setInterval(() => this.props.newGeneration(this.props.data.arr), 90)
}
render() {
return (
<table onClick={this.toggle}>
<thead>
</thead>
<tbody>
{this.props.data.arr.map((row, i) =>
<tr key={i}> {row.map((cell, j) =>
<Cell key={j} black={cell}/>)}
</tr> )}
</tbody>
</table>
);
}
}
const mapStateToProps = (state) => {
return {
data: state
};
};
const mapDispatchToProps = (dispatch) => {
return {
newGeneration: (array) => {
let arr1 = array.slice(0);
let arr2 = array.slice(0);
let newArr = newBoard(arr1, arr2);
dispatch(newGeneration(newArr));
}
}
}
function newGeneration(newArr) {
return {
type: "NEW_ARR",
arr: newArr
};
}
App = connect(mapStateToProps, mapDispatchToProps)(App); // use same name as class apparently?
const main = window.document.getElementById("main");
// Provider wraps our app
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
main);
我有点想明白了。在我的 newBoard 函数中,原始数组 (arr) 中的值正在更改(即使在我的代码中我表面上只是更改了 newArr 值)。
所以我改为更改 newBoard 函数,在函数中创建一个新数组,而不是传入一个数组。这有效:
https://codepen.io/lieberscott/pen/EQWGXW?editors=0110
const newBoard = (arr) => {
let newArr = [];
for (let i = 0; i < height; i++) {
newArr.push([]);
for (let j = 0; j < width; j++) {
let score = checkNeighbors(arr, i, j);
if (arr[i][j] == false && score == 3) {
newArr[i].push(true);
}
else if (arr[i][j] == true && (score > 3 || score < 2)) {
newArr[i].push(false);
}
else {
newArr[i].push(arr[i][j]);
}
}
}
return newArr;
}
不过,我认为任何关于为什么会发生原始行为的评论都是有价值的。
我正在尝试实施 Conway 的生命游戏,但它运行不正常,但我找不到问题所在。目前我每次都使用 setInterval()
来获得新一代的电路板,但我尝试使用 setTimeout()
进行一些错误检查,然后使用 console.table
检查前后表,但无法弄清楚。我的 checkNeighbors 函数对某些细胞但不是所有细胞都正常工作(即识别出生到死亡和死亡到出生)。
谁能帮我找出问题所在?
(我从我在 mapDispatchToProps 函数中调用的 newBoard 函数获取新板。)
这是我的代码和 Codepen 的 link:https://codepen.io/lieberscott/pen/qxrVbE?editors=0110
// React & Redux libraries setup
const { Component } = React;
const { createStore, applyMiddleware } = Redux;
const { Provider } = ReactRedux;
const { connect } = ReactRedux;
const { combineReducers } = Redux;
let grid = [];
let width = 25;
let height = 50;
for (let i = 0; i < height; i++) {
grid.push([]);
for (let j = 0; j < width; j++) {
grid[i][j] = Math.random() > 0.85;
}
}
const initState = {
arr: grid
};
const reducer = (state = initState, action) => {
let newState;
// console.table(state.arr);
switch (action.type) {
case "NEW_ARR":
newState = {
arr: action.arr
};
// console.table(newState.arr);
return newState;
break;
default:
return state;
break;
}
}
const store = createStore(reducer);
const newBoard = (arr, newArr) => {
for (let i = 0; i < height; i++) {
for (let j = 0; j < width; j++) {
let score = checkNeighbors(arr, i, j);
if (arr[i][j] == false && score == 3) {
newArr[i][j] = true;
}
else if (arr[i][j] == true && (score > 3 || score < 2)) {
newArr[i][j] = false;
}
else { // unessential line since already set newArr = arr
newArr[i][j] = arr[i][j];
}
}
}
return newArr;
}
function checkNeighbors(array, x, y) {
let score = 0;
for (let i = -1; i <= 1; i++) {
let h = (i + x + height) % height;
for (let j = -1; j <= 1; j++) {
let w = (j + y + width) % width;
score += array[h][w];
}
}
score -= array[x][y];
return score;
}
const Cell = (props) => {
return (
<td className={props.black ? "black" : ""}>
</td>
);
}
class App extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
setInterval(() => this.props.newGeneration(this.props.data.arr), 90)
}
render() {
return (
<table onClick={this.toggle}>
<thead>
</thead>
<tbody>
{this.props.data.arr.map((row, i) =>
<tr key={i}> {row.map((cell, j) =>
<Cell key={j} black={cell}/>)}
</tr> )}
</tbody>
</table>
);
}
}
const mapStateToProps = (state) => {
return {
data: state
};
};
const mapDispatchToProps = (dispatch) => {
return {
newGeneration: (array) => {
let arr1 = array.slice(0);
let arr2 = array.slice(0);
let newArr = newBoard(arr1, arr2);
dispatch(newGeneration(newArr));
}
}
}
function newGeneration(newArr) {
return {
type: "NEW_ARR",
arr: newArr
};
}
App = connect(mapStateToProps, mapDispatchToProps)(App); // use same name as class apparently?
const main = window.document.getElementById("main");
// Provider wraps our app
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
main);
我有点想明白了。在我的 newBoard 函数中,原始数组 (arr) 中的值正在更改(即使在我的代码中我表面上只是更改了 newArr 值)。
所以我改为更改 newBoard 函数,在函数中创建一个新数组,而不是传入一个数组。这有效:
https://codepen.io/lieberscott/pen/EQWGXW?editors=0110
const newBoard = (arr) => {
let newArr = [];
for (let i = 0; i < height; i++) {
newArr.push([]);
for (let j = 0; j < width; j++) {
let score = checkNeighbors(arr, i, j);
if (arr[i][j] == false && score == 3) {
newArr[i].push(true);
}
else if (arr[i][j] == true && (score > 3 || score < 2)) {
newArr[i].push(false);
}
else {
newArr[i].push(arr[i][j]);
}
}
}
return newArr;
}
不过,我认为任何关于为什么会发生原始行为的评论都是有价值的。