首页 > 技术文章 > 生命游戏

panxubin1011703 2018-12-12 22:54 原文

生命游戏实现代码:

package cn.com.demo.game;

import javax.swing.JLabel;

public class Cell extends JLabel {
private int status = 1;// 1活的 0:死

public int getStatus() {
	return status;
}

public void setStatus(int status) {
	this.status = status;
	if(this.status == 1){
		this.setIcon(Resources.LIVING);
	}else{
		this.setIcon(Resources.DEADED);
	}
}

}
////////
package cn.com.demo.game;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JPanel;

/**

  • 初始化细胞

  • 根据算法改变所有细胞下个状态

  • */
    public class CellController {
    // 行数
    private int rowCount = 0;
    // 列数
    private int columnCount = 0;
    // 二维数组
    // List
    private List<Cell[]> celles = new ArrayList<Cell[]>();
    // 存放所有细胞的新状态
    private List<int[]> newStatus = new ArrayList<int[]>();
    // 定义一个产生随机数的对象
    private Random random = new Random();

    private JPanel container;
    /**

    • 初始化所有的细胞,放到容器显示

    • /
      public void initCells(JPanel container){
      this.container = container;
      // 清除所有的旧细胞
      container.removeAll();
      // 获取容器的高度和宽度
      Rectangle rect = container.getBounds();
      int width = rect.width;
      int height = rect.height;
      // 根据容器的大小,计算出一行可以放多少个细胞(x)
      int xCount = width/30;
      this.columnCount = xCount;
      // 根据容器的大小,计算出一共可以放多少行细胞(y)
      int yCount = height/30;
      this.rowCount = yCount;
      // 根据计算的xCount和yCount初始化存放细胞的容器
      Cell[] row = null;
      for(int i=0;i<yCount;i++){
      row = new Cell[xCount];
      this.celles.add(row);
      this.newStatus.add(new int[xCount]);
      }
      // 在容器空格中添加细胞(状态为随机)
      for(int i=0;i<yCount;i++){
      // 获取i对应行的细胞位置
      row = this.celles.get(i);
      for(int j=0;j<xCount;j++){
      // 随机的产生一个细胞,放在当前的位置
      Cell cell = new Cell();
      // 设置一个随机的状态
      int randomNumber = this.random.nextInt(10000);
      int status = randomNumber%3;//0 1 2
      if(status == 2){
      cell.setStatus(1);// 活
      }else{
      cell.setStatus(0);// 死
      }
      // 设置细胞在容器中的位置
      cell.setBounds(j
      30, i*30, 30, 30);
      // 将细胞放入显示的容器中
      container.add(cell);
      // 将细胞放入自己的数据结构中
      row[j] = cell;
      }
      }
      }
      /**

    • 根据细胞现有的状态,计算下一个状态

    • 计算完后,更新所有细胞状态

    • */
      public void changeCellStatus(){
      // 计算所有细胞的下一个状态
      for(int i=0;i<this.rowCount;i++){
      Cell[] row = this.celles.get(i);
      for(int j=0;j<this.columnCount;j++){
      // 计算周围细胞的生命值
      int liveCount = this.computeLivingCount(j, i);
      // 根据周围细胞的生命值,确定当前细胞下一个状态
      if(liveCount>=3){
      this.newStatus.get(i)[j] = 1;
      }else if(liveCount>=2){// 2或 3
      this.newStatus.get(i)[j] = row[j].getStatus();
      }else{
      this.newStatus.get(i)[j] = 0;
      }
      }
      }

      // 根据前面计算的所有细胞的状态值,更新所有细胞的状态
      for(int i=0;i<this.rowCount;i++){
      for(int j=0;j<this.columnCount;j++){
      this.celles.get(i)[j].setStatus(this.newStatus.get(i)[j]);
      }
      }

      this.container.repaint();
      }
      /**
      计算x,y位置细胞的周围一共有多少活的细胞

    • */
      private int computeLivingCount(int x,int y){
      int count = 0;
      int targetX = 0, targetY =0;
      // 获取当前细胞左上角细胞的状态
      targetX = x-1;
      targetY = y -1;
      count += this.getStatus(targetX, targetY);
      // 获取当前细胞上细胞的状态
      targetX = x;
      targetY = y -1;
      count += this.getStatus(targetX, targetY);
      // 获取当前细胞右上角细胞的状态
      targetX = x + 1;
      targetY = y - 1;
      count += this.getStatus(targetX, targetY);
      // 获取当前细胞右细胞的状态
      targetX = x + 1;
      targetY = y;
      count += this.getStatus(targetX, targetY);
      // 获取当前细胞右下角细胞的状态
      targetX = x + 1;
      targetY = y + 1;
      count += this.getStatus(targetX, targetY);
      // 获取当前细胞下角细胞的状态
      targetX = x;
      targetY = y + 1;
      count += this.getStatus(targetX, targetY);
      // 获取当前细胞左下角细胞的状态
      targetX = x - 1;
      targetY = y + 1;
      count += this.getStatus(targetX, targetY);
      // 获取当前细胞左细胞的状态
      targetX = x - 1;
      targetY = y;
      count += this.getStatus(targetX, targetY);

      return count;
      }

    private int getStatus(int x, int y){
    int status = 0;
    if(x>=0 && x<this.columnCount && y>=0 && y<this.rowCount){
    status = this.celles.get(y)[x].getStatus();
    }
    return status;
    }
    }
    ///////
    package cn.com.demo.game;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainUI extends JFrame {
private CellController cellController = null;
private TimeController timeController = null;
private JPanel sub2;
public MainUI(){
cellController = new CellController();
init();
}

private void init(){
	// 设置窗口的大小
	this.setSize(600, 500);
	// 设置窗口显示的位置(居中)
	this.setLocationRelativeTo(null);
	// 设置窗口的标题
	this.setTitle("细胞游戏");
	// 点击x关闭窗口
	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	// 设置不允许改变窗口的大小
	this.setResizable(false);
	
	
	// 在窗口中放一个大容器
	// 创建容器对象
	JPanel container = new JPanel();
	// 设置容器的背景颜色
	container.setBackground(Color.green);
	// 设置布局管理器,以便于自己控制容器中其他对象的位置和大小
	container.setLayout(null);
	// 将容器加入窗口
	this.setContentPane(container);
	
	// 操作第一个子容器
	// 创建容器对象
	JPanel sub1 = new JPanel();
	sub1.setBackground(Color.white);
	sub1.setBounds(5, 5, 585, 50);
	sub1.setLayout(null);
	// 将子容器加入大容器
	container.add(sub1);
	
	// 在sub1容器里面,添加2个按钮和一个显示时间的标签
	// 创建开始按钮对象
	JButton btnStart = new JButton("开始游戏");
	btnStart.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent e) {
			cellController.initCells(sub2);
			if(timeController != null){
				timeController.setStop();
			}
			timeController = new TimeController(cellController);
			// 启动时间控制器
			timeController.start();
		}
	});
	// 设置开始按钮对象的位置
	btnStart.setBounds(10, 10, 110, 30);
	// 将开始按钮添加到sub1容器中
	sub1.add(btnStart);
	// 创建暂停和继续按钮
	JButton btnPause = new JButton("暂停/继续");
	btnPause.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent e) {
			// 暂停时间控制器
			timeController.changePauseStatus();
		}
	});
	btnPause.setBounds(130, 10, 110, 30);
	sub1.add(btnPause);
	// 创建显示时间的标签对象
	TimeLabel lblTime = new TimeLabel("游戏进行了3分43秒");
	lblTime.setBounds(300, 10, 200, 30);
	sub1.add(lblTime);
	
	// 第二个子容器
	sub2 = new JPanel();
	sub2.setBackground(Color.white);
	sub2.setBounds(5, 60, 585, 405);
	sub2.setLayout(null);
	container.add(sub2);
	
	// 调用细胞控制器的方法,初始容器中的所有细胞
	this.cellController.initCells(sub2);
}

}
/////
package cn.com.demo.game;

