生命游戏(Conway's Game of Life),又称为康威生命游戏、生命棋、康威生命棋,是一款零玩家游戏,由英国数学家约翰·霍顿·康威在1970年发明。这个游戏模拟了一个二维的格子世界,每个格子居住着一个生命细胞,每个细胞在下一个时间点只能处于两种状态之一:存活或死亡。
游戏规则如下:
- 任何有三个邻居的死细胞将会复活。
- 任何有两个邻居的细胞状态保持不变。
- 其他所有情况,细胞将会死亡。
其中,“邻居”是指一个细胞上下左右以及对角线方向的八个相邻细胞。
下面开始设计:
- 生命空间Space
- 生命细胞Cell
- 生命细胞组合在一起的时候,会有一些表现,Group
这里利用java的cavas开发,代码如下
1、Space类
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import static Constant.*;
public class Space extends JFrame {
public void launch() {
this.setSize(1920, 1080);
this.setLocation(0, 0);
this.setVisible(true);
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
//画出分割线
private void paintLine(Graphics g){
for(int i=0;i< width;i++){
g.drawLine(LENGTH*i,0,LENGTH*i,1080);
}
for(int j=0;j<height;j++){
g.drawLine(0,LENGTH*j,1920,LENGTH*j);
}
}
/**
* 继承gui方法,画出gui界面
* @param g
*/
@Override
public void paint(Graphics g){
g.setColor(new Color(42,17,21));
g.fillRect(0,0,1920,1080);
super.paint(g);
g.setColor(new Color(147,147,147));
paintLine(g);
}
//双缓冲
private Image offScreenImage = null;
@Override
public void update(Graphics g){
System.out.println(1);
if(offScreenImage == null){
System.out.println(2);
offScreenImage = this.createImage(1920,1080);
}
System.out.println(3);
Graphics gOff = offScreenImage.getGraphics();
paint(gOff);
g.drawImage(offScreenImage,0,0,null);
System.out.println(4);
}
}
2、Cell类
import java.awt.*;
import static Constant.*;
public class Cell {
private int x=0;
private int y=0;
private boolean status=false;//true:存活;false:死亡
public Cell(int x, int y){
this.x=x;
this.y=y;
}
public void setStatus(boolean status){
this.status = status;
}
public boolean isStatus() {
return status;
}
/**
* 在gui上画的方法
*/
public void paint(Graphics2D g){
//如果存活,则画图
if(status)
g.fillRect(x* LENGTH-6,y*LENGTH-3,LENGTH-5,LENGTH-5);
}
}
3、Group类
import javax.swing.*;
import java.awt.*;
import static Constant.*;
public class Group extends JPanel {
//定义细胞数组,对应相应格子的生命
public Cell[][] cellArray;
/**
* 构造方法
*/
public Group(){
//初始化细胞
cellArray= new Cell[width][height];
for(int i=0;i<width;i++){
for(int j=0;j<height;j++){
cellArray[i][j]=new Cell(i,j);
}
}
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
//转换为2d获得更高级的功能
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(new Color(28,159,32));
//更新页面
refreshCellArray(g2d);
}
/**
* 返回对应位置的细胞
* @param x
* @param y
* @return
*/
public Cell getCellxy(int x,int y){
if(x<0||x>=width||y<0||y>=height){
return null;
}
return cellArray[x][y];
}
/**
* 刷新细胞状态
*/
public void refreshCellArray(Graphics2D g){
Cell[][] nextCellArray = new Cell[width][height];
//赋值
for(int i=0;i<width;i++){
for(int j=0;j<height;j++){
nextCellArray[i][j]=new Cell(i,j);
nextCellArray[i][j].setStatus(cellArray[i][j].isStatus());
}
}
//刷新页面
for(int i=0;i<width;i++){
for(int j=0;j<height;j++){
boolean nextStatus = NumUtils.nextGenerationStatus(i,j,width,height,nextCellArray);
cellArray[i][j].setStatus(nextStatus);
cellArray[i][j].paint(g);
}
}
}
}
4、Main方法
import static Constant.FREQUENCY;
public class Main {
Space space = null;
Group group = null;
public static void main(String[] args) {
Main run = new Main();
}
public Main(){
//生成空间
space = new Space();
//生成细胞群
group = new Group();
//初始化细胞
this.initCellArray(group);
space.getContentPane().add(group);
space.launch();
//线程
new PaintThread().start();
}
//构造初始生命
public void initCellArray(Group group){
//滑翔机
group.getCellxy(10,10).setStatus(true);
group.getCellxy(11,11).setStatus(true);
group.getCellxy(9,12).setStatus(true);
group.getCellxy(10,12).setStatus(true);
group.getCellxy(11,12).setStatus(true);
}
//线程
class PaintThread extends Thread{
@Override
public void run(){
while (true){
space.repaint();
try{
Thread.sleep(FREQUENCY);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
}
5、工具类NumUtils
public class NumUtils {
/**
* 判断x,y是否超出二维数组范围
* @param x
* @param y
* @param width
* @param length
* @return
*/
public static boolean isOut(int x,int y,int width,int length){
if(x<0||x>=width||y<0||y>=length){
return false;
}
return true;
}
/**
* 判断下一代状态
* 如果周围3个细胞生存,则它为生
* 如果周围2个细胞生存,则不变
* 其他情况,则为死
* @return
*/
public static boolean nextGenerationStatus(int x, int y, int width, int length, Cell[][] cellArray){
int number = 0;//计算周围生存细胞的数量
//计算周边存活数量
int[][] matrix = {{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
for(int i=0;i<matrix.length;i++){
if(NumUtils.isOut(x+matrix[i][0],y+matrix[i][1],width,length)&&cellArray[x+matrix[i][0]][y+matrix[i][1]].isStatus()){
number++;
}
}
//判断状态
if(number==3){
return true;
}else if(number==2){
return cellArray[x][y].isStatus();
}
return false;
}
}
6、参数Constant
public class Constant {
public static int LENGTH = 15;//每格生命所占屏幕项目的长度
public static long FREQUENCY = 200;//页面刷新频率200ms/次
public static int width = 1920 / LENGTH;//从左往右
public static int height = 1080 / LENGTH;//从上往下
}
运行Main方法后即在界面上看到细胞的演化情况。