Wiki

Clone wiki

Tic Tac Toe 3D / How_to_write_your_own_computer_enemy

To build your own computer enemy you have to implement the interface tictactoe3d.gamelogic.local.ComputerEnemy. However, the abstract class tictactoe3d.gamelogic.local.AbstractComputerEnemy does already some basic things for you, so it might be more handy to extend this class instead. In the following example a computer enemy is implemented that makes purely random moves.

tictactoe3d/computerenemies/RandomComputerEnemy.java:

package tictactoe3d.computerenemies;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import tictactoe3d.gamelogic.Cell;
import tictactoe3d.gamelogic.Game;
import tictactoe3d.gamelogic.GameActionListener;
import tictactoe3d.gamelogic.Player;
import tictactoe3d.gamelogic.local.AbstractComputerEnemy;

/**
 * This computer enemy makes purely random moves.
 */
public class RandomComputerEnemy extends AbstractComputerEnemy {
	private Random     random    = new Random();
	private List<Cell> openCells = new ArrayList<Cell>(4 * 4 * 4);
	
	/**
	 * In order to get notified on game events we have to
	 * implement the GameActionListener interface.
	 */
	private GameActionListener listener = new GameActionListener() {
		public void join(String userName, Player player) {}

		/**
		 * The only thing we need to do here is to update the
		 * computer enemies representation of the game field and
		 * make a move when the other player made one.
		 * 
		 * @param x coordiante of the issued move
		 * @param y coordiante of the issued move
		 * @param z coordiante of the issued move
		 * @param player is the id of the player who issued the moved
		 *        (Player.X or Player.O)
		 */
		public void move(int x, int y, int z, Player player) {
			openCells.remove(new Cell(x, y, z));
			
			/*
			 * Note: Because this comuter enemy is really dumb and can't
			 * decide by himself if the game already ended, it will make one
			 * last move after the other player won or the game ends with a
			 * draw. Maybe I will add a way to check the game's state, e.g. by
			 * game.getGameState() == GameState.PLAYING.
			 * 
			 * The wrong move will be reported to System.err but no error
			 * message will be shown to the user.
			 */
			if (player == other) {
				RandomComputerEnemy.this.move();
			}
		}

		public void draw() {}

		public void winner(Player player, Cell[] line) {}

		public void reset() {}

		public void leave(Player player) {}
	};
	
	/**
	 * This method initializes the computer enemies state. It will be called
	 * only once by tictactoe3d.gui.TicTacToe3DView.
	 * 
	 * @param game is the game to send the moves to.
	 * @param self is the id of this player (either Player.X or Player.O).
	 * @param name is the name of this player.
	 */
	@Override
	public void init(Game game, Player self, String name) {
		super.init(game, self, name);
		game.addGameActionListener(listener);
		reset();
	}
	
	/**
	 * With this method the class tictactoe3d.gui.TicTacToe3DView can command
	 * the computer enemy to forget its internal representation of the game.
	 */
	@Override
	public void reset() {
		openCells.clear();
		for (int z = 0; z <= 3; ++ z) {
			for (int y = 0; y <= 3; ++ y) {
				for (int x = 0; x <= 3; ++ x) {
					openCells.add(new Cell(x, y, z));
				}	
			}
		}
	}
	
	/**
	 * With this method the class tictactoe3d.gui.TicTacToe3DView can command
	 * the computer enemy to make a move.
	 */
	@Override
	public void move() {
		int n = openCells.size();
		
		if (n > 0) {
			Cell cell = openCells.get(random.nextInt(n));
			game.move(cell.x, cell.y, cell.z, self);
		}
	}
}

You can optionally assign a display name and a tooltip to your computer enemy using a properties file. This file has to have the same name and package path as the class of the computer enemy, but with the extension .properties instead of .java. It's also possible to use l10n and to add localized properties file, e.g. with the extension .properties.de ("de" stands for german ("deutsch")). If you do not provide a display name the classes simple name will be used (e.g. "RandomComputerEnemy"). These values will be used in the menu.

tictactoe3d/computerenemies/RandomComputerEnemy.properties:

displayName=random
tooltip=This computer enemy makes purely random moves.

Updated