/* * Artificial Intelligence for Humans * Volume 2: Nature Inspired Algorithms * Java Version * http://www.aifh.org * http://www.jeffheaton.com * * Code repository: * https://github.com/jeffheaton/aifh * * Copyright 2014 by Jeff Heaton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * For more information on Heaton Research copyrights, licenses * and trademarks visit: * http://www.heatonresearch.com/copyright */ package com.heatonresearch.aifh.examples.ca; import com.heatonresearch.aifh.examples.util.WorldPanel; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; /** * This example implements an elementary cellular automation. * <p/> * References: * http://mathworld.wolfram.com/ElementaryCellularAutomaton.html */ public class ElementaryCA extends JFrame implements ActionListener, WindowListener { /** * The generate button. */ private JButton generateButton; /** * The world area. */ private WorldPanel worldArea; /** * Allow rule # to be entered. */ private TextField ruleInput; /** * The number of rows. */ public static final int ROWS = 200; /** * The number of columns. */ public static final int COLS = 200; /** * The constructor. */ public ElementaryCA() { setSize(500, 500); setTitle("Elementary Cellular Automation"); Container c = getContentPane(); c.setLayout(new BorderLayout()); JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); c.add(buttonPanel, BorderLayout.NORTH); buttonPanel.add(new Label("Rule (0-255):")); buttonPanel.add(this.ruleInput = new TextField(5)); this.ruleInput.setText("30"); buttonPanel.add(generateButton = new JButton("Generate")); this.worldArea = new WorldPanel(ROWS, COLS, false); /* Allow scrolling. */ final JScrollPane scroll = new JScrollPane(this.worldArea); c.add(scroll, BorderLayout.CENTER); generateButton.addActionListener(this); this.addWindowListener(this); } /** * {@inheritDoc} */ @Override public void actionPerformed(ActionEvent ev) { if (ev.getSource() == generateButton) { performGenerate(); repaint(); } } /** * {@inheritDoc} */ @Override public void windowActivated(WindowEvent arg0) { // TODO Auto-generated method stub } /** * {@inheritDoc} */ @Override public void windowClosed(WindowEvent arg0) { } /** * {@inheritDoc} */ @Override public void windowClosing(WindowEvent arg0) { System.exit(0); } /** * {@inheritDoc} */ @Override public void windowDeactivated(WindowEvent arg0) { // TODO Auto-generated method stub } /** * {@inheritDoc} */ @Override public void windowDeiconified(WindowEvent arg0) { // TODO Auto-generated method stub } /** * {@inheritDoc} */ @Override public void windowIconified(WindowEvent arg0) { // TODO Auto-generated method stub } /** * {@inheritDoc} */ @Override public void windowOpened(WindowEvent arg0) { performGenerate(); } /** * The main entry point. * * @param args The arguments. */ public static void main(String[] args) { try { JFrame f = new ElementaryCA(); f.setVisible(true); } catch (Exception ex) { ex.printStackTrace(); } } /** * Generate the CA. */ public void performGenerate() { boolean invalid = false; boolean[] output = new boolean[8]; int center = this.worldArea.getCols() / 2; this.worldArea.getPrimaryGrid()[0][center] = true; boolean[][] grid = this.worldArea.getPrimaryGrid(); // Default to rule 30 int rule = 30; try { rule = Integer.parseInt(this.ruleInput.getText()); if (rule < 0 || rule > 255) { invalid = true; } } catch (NumberFormatException ex) { invalid = true; } if (invalid) { JOptionPane.showMessageDialog(null, "Invalid rule number, must be between 0 and 255."); return; } int cx = 1; int idx = 7; while (idx > 0) { output[idx--] = (rule & cx) != 0; cx *= 2; } for (int row = 1; row < this.worldArea.getRows(); row++) { int prevRow = row - 1; for (int i = 0; i < this.worldArea.getCols() - 2; i++) { boolean result = false; boolean a = grid[prevRow][i]; boolean b = grid[prevRow][i + 1]; boolean c = grid[prevRow][i + 2]; if (a && b && c) { result = output[0]; } else if (a && b && !c) { result = output[1]; } else if (a && !b && c) { result = output[2]; } else if (a && !b && !c) { result = output[3]; } else if (!a && b && c) { result = output[4]; } else if (!a && b && !c) { result = output[5]; } else if (!a && !b && c) { result = output[6]; } else if (!a && !b && !c) { result = output[7]; } grid[row][i + 1] = result; } } this.repaint(); } }