【发布时间】:2019-09-21 03:32:01
【问题描述】:
如果您不知道康威的人生游戏是什么,请检查一下,它是零玩家游戏和细胞自动化。 https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
我需要帮助调试我的代码中的以下问题。如有必要,我可以编辑此问题以包含我的程序的旧版本,这些版本不打算扩展。
我还将接受改进我的程序的提示,包括(但不限于)时间效率(但题外话,因为这不是主要问题)和不正确地使用现有方法。 (我的 paint() 方法)
问题:
检查图 1 中的滑翔机 A。(预期行为)该程序的全部目的是使 JFrame 中的单元格缩小,并将另一行或列死单元格添加到
ArrayList<ArrayList<Boolean>> grid。不幸的是,这架滑翔机不会导致这种情况发生。相反,结果(意外行为)是它只是“扁平化为正方形”,如图 2 所示(标有 A 的正方形)。检查图像 1 中的滑翔机 B。(预期行为)看到图像 1 中的滑翔机 A 的结果让我认为滑翔机 B 会以同样的方式结束。然而,这远非如此。看看图 2 中的滑翔机 B。由于某种原因,它甚至没有到达边界。 (意外)
这个程序的用途和目的:康威的生命游戏是在一个无限的 2D 平面上,所以我想复制它。我的其他程序使用了固定的数组大小,但这使用了嵌套的 ArrayLists 来扩展,并且真正是无限的(直到内存限制到来)
不幸的是,这个扩展程序根本无法扩展边界。 (边框实际上比看起来要小。基本上,(假装我的 ArrayList> 网格是一个数组)grid[0][0 to grid.length-1] inclusive、grid[grid.length-1][0 to grid.length-1] inclusive、grid[1 to grid.length-1][0] inclusive 和 grid[1 to grid.length-1][grid.length-1] inclusive。)而不是做指定的腾出空间的步骤,图 1 中的滑翔机 A 压平在边界上。 (边框在单元格网格下方,没有灰线)
这些图像相互对应;来自图像 1 的滑翔机 A 标题生成图像 2 中的正方形,也 标记为 A。如果您在代码中的 cmets 中看到任何描述“第 74 行”的词指向“第 74 行”或类似“UP”(没有任何其他含义)的词,请告诉我,以便我删除它们。这是一个单独的、已经修复的错误。
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Expansion {
static int delay = 50;
static SquarePaint sp = new SquarePaint();
static int K = 75; // An integer used below to create the starting setup for the grid.
static{
// 001 101 011
boolean[][] array = new boolean [300][200];
// array[30][30]
array[K][K+2] = true;
array[K+1][K] = true;
array[K+1][K+2] = true;
array[K+2][K+1] = true;
array[K+2][K+2] = true;
sp.define(array); // Uses array to make first setup
}
public static void main (String[] args){
// It is possible to put this information in a constructor instead
JFrame j = new JFrame();
j.add(sp); // Must add a custom paint component overriding the paint component,
//a class could and will do this
j.setVisible(true);
j.setSize(2000, 1000);
j.setResizable(false);
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static class SquarePaint extends Component{
static boolean VALUE = false;
public static final int screenX = 1000, screenY = 500;
static int cellSize = 5;
int cellsX = screenX / cellSize, cellsY = screenY / cellSize, frames = 0;
ArrayList<ArrayList<Boolean>> grid = new ArrayList<ArrayList<Boolean>>(); ////
Timer timer = new Timer(delay, new ActionListener(){
@Override
public void actionPerformed(ActionEvent A) {
//UPDATE FUNCTION
frames++;
boolean [][] oldGrid = new boolean[cellsX][cellsY];
for(int i=0; i<cellsX && i<grid.get(1).size(); i++){
for(int j=0; j<cellsY && j<grid.get(1).size(); j++){
oldGrid[i][j] = grid.get(i).get(j); // <<Line 74>><<Line 74>><<Line 74>>
}
}
/* These are notes
* How would I:
* Expand LinkedLists, for example
(Grid in a picture, 0 = variable, + = new cell)
0 0 0 +
0 0 0 +
0 0 0 +
0 0 0 +
* Adjust existing variables (and poorly coded methods if they exist) to suit this new change
*/
for(int i=1; i<cellsX-2; i++) {
for(int j=1; j<cellsY-2; j++) { // TODO
// System.out.println(i + " " + j);
int nearbyCells = nearbyCells(oldGrid, i, j);
/////////////////////////////////////////////
if(oldGrid[i][j]){
// If the cell is alive
// and is beside the no interact border, expand it by 1
// (Basically, to prevent ArrayOutOfBoundsException s,
// (the ArrayList equivalent) only cells from 1 to cellsX-1(-1)/cellsY-1(-1)
// are counted,)
// meaning that a whole row/column of cells is ignored and is not interacted with,
// until the grid expands.
ArrayList <Boolean> l = new ArrayList<Boolean>();
for(int k=0; k<cellsX; k++){
l.add(false);
}
if(i <= 1){ // You may notice that the above comments are wrong.
// This is because I thought this might be a small chance for it to succeed
// while I was frustrated this was not working.
grid.add(0, l);
cellSize = screenX / (cellSize + 1);
cellsX++;
VALUE = true;
repaint();
System.out.println("i<=5");
}
if(i >= cellsX-1){
grid.add(l);
cellSize = screenX / (cellSize + 1);
cellsX++;
VALUE = true;
repaint();
System.out.println("i>=cellsX");
}
if(j <= 1) {
for(int k=0; k<cellsY; k++){
grid.get(k).add(false);
}
cellSize = screenY / (cellSize + 1);
cellsY++;
VALUE = true;
System.out.println("j<=5");
repaint();
}
if(j >= cellsY-1) {
for(int k=0; k<cellsY; k++){
grid.get(k);
}
cellSize = screenY / (cellSize + 1);
cellsY++;
VALUE = true;
System.out.println("j>cellsY");
repaint();
}
//corner cases aren't a problem, it'll add to both sides
// && (i == 1 || i == cellsX-1 || j == 1 || j == cellsY-1)
/* i.e.
* 0 = dead cells
* 1 = annoying cells in the corner
* + = new cells
* First, it'll do this
* + + +
* 0 1 1
* 0 1 1 // Note that the square is a "still life form" meaning that it will
* 0 0 0 // simply sit there and do nothing for infinite generations if
* // untouched
* But the if statements above will return true more than once, so
* 0 0 0 +
* 0 1 1 +
* 0 1 1 +
* 0 0 0 +
*/
}
/////////////////////////////////////////////
if (oldGrid[i][j] && !(nearbyCells == 2 || nearbyCells == 3)){
// if it is alive, sustain rules
grid.get(i).set(j, false);
}
else if (!oldGrid[i][j] && nearbyCells == 3){ // if it is dead, birth rules
grid.get(i).set(j, true);
}
}
}
repaint(); // never erase, note that in bigger applications I assume that they
// draw to pictures that get slapped onto the screen so the paint function doesn't
// get called 9999 times and slow the fps down
}
});
int nearbyCells(boolean[][] oldGrid, int i, int j) { // A method that calculates how many cells are
//alive near it, i.e.
/* 0 = Dead
* 1 = Alive
* "+" = center
* 1 0 0
* 0 + 1
* 0 0 1
* If you called nearbyCells on the center in the example, then it would return 3.
*/
int nearbyCells = 0;
if(oldGrid[i+1][j+1]) nearbyCells++;
if(oldGrid[i+1][j]) nearbyCells++;
if(oldGrid[i+1][j-1]) nearbyCells++;
if(oldGrid[i][j+1]) nearbyCells++;
if(oldGrid[i][j-1]) nearbyCells++; // i, j is where the to-be-changed cell is, skip it
if(oldGrid[i-1][j+1]) nearbyCells++;
if(oldGrid[i-1][j]) nearbyCells++;
if(oldGrid[i-1][j-1]) nearbyCells++;
return nearbyCells;
}
public SquarePaint(boolean[][] grid){
define(grid);
timer.start();
}
public SquarePaint(){
timer.start();
}
public void define (boolean[][] grid){ // define cannot be called twice, not intended
for(int i=0; i<cellsX; i++){
ArrayList<Boolean> l = new ArrayList<Boolean>();
for(int j=0; j<cellsY; j++){
l.add(grid[i][j]);
}
this.grid.add(l);
}
}
@Override
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, screenX, screenY); // Warning: Color must be set
// each time if the paint command is ever to be called again
for(int i=0; i<cellsX-1; i++){
for(int j=0; j<cellsY-1; j++){
try{
if(grid.get(i).get(j)){
g.setColor(Color.WHITE);
g.fillRect(i * cellSize, j * cellSize, cellSize, cellSize);
} // Basically, 2 for loops
}// Nested for loops draw each cell on the potentially expanding ArrayList "grid" of cells
catch(java.lang.IndexOutOfBoundsException e){
System.out.println(i + " " + j);
e.getStackTrace();
}
g.setColor(Color.GRAY);
g.drawRect(i * cellSize, j * cellSize, cellSize, cellSize);
}
}
}
}
}
【问题讨论】:
标签: java swing arraylist jframe conways-game-of-life