首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Java创建生命游戏的代码

用Java创建生命游戏的代码
EN

Code Review用户
提问于 2019-05-13 14:06:42
回答 1查看 109关注 0票数 2

链接到github链接到github:https://github.com/zombi3123/Game-Of-Life/

源代码:

Window.Java

代码语言:javascript
复制
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);
}

}

Main.Java

代码语言:javascript
复制
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);

}
}

Frame.Java

代码语言:javascript
复制
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) {}
}

Cell.Java

代码语言:javascript
复制
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);
    }
}

我想知道如何将这个程序精简成更少的行。

EN

回答 1

Code Review用户

回答已采纳

发布于 2019-05-14 06:10:21

线条的数量很少是衡量质量的标准。如果增加代码的可读性或效率,使用更多的行总是更好的。你为什么想要更少的台词?

无论如何,由于这是一个“大代码转储”,我将浏览它,指出最明显的事情。这不是一个详尽的清单。您可以从这些代码开始改进代码。

Window.Java

参数名称xy保留用于索引二维地图,例如,在图像中定位像素。代码将它们用于维度,其中widthheight会更好。

Main.Java

我不记得太多的秋千,但窗口不应该调整自己的大小,以适应框架?因此,将帧大小传递到窗口是多余的,因为它正是您想要的1800x1000像素的帧。

Frame.java

您可以从实现的接口中看到,这个类加载责任。将侦听器重构为独立的类,这样框架就不需要负责解释鼠标移动(单一责任原则)等等。该框架只适用于显示图形。

这门课有点乱。单元格存储在行和列的冗余数组中。从x和y位置计算索引的二维数组或一维数组将更容易理解,因为它们是此类应用程序中的常见结构。

General

细胞有一个单独的类,但在生命游戏中,细胞之间的关系同样重要。网格应该有一个单独的类,它包含单元格。不仅仅是一堆ArrayLists。控制细胞生死存亡的规则应该是另一类的。那门课就是游戏引擎。

框架不应该控制游戏。定时器应该是一个单独的类,它告诉游戏引擎更新游戏模型,并将事件发送到框架,让它知道视觉表示需要更新。看看模型-视图-控制器设计模式。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/220182

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档