import javax.swing.Icon;
import javax.swing.ImageIcon;

public class Resources {
public static Icon LIVING;
public static Icon DEADED;

static{

   LIVING = new ImageIcon(Resources.class.getResource("/images/1.png"));
   DEADED = new ImageIcon(Resources.class.getResource("/images/2.png"));

}
}

////
package cn.com.demo.game;
/*
定时器
*/
public class TimeController extends Thread {
private CellController cellController;
private boolean isRun = true;
private boolean isPause = false;
public TimeController(CellController c){
this.cellController = c;
}

public void setStop(){
	this.isPause = false;
	this.isRun = false;
}

public void run(){
	while(isRun){
		System.out.println("****************111");
		// 定时更新细胞的状态
		this.cellController.changeCellStatus();
		try {
			// 1.5秒
			sleep(1500);
			// 控制暂停
			while(this.isPause){
				sleep(1000);
			}
		} catch (InterruptedException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}
}
// 改变是否暂停
public void changePauseStatus(){
	this.isPause = !this.isPause;
}

}

/////
package cn.com.demo.game;

import javax.swing.JLabel;

public class TimeLabel extends JLabel {
public TimeLabel(){
super();
}
public TimeLabel(String str){
super(str);
}
}
/////
package cn.com.demo.game;

public class Client {

public static void main(String[] args) {
	MainUI game = new MainUI();
	game.setVisible(true);
}

}

推荐阅读