链接到github链接到github:https://github.com/zombi3123/Game-Of-Life/
源代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
//JFrame Class
public class Window extends JFrame {
public Window(int x, int y) {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(x, y);
this.setResizable(true);
this.setLayout(null);
getContentPane().setBackground(Color.BLACK);
}
}public class Main {
//Main class
public static void main(String[] args){
Window w=new Window(1800,1000);
Frame f=new Frame(w.getWidth(),w.getHeight());
w.add(f);
w.setVisible(true);
}
}import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Random;
//JFrame class
public class Frame extends JPanel implements MouseListener, ActionListener, MouseMotionListener {
private ArrayList<Cell> columns;
private ArrayList<ArrayList<Cell>> rows;
private int cellLength,JFrameWidth,JFrameHeight;
private Color dead,killDefaultColor;
private Timer tm;
private int border;
private JButton Start,stop,randomize,kill,step,reset,drawLine;
private Random randNum;
private boolean killCells,drawLineMode;
public Frame(int JFrameWidth,int JFrameHeight){
tm=new Timer(1,this);
rows=new ArrayList<>();
columns= new ArrayList<>();
this.cellLength=3;
this.dead=Color.BLACK;
this.border=1;
this.JFrameWidth=JFrameWidth;
this.JFrameHeight=JFrameHeight;
this.killCells=false;
this.drawLineMode=false;
this.setSize(new Dimension(this.JFrameWidth, this.JFrameHeight));
randNum=new Random();
Start=new JButton("Start");
stop=new JButton("Stop");
randomize=new JButton("Randomize");
kill=new JButton("Kill Cells");
step=new JButton("Step");
reset=new JButton("Reset");
drawLine =new JButton("Line");
ArrayList<JButton> JB = new ArrayList<>();
JB.add(Start);
JB.add(stop);
JB.add(randomize);
JB.add(kill);
JB.add(step);
JB.add(reset);
JB.add(drawLine);
int i=50;
for (JButton j:JB){
j.setBounds(i*2,0,50,20);
this.add(j);
i+=10;
}
killDefaultColor=kill.getBackground();
Color killActiveColour=Color.green;
Start.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tm.start();
Start.setVisible(false);
// Start.setEnabled(false);
}
});
stop.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tm.stop();
Start.setEnabled(true);
Start.setVisible(true);
}
});
randomize.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for (int i = 1; i < rows.size()-1; i++) {
for (int j = 1; j < rows.get(0).size()-1; j++){
Cell c=rows.get(i).get(j);
float a=randNum.nextFloat();
if (a>0.90) {
c.setAlive();
}
}
}
repaint();
}
});
kill.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
killCells=!killCells;
if (!killCells) {
kill.setBackground(killDefaultColor);
}
else kill.setBackground(killActiveColour);
}
});
step.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ArrayList<Cell> deadCells=new ArrayList<Cell>();
ArrayList<Cell> bornCells=new ArrayList<Cell>();
for (int i = 1; i < rows.size()-1; i++) {
for (int j = 1; j < rows.get(0).size()-1; j++){
Cell c=rows.get(i).get(j);
Cell cE=rows.get(i).get(j+1);
Cell cW=rows.get(i).get(j-1);
Cell cN=rows.get(i-1).get(j);
Cell cS=rows.get(i+1).get(j);
Cell cNE=rows.get(i-1).get(j+1);
Cell cNW=rows.get(i-1).get(j-1);
Cell cSE=rows.get(i+1).get(j+1);
Cell cSW=rows.get(i+1).get(j-1);
if(c.isAlive()){
if(c.totalNeighbours(cE,cW,cN,cS,cNE,cNW,cSE,cSW)>=4){deadCells.add(c);}
if(c.totalNeighbours(cE,cW,cN,cS,cNE,cNW,cSE,cSW)<2){deadCells.add(c);}
}
else{
if(c.totalNeighbours(cE,cW,cN,cS,cNE,cNW,cSE,cSW)==3){bornCells.add(c);}
}
repaint();
}
}
for(Cell c:deadCells){c.setDead();}
for(Cell c:bornCells){c.setAlive();}
}
});
reset.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < rows.size()-1; i++) {
for (int j = 0; j < rows.get(0).size()-1; j++){
Cell c=rows.get(i).get(j);
c.setDead();
}
}
repaint();
}
});
drawLine.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
drawLineMode = !drawLineMode;
if (drawLineMode) {
killCells=false;
drawLine.setBackground(killActiveColour);
}
else{
drawLine.setBackground(killDefaultColor);
}
}
});
repaint();
createMap();
addMouseListener(this);
addMouseMotionListener(this);
setFocusable(true);
}
private void initComponents() {
}
public void createMap(){
//Draw grid. Initialize all cells to dead
for(int columsi=0;columsi<getHeight()/cellLength;columsi++){
ArrayList<Cell> columns = new ArrayList<>();
for(int rowsi=0;rowsi<getWidth()/cellLength;rowsi++){
Cell c=new Cell(rowsi*(cellLength+border),columsi*(cellLength+border),cellLength,false);
columns.add(c);
repaint();
}
rows.add(columns);
}
System.out.println(rows.size()*rows.get(0).size());
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < rows.size(); i++) {
for (int j = 0; j < rows.get(0).size(); j++){
Cell c=rows.get(i).get(j);
if (c.isAlive()) {
g.setColor(Color.black);
} else {
g.setColor(Color.white);
}
c.draw(g);
}
}
}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {
if (killCells){
for (int i = 1; i < rows.size()-1; i++) {
for (int j = 1; j < rows.get(0).size()-1; j++){
Cell c=rows.get(i).get(j);
if(e.getX()>=c.getTlx()&&e.getX()<c.getTlx()+c.getCellLength()&&e.getY()>= c.getTly()&&e.getY()<c.getTly()+c.getCellLength()) {
c.setDead();
repaint();
}
}
}
}
else if(!killCells && !drawLineMode){
outerLoop:
for (int i = 1; i < rows.size()-1; i++) {
for (int j = 1; j < rows.get(0).size()-1; j++){
Cell c=rows.get(i).get(j);
if(e.getX()>=c.getTlx()&&e.getX()<c.getTlx()+c.getCellLength()&&e.getY()>= c.getTly()&&e.getY()<c.getTly()+c.getCellLength()) {
c.setAlive();
repaint();
break outerLoop;
}
}
}
}
else if(drawLineMode=true){
outerLoop:
for (int i = 0; i < rows.size()-1; i++) {
for (int j = 0; j < rows.get(0).size()-1; j++){
Cell c=rows.get(i).get(j);
if(e.getX()>=c.getTlx()&&e.getX()<c.getTlx()+c.getCellLength()&&e.getY()>= c.getTly()&&e.getY()<c.getTly()+c.getCellLength()) {
for (int k = rows.indexOf(c); k < rows.get(0).size()-1; k++){
if(k+j>rows.get(0).size()-1){break outerLoop;}
else{rows.get(i).get(j+k).setAlive();}
repaint();
}
//break outerLoop;
}
}
}
}
}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
@Override
//When the timer ticks, action is performed
public void actionPerformed(ActionEvent e) {
ArrayList<Cell> deadCells=new ArrayList<Cell>();
ArrayList<Cell> bornCells=new ArrayList<Cell>();
for (int i = 1; i < rows.size()-1; i++) {
for (int j = 1; j < rows.get(0).size()-1; j++){
Cell c=rows.get(i).get(j);
Cell cE=rows.get(i).get(j+1);
Cell cW=rows.get(i).get(j-1);
Cell cN=rows.get(i-1).get(j);
Cell cS=rows.get(i+1).get(j);
Cell cNE=rows.get(i-1).get(j+1);
Cell cNW=rows.get(i-1).get(j-1);
Cell cSE=rows.get(i+1).get(j+1);
Cell cSW=rows.get(i+1).get(j-1);
if(c.isAlive()){
if(c.totalNeighbours(cE,cW,cN,cS,cNE,cNW,cSE,cSW)>=4){deadCells.add(c);}
if(c.totalNeighbours(cE,cW,cN,cS,cNE,cNW,cSE,cSW)<2){deadCells.add(c);}
}
else{
if(c.totalNeighbours(cE,cW,cN,cS,cNE,cNW,cSE,cSW)==3){bornCells.add(c);}
}
repaint();
}
}
for(Cell c:deadCells){c.setDead();}
for(Cell c:bornCells){c.setAlive();}
}
@Override
//When mouse dragged across screen, draw cells according to mouses position
public void mouseDragged(MouseEvent e) {
if(killCells){
outerloop:
for (int i = 1; i < rows.size()-1; i++) {
for (int j = 1; j < rows.get(0).size()-1; j++){
Cell c=rows.get(i).get(j);
if(c.isAlive()){
if(e.getX()>=c.getTlx()&&e.getX()<c.getTlx()+c.getCellLength()&&e.getY()>= c.getTly()&&e.getY()<c.getTly()+c.getCellLength()) {
c.setDead();
repaint();
break outerloop;
}
}
}
}
}
else{
for (int i = 1; i < rows.size()-1; i++) {
for (int j = 1; j < rows.get(0).size()-1; j++){
Cell c=rows.get(i).get(j);
if(e.getX()>=c.getTlx()&&e.getX()<c.getTlx()+c.getCellLength()&&e.getY()>= c.getTly()&&e.getY()<c.getTly()+c.getCellLength()) {
c.setAlive();
repaint();
}
}
}
}
}
@Override
public void mouseMoved(MouseEvent e) {}
}import java.awt.*;
import java.util.ArrayList;
//Cell class
public class Cell {
private int cellLength,tlx,tly;
private Color color;
private boolean alive;
public Cell(int tlx,int tly,int cellLength,boolean alive){
this.cellLength=cellLength;
this.alive=alive;
this.color=color;
this.tlx=tlx;
this.tly=tly;
}
public int getTlx(){return this.tlx;}
public int getTly(){return this.tly;}
public void setAlive() {
this.alive = true;
}
public void setDead() {
this.alive = false;
}
public boolean isAlive() {
return alive;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public int getCellLength() {
return cellLength;
}
public int totalNeighbours(Cell c1,Cell c2,Cell c3,Cell c4,Cell c5,Cell c6,Cell c7,Cell c8){
int liveNeighbours=0;
ArrayList<Cell> neighborslist=new ArrayList();
neighborslist.add(c1);
neighborslist.add(c2);
neighborslist.add(c3);
neighborslist.add(c4);
neighborslist.add(c5);
neighborslist.add(c6);
neighborslist.add(c7);
neighborslist.add(c8);
for(Cell c:neighborslist){
if(c.isAlive()){
liveNeighbours+=1;
}
}
return liveNeighbours;
}
public void draw(Graphics g){
g.setColor(color);
g.fillRect(tlx,tly,cellLength,cellLength);
}
}我想知道如何将这个程序精简成更少的行。
发布于 2019-05-14 06:10:21
线条的数量很少是衡量质量的标准。如果增加代码的可读性或效率,使用更多的行总是更好的。你为什么想要更少的台词?
无论如何,由于这是一个“大代码转储”,我将浏览它,指出最明显的事情。这不是一个详尽的清单。您可以从这些代码开始改进代码。
参数名称x和y保留用于索引二维地图,例如,在图像中定位像素。代码将它们用于维度,其中width和height会更好。
我不记得太多的秋千,但窗口不应该调整自己的大小,以适应框架?因此,将帧大小传递到窗口是多余的,因为它正是您想要的1800x1000像素的帧。
您可以从实现的接口中看到,这个类加载责任。将侦听器重构为独立的类,这样框架就不需要负责解释鼠标移动(单一责任原则)等等。该框架只适用于显示图形。
这门课有点乱。单元格存储在行和列的冗余数组中。从x和y位置计算索引的二维数组或一维数组将更容易理解,因为它们是此类应用程序中的常见结构。
细胞有一个单独的类,但在生命游戏中,细胞之间的关系同样重要。网格应该有一个单独的类,它包含单元格。不仅仅是一堆ArrayLists。控制细胞生死存亡的规则应该是另一类的。那门课就是游戏引擎。
框架不应该控制游戏。定时器应该是一个单独的类,它告诉游戏引擎更新游戏模型,并将事件发送到框架,让它知道视觉表示需要更新。看看模型-视图-控制器设计模式。
https://codereview.stackexchange.com/questions/220182
复制相似问题