[TASK] Import.

This commit is contained in:
Jan Philipp Timme 2015-12-06 19:52:11 +01:00
commit 43e236fda9
25 changed files with 1516 additions and 0 deletions

8
.classpath Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="lib" path="forms-1.3.0.jar" sourcepath="forms-1.3.0-src.zip"/>
<classpathentry kind="lib" path="miglayout15-swing.jar" sourcepath="miglayout-src.zip"/>
<classpathentry kind="output" path="bin"/>
</classpath>

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.class

17
.project Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>TicTacToe</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,12 @@
#Sat Sep 03 13:48:41 CEST 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

3
META-INF/MANIFEST.MF Normal file
View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path: tictactoe.jar
Main-Class: org.jpt.tictactoe.Game

15
TicTacToeGui.launch Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/TicTacToe/src/org/jpt/tictactoe/gui/Main.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.jpt.tictactoe.gui.Main"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="TicTacToe"/>
</launchConfiguration>

BIN
forms-1.3.0-src.zip Normal file

Binary file not shown.

BIN
forms-1.3.0.jar Normal file

Binary file not shown.

BIN
miglayout-src.zip Normal file

Binary file not shown.

BIN
miglayout15-swing.jar Normal file

Binary file not shown.

View File

@ -0,0 +1,33 @@
package org.jpt.tictactoe;
import java.util.ArrayList;
public abstract class AbstractKi extends AbstractPlayer {
/**
* @param name
*/
public AbstractKi(String name) {
super(name);
}
/**
* @param Game
*/
public abstract boolean takeTurn(Game game);
/**
* @param fieldSet
* @return ArrayList<int[]>
*/
protected ArrayList<int[]> getEmptyFieldsFromFieldSet(int[][] fields) {
ArrayList<int[]> emptyFields = new ArrayList<int[]> ();
for(int x = 0; x < 3; x++){
for(int y = 0; y < 3; y++){
if(fields[x][y] == 0) emptyFields.add(new int[]{x,y});
}
}
return emptyFields;
}
}

View File

@ -0,0 +1,74 @@
package org.jpt.tictactoe;
public abstract class AbstractPlayer {
/**
* contains the next turn of the human player
* @var int[]
*/
protected int[] nextField = new int[2];
/**
* @var String
*/
protected String name;
/**
* @var int
*/
protected int playerNumber;
/**
* constructor
* @param playerNumber
* @param name
*/
public AbstractPlayer(String name) {
this.name = name;
}
/**
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return String
*/
public String getName() {
return this.name;
}
/**
* @param playerNumber
*/
public void setPlayerNumber(int playerNumber) {
this.playerNumber = playerNumber;
}
/**
* @return int
*/
public int getPlayerNumber() {
return this.playerNumber;
}
/**
* This method will be called by stuff.
* It will call a similar method on the game - this is legit.
*/
abstract public boolean takeTurn(Game game);
/**
* Sets the next field the player can use to make a turn.
* This is in use for HumanPlayers only!
* @param nextField
*/
public void setNextTurn(int[] nextField) {
this.nextField = nextField;
}
}

View File

@ -0,0 +1,35 @@
package org.jpt.tictactoe;
public interface AbstractView {
/**
* @param FieldSet fieldSet
* draws the field - however this will happen
*/
public abstract void drawField(FieldSet fieldSet);
/**
* @param player
* @return int[] containing the coordinates
*/
public abstract int[] askPlayerForField();
/**
* @param player
* @return String the Name
*/
public abstract String askPlayerForName();
/**
* have the view display the given message.
* @param msg
*/
public abstract void message(String msg);
/**
* I need this for gui stuff. Sorry :(
* @param game
*/
public abstract void setGame(Game game);
}

View File

@ -0,0 +1,24 @@
package org.jpt.tictactoe;
public class DumbKi extends AbstractKi {
/**
* constructor
* @param name
*/
public DumbKi(String name) {
super(name);
}
/**
* @param Game game
*/
public boolean takeTurn(Game game) {
for(int i = 0; i<3; i++) {
for(int j = 0; j<3; j++) {
if(game.setFieldOnFieldSet(i, j, this)) return true;
}
}
return false;
}
}

View File

@ -0,0 +1,65 @@
package org.jpt.tictactoe;
public class FieldSet {
/**
* 2D-Array for the field
*/
protected int[][] fields = new int[3][3];
/**
* Field constructor.
* Initializes field.
*/
public FieldSet(){
for(int i = 0; i<3; i++) {
for(int j = 0; j<3; j++) {
fields[i][j] = 0;
}
}
}
/**
* method to set a certain field to n.
* @param x
* @param y
* @param n
* @throws UsedFieldException
*/
public void setField(int x, int y, int n) throws UsedFieldException {
if(this.fields[x][y] != 0) throw new UsedFieldException();
else this.fields[x][y] = n;
}
/**
* method to retrieve the value of a certain field.
* @param x
* @param y
* @return int
*/
public int getField(int x, int y) {
return this.fields[x][y];
}
/**
* returns the whole fieldset
* @return int[][]
*/
public int[][] getFieldSet() {
return this.fields;
}
/**
* Checks the fieldset.
* @return boolean
*/
public boolean isFull() {
for(int i = 0; i<3; i++) {
for(int j = 0; j<3; j++) {
if(fields[i][j] == 0) return false;
}
}
return true;
}
}

View File

@ -0,0 +1,264 @@
package org.jpt.tictactoe;
public class Game {
/**
* @var FieldSet
*/
protected FieldSet fieldSet;
/**
* Index that points to the active player in the players-array
* @var int
*/
protected int activePlayer;
/**
* @var boolean
*/
protected boolean gameOver;
/**
* @var Array
*/
protected AbstractPlayer[] players = new AbstractPlayer[2];
/**
* @var int
*/
protected int playerCount = 0;
/**
* @var AbstractView
*/
protected AbstractView view;
/**
* @author JPT
* Contains representative values for the different kinds of players this game supports.
*/
public enum PlayerType {
HumanPlayer, DumbKI, MediumKI, RandomKI
}
/**
* constructor
*/
public Game() {
this.resetGame();
}
/**
* this method will process almost everything as long as there is no human interaction needed.
* also, it does NOT process human player turns. they do it on their own.
*/
public void processGame() {
this.gameOver = this.checkGameOver();
if(this.isGameOver() == true) return;
//get active player
AbstractPlayer activePlayer = this.getActivePlayer();
//as long as active player is NOT human, do it automatically
while(activePlayer instanceof HumanPlayer == false) {
activePlayer.takeTurn(this);
this.gameOver = this.checkGameOver();
this.drawField();
activePlayer = this.getActivePlayer();
//it's not thaat important...
if(this.isGameOver()) break;
}
}
/**
* Adds a player to the game. hehehehe... the game...
* you just lost it. :P
* @param player
*/
public void addPlayer(AbstractPlayer player) {
player.setPlayerNumber(this.playerCount + 1);
this.players[this.playerCount] = player;
this.playerCount++;
}
/**
* checks the field for a gameover condition.
* @return boolean
*/
protected boolean checkGameOver() {
int[][] fieldSetCopy = this.fieldSet.getFieldSet();
int winnerId = 0;
//check rows
for(int x = 0; x < 3; x++) {
if(fieldSetCopy[x][0] == fieldSetCopy[x][1] && fieldSetCopy[x][1] == fieldSetCopy[x][2]) {
if(winnerId == 0) winnerId = fieldSetCopy[x][0];
}
}
//check cols
for(int y = 0; y < 3; y++) {
if(fieldSetCopy[0][y] == fieldSetCopy[1][y] && fieldSetCopy[1][y] == fieldSetCopy[2][y]) {
if(winnerId == 0) winnerId = fieldSetCopy[0][y];
}
}
//check diags
if(fieldSetCopy[0][0] == fieldSetCopy[1][1] && fieldSetCopy[1][1] == fieldSetCopy[2][2]) {
if(winnerId == 0) winnerId = fieldSetCopy[1][1];
}
//other diags
if(fieldSetCopy[2][0] == fieldSetCopy[1][1] && fieldSetCopy[1][1] == fieldSetCopy[0][2]) {
if(winnerId == 0) winnerId = fieldSetCopy[1][1];
}
//if winner, announce winner
if(winnerId != 0) {
this.view.message(this.getPlayerByPlayerNumber(winnerId).getName() + " won the game!");
return true;
}
//else, if it's just full...
if(this.fieldSet.isFull() == true){
this.view.message("Apparently, this is a draw. Congratulations :D");
return true;
}
return false;
}
/**
* Checks whether the player is allowed to take its turn.
* Also manages the activePlayer attribute.
*
* @param x
* @param y
* @param player
* @return boolean
*/
public boolean setFieldOnFieldSet(int x, int y, AbstractPlayer player) {
if(player != this.getActivePlayer()) {
this.view.message(player.getName() + " took an illegal turn!");
return false;
}
try {
//check whether coords are in range...
if(x < 0 || x > 2 || y < 0 || y > 2) {
return false;
}
this.fieldSet.setField(x, y, player.getPlayerNumber());
this.view.message(player.getName() + " took his turn and marked on: ["+x+","+y+"]");
this.changeActivePlayer();
return true;
} catch (UsedFieldException e) {
return false;
}
}
/**
* changes the active player.
*/
protected void changeActivePlayer() {
int activePlayerPointer = this.activePlayer;
activePlayerPointer++;
if(activePlayerPointer == this.players.length) activePlayerPointer = 0;
this.activePlayer = activePlayerPointer;
}
/**
* @return AbstractPlayer active player
*/
public AbstractPlayer getActivePlayer() {
return this.players[this.activePlayer];
}
/**
* @return AbstractPlayer player
*/
protected AbstractPlayer getPlayerByPlayerNumber(int playerNumber) {
for(int i = 0; i < this.players.length; i++) {
if(this.players[i].getPlayerNumber() == playerNumber) return this.players[i];
}
return null;
}
/**
* @return FieldSet
*/
public FieldSet getFieldSet() {
return this.fieldSet;
}
/**
* Sets the view.
* @param view
*/
public void setView(AbstractView view) {
view.message("Welcome to TicTacToe!");
this.view = view;
}
/**
* Gets the view.
* @return AbstractView view
*/
public AbstractView getView() {
return this.view;
}
/**
* @return boolean
*/
public boolean isGameOver() {
return this.gameOver;
}
/**
* Have the view draw the field.
*/
public void drawField() {
this.view.drawField(this.fieldSet);
}
/**
* Creates a player based on a given PlayerType
* @param playerType
* @param name
* @return AbstractPlayer
*/
public AbstractPlayer createPlayerByEnum(PlayerType playerType, String name) {
switch(playerType) {
case HumanPlayer:
return new HumanPlayer(name);
case DumbKI:
return new DumbKi(name);
case MediumKI:
return new MediumKi(name);
case RandomKI:
return new RandomKi(name);
default:
System.out.println("Not implemented yet: " + playerType);
break;
}
return null;
}
/**
* resets all game relevant variables except for the players.
*/
public void resetGame() {
this.fieldSet = new FieldSet();
this.gameOver = false;
this.playerCount = 0;
this.activePlayer = 0;
}
/**
* @return AbstractPlayer[]
*/
public AbstractPlayer[] getPlayers() {
return this.players;
}
}

View File

@ -0,0 +1,42 @@
package org.jpt.tictactoe;
public class HumanPlayer extends AbstractPlayer {
/**
* constructor
* @param name
*/
public HumanPlayer(String name) {
super(name);
}
/**
* Sets the next turn the humanPlayer will do.
* @param nextField
*/
public void setNextTurn(int[] nextField) {
this.nextField = nextField;
}
/**
* We take our turn here.
* @return boolean
*/
public boolean takeTurn(Game game) {
if(game.isGameOver()) return false;
boolean success = false;
int[] coordinates = this.nextField;
if(coordinates == null) {
game.getView().message("Ups.");
}
int x = coordinates[0];
int y = coordinates[1];
success = game.setFieldOnFieldSet(x, y, this);
if(!success) {
game.getView().message("The field on ["+x+","+y+"] is already taken or invalid.");
}
return success;
}
}

View File

@ -0,0 +1,121 @@
package org.jpt.tictactoe;
import java.util.ArrayList;
import java.util.Random;
public class MediumKi extends AbstractKi {
/**
* constructor
* @param name
*/
public MediumKi(String name) {
super(name);
}
/**
* @param Game game
* @return boolean
*/
public boolean takeTurn(Game game) {
Random randomGenerator = new Random(System.nanoTime());
int[][] fields = game.getFieldSet().getFieldSet();
AbstractPlayer[] players = game.getPlayers();
int enemyNumber = 0;
for(int i = 0; i < players.length; i++) {
if(players[i].equals(this) == false) enemyNumber = players[i].getPlayerNumber();
}
ArrayList<int[]> instantWinFields = this.getWinFieldsForNumber(this.getPlayerNumber(), fields, false);
if(instantWinFields.size() > 0) {
int randomInt = (instantWinFields.size() > 1) ? randomGenerator.nextInt(instantWinFields.size()) : 0;
int[] coord = instantWinFields.get(randomInt);
int x = coord[0];
int y = coord[1];
if(game.setFieldOnFieldSet(x, y, this)) return true;
}
ArrayList<int[]> enemyFields = this.getWinFieldsForNumber(enemyNumber, fields, false);
if(enemyFields.size() > 0) {
int randomInt = (enemyFields.size() > 1) ? randomGenerator.nextInt(enemyFields.size() - 1) : 0;
int[] coord = enemyFields.get(randomInt);
int x = coord[0];
int y = coord[1];
if(game.setFieldOnFieldSet(x, y, this)) return true;
}
ArrayList<int[]> possibleWinFields = this.getWinFieldsForNumber(this.getPlayerNumber(), fields, true);
if(possibleWinFields.size() > 0) {
int randomInt = (possibleWinFields.size() > 1) ? randomGenerator.nextInt(possibleWinFields.size()) : 0;
int[] coord = possibleWinFields.get(randomInt);
int x = coord[0];
int y = coord[1];
if(game.setFieldOnFieldSet(x, y, this)) return true;
}
ArrayList<int[]> emptyFields = this.getEmptyFieldsFromFieldSet(fields);
if(emptyFields.size() > 0) {
int randomInt = (emptyFields.size() > 1) ? randomGenerator.nextInt(emptyFields.size() - 1) : 0;
int[] coord = emptyFields.get(randomInt);
int x = coord[0];
int y = coord[1];
if(game.setFieldOnFieldSet(x, y, this)) return true;
}
game.getView().message("I don't know what to do! O__o");
return false;
}
/**
* Finds the position of the empty field in case the the other two fields are equal
* @param int[] numbers
* @return int
*/
protected int getFreeFieldFor(int[] numbers, int playerNumber, boolean softResults) {
if(numbers[0] == numbers[1] || numbers[1] == numbers[2] || numbers[2] == numbers[0]) {
int[] counter = new int[]{0,0,0};
int fieldPos = 0;
for(int i = 0; i < 3; i++) {
if(numbers[i] == 0) fieldPos = i;
counter[numbers[i]]++;
}
if(counter[0] == 1 && counter[playerNumber] == 2) return fieldPos;
if(softResults == true && counter[0] == 2 && counter[playerNumber] == 1) return fieldPos;
}
return -1;
}
/**
* returns an ArrayList of possible winner-coords based on the game logic for the given playerNumber.
* [we search for a win condition and then add empty fields]
* @return ArrayList<int[]>
*/
protected ArrayList<int[]> getWinFieldsForNumber(int playerNumber, int[][] fields, boolean softResult) {
ArrayList<int[]> relevantFields = new ArrayList<int[]> ();
int fieldPos;
//check rows
for(int x = 0; x < 3; x++) {
fieldPos = this.getFreeFieldFor(new int[]{fields[x][0],fields[x][1],fields[x][2]}, playerNumber, softResult);
if(fieldPos > -1) relevantFields.add(new int[]{x,fieldPos});
}
//check cols
for(int y = 0; y < 3; y++) {
fieldPos = this.getFreeFieldFor(new int[]{fields[0][y],fields[1][y],fields[2][y]}, playerNumber, softResult);
if(fieldPos > -1) relevantFields.add(new int[]{fieldPos, y});
}
//check diags
fieldPos = this.getFreeFieldFor(new int[]{fields[0][0],fields[1][1],fields[2][2]}, playerNumber, softResult);
if(fieldPos > -1) relevantFields.add(new int[]{fieldPos, fieldPos});
//check diags
fieldPos = this.getFreeFieldFor(new int[]{fields[2][0],fields[1][1],fields[0][2]}, playerNumber, softResult);
if(fieldPos > -1) relevantFields.add(new int[]{2 - fieldPos, fieldPos});
return relevantFields;
}
}

View File

@ -0,0 +1,34 @@
package org.jpt.tictactoe;
import java.util.ArrayList;
import java.util.Random;
public class RandomKi extends AbstractKi {
/**
* constructor
* @param name
*/
public RandomKi(String name) {
super(name);
}
/**
* @param Game game
* @return boolean
*/
public boolean takeTurn(Game game) {
Random randomGenerator = new Random(System.nanoTime());
int[][] fields = game.getFieldSet().getFieldSet();
ArrayList<int[]> emptyFields = this.getEmptyFieldsFromFieldSet(fields);
int i = emptyFields.size();
i = (i > 1) ? i - 1 : i;
int randomInt = randomGenerator.nextInt(i);
int[] coord = emptyFields.get(randomInt);
int x = coord[0];
int y = coord[1];
if(game.setFieldOnFieldSet(x, y, this)) return true;
return false;
}
}

View File

@ -0,0 +1,10 @@
package org.jpt.tictactoe;
public class UsedFieldException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,401 @@
package org.jpt.tictactoe.gui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import javax.swing.text.BadLocationException;
import net.miginfocom.swing.MigLayout;
import org.jpt.tictactoe.AbstractView;
import org.jpt.tictactoe.FieldSet;
import org.jpt.tictactoe.Game;
import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;
public class GuiView extends JFrame implements AbstractView, ActionListener, MouseListener {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* @var JLabel
*/
public JLabel player1NameLabel;
/**
* @var JLabel
*/
public JLabel player2NameLabel;
/**
* an array of buttons...
*/
protected JButton[][] buttons = new JButton[3][3];
/**
* @var JTextArea
*/
protected JTextArea textArea;
/**
* @var NewGameDialog
*/
protected NewGameDialog newGameDialog;
/**
* Contains the game. I need this to be consistent here.
* It's important for the Gui stuff.
* @var Game
*/
protected Game game;
/**
* @var JScrollPane
*/
protected JScrollPane scrollPane;
/**
* @var JButton
*/
protected JButton newGameButton;
/**
* @var JButton
*/
protected JButton repeatGameButton;
/**
* @param game
*/
public void setGame(Game game) {
this.game = game;
}
/**
* Create the frame.
* And the stuff within.
* And even more weird configurations.
*/
public GuiView() {
setTitle("TicTacToe");
setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
getContentPane().setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
getContentPane().setLayout(new BorderLayout(0, 0));
JPanel MidWestPanel = new JPanel();
MidWestPanel.setPreferredSize(new Dimension(135, 10));
MidWestPanel.setMinimumSize(new Dimension(125, 10));
getContentPane().add(MidWestPanel, BorderLayout.WEST);
MidWestPanel.setLayout(new FormLayout(new ColumnSpec[] {
FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
ColumnSpec.decode("125px"),},
new RowSpec[] {
FormFactory.LINE_GAP_ROWSPEC,
RowSpec.decode("23px"),
FormFactory.LINE_GAP_ROWSPEC,
RowSpec.decode("23px"),}));
JLabel player1Label = new JLabel("Spieler 1");
player1Label.setFont(new Font("SansSerif", Font.BOLD, 12));
MidWestPanel.add(player1Label, "2, 2, center, center");
JLabel player1NameLabel = new JLabel("");
this.player1NameLabel = player1NameLabel;
MidWestPanel.add(player1NameLabel, "2, 4, center, center");
JPanel MidEastPanel = new JPanel();
MidEastPanel.setPreferredSize(new Dimension(135, 10));
MidEastPanel.setMinimumSize(new Dimension(100, 10));
getContentPane().add(MidEastPanel, BorderLayout.EAST);
MidEastPanel.setLayout(new FormLayout(new ColumnSpec[] {
FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
ColumnSpec.decode("125px"),},
new RowSpec[] {
FormFactory.LINE_GAP_ROWSPEC,
RowSpec.decode("23px"),
FormFactory.LINE_GAP_ROWSPEC,
RowSpec.decode("23px"),}));;
JLabel player2Label = new JLabel("Spieler 2");
player2Label.setFont(new Font("SansSerif", Font.BOLD, 12));
MidEastPanel.add(player2Label, "2, 2, center, center");
JLabel player2NameLabel = new JLabel("");
this.player2NameLabel = player2NameLabel;
MidEastPanel.add(player2NameLabel, "2, 4, center, center");
JPanel TitlePanel = new JPanel();
getContentPane().add(TitlePanel, BorderLayout.NORTH);
JLabel TitleLabel = new JLabel("TicTacToe - Die Maschine gewinnt immer!");
TitleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
TitlePanel.add(TitleLabel);
TitleLabel.setFont(new Font("Tahoma", Font.BOLD, 14));
TitleLabel.setHorizontalTextPosition(SwingConstants.CENTER);
JPanel TextPanel = new JPanel();
TextPanel.setBounds(new Rectangle(50, 50, 0, 150));
getContentPane().add(TextPanel, BorderLayout.SOUTH);
JTextArea textArea = new JTextArea(7,46);
textArea.setLineWrap(true);
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
TextPanel.add(scrollPane);
JPanel CenterPanel = new JPanel();
getContentPane().add(CenterPanel, BorderLayout.CENTER);
CenterPanel.setLayout(new BorderLayout(0, 0));
JPanel GameLayoutContainer = new JPanel();
CenterPanel.add(GameLayoutContainer);
GameLayoutContainer.setLayout(new BoxLayout(GameLayoutContainer, BoxLayout.X_AXIS));
JPanel GameAlignPanel = new JPanel();
GameLayoutContainer.add(GameAlignPanel);
GameAlignPanel.setLayout(null);
JPanel GameFieldPanel = new JPanel();
GameFieldPanel.setBounds(50, 67, 172, 172);
GameAlignPanel.add(GameFieldPanel);
JButton button1 = new JButton("1");
button1.setMinimumSize(new Dimension(50, 50));
GameFieldPanel.setLayout(new MigLayout("", "[50px][50px][]", "[50px][][]"));
JButton button2 = new JButton("2");
button2.setMinimumSize(new Dimension(50, 50));
GameFieldPanel.add(button2, "cell 1 0,grow");
GameFieldPanel.add(button1, "cell 0 0,alignx left,aligny top");
JButton button3 = new JButton("3");
button3.setMinimumSize(new Dimension(50, 50));
GameFieldPanel.add(button3, "cell 2 0");
JButton button4 = new JButton("4");
button4.setMinimumSize(new Dimension(50, 50));
GameFieldPanel.add(button4, "cell 0 1");
JButton button5 = new JButton("5");
button5.setMinimumSize(new Dimension(50, 50));
GameFieldPanel.add(button5, "cell 1 1");
JButton button6 = new JButton("6");
button6.setMinimumSize(new Dimension(50, 50));
GameFieldPanel.add(button6, "cell 2 1");
JButton button7 = new JButton("7");
button7.setMinimumSize(new Dimension(50, 50));
GameFieldPanel.add(button7, "cell 0 2");
JButton button8 = new JButton("8");
button8.setMinimumSize(new Dimension(50, 50));
GameFieldPanel.add(button8, "cell 1 2");
JButton button9 = new JButton("9");
button9.setMinimumSize(new Dimension(50, 50));
GameFieldPanel.add(button9, "cell 2 2");
this.buttons[0][0] = button1;
this.buttons[0][1] = button2;
this.buttons[0][2] = button3;
this.buttons[1][0] = button4;
this.buttons[1][1] = button5;
this.buttons[1][2] = button6;
this.buttons[2][0] = button7;
this.buttons[2][1] = button8;
this.buttons[2][2] = button9;
JPanel panel = new JPanel();
panel.setBounds(0, 269, 272, 35);
GameAlignPanel.add(panel);
panel.setLayout(new FormLayout(new ColumnSpec[] {
ColumnSpec.decode("127px"),
FormFactory.RELATED_GAP_COLSPEC,
FormFactory.DEFAULT_COLSPEC,
FormFactory.RELATED_GAP_COLSPEC,
FormFactory.DEFAULT_COLSPEC,},
new RowSpec[] {
RowSpec.decode("28px"),}));
JButton btnNeuesSpiel = new JButton("Neues Spiel");
btnNeuesSpiel.setPreferredSize(new Dimension(127, 28));
panel.add(btnNeuesSpiel, "1, 1, left, top");
btnNeuesSpiel.setFont(new Font("Tahoma", Font.PLAIN, 10));
btnNeuesSpiel.addMouseListener(this);
this.newGameButton = btnNeuesSpiel;
JButton btnSpielWiederholen = new JButton("Spiel wiederholen");
btnSpielWiederholen.setPreferredSize(new Dimension(127, 28));
panel.add(btnSpielWiederholen, "5, 1, left, top");
btnSpielWiederholen.addMouseListener(this);
btnSpielWiederholen.setFont(new Font("Tahoma", Font.PLAIN, 10));
this.repeatGameButton = btnSpielWiederholen;
setName("TicTacToeFrame");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 550, 500);
this.textArea = textArea;
this.scrollPane = scrollPane;
for(int x = 0; x < 3; x++) {
for(int y = 0; y < 3; y++) {
this.buttons[x][y].setText("");
this.buttons[x][y].addMouseListener(this);
this.buttons[x][y].setEnabled(true);
}
}
}
/**
* handles turns based on incoming events.
* @param coords
*/
protected void handleTurn(int[] coords) {
//listen for event, then execute this
if(this.game.isGameOver() == false) {
this.game.getActivePlayer().setNextTurn(coords);
this.game.getActivePlayer().takeTurn(this.game);
this.game.drawField();
this.game.processGame();
}
}
/**
* Uses the given fieldSet to "draw" the current state of the field.
* @param FieldSet fieldSet
*/
public void drawField(FieldSet fieldSet) {
String text = "";
int[][] field = fieldSet.getFieldSet();
for(int x = 0; x < 3; x++) {
for(int y = 0; y < 3; y++) {
text = Integer.toString(field[x][y]);
if(text.equals("0")) text = "";
this.buttons[x][y].setText(text);
}
}
}
/**
* @return int[]
*/
public int[] askPlayerForField() {
return null;
}
/**
* @return String name
*/
public String askPlayerForName() {
return "JPT";
}
/**
* append the text to the textarea and scroll down ;)
*/
public void message(String msg) {
try {
this.textArea.getDocument().insertString(this.textArea.getDocument().getLength(), msg + "\r\n", null);
} catch (BadLocationException e) {
e.printStackTrace();
}
//move the cursor down.
this.textArea.setCaretPosition(this.textArea.getText().length());
}
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
/**
* handle the mouseClick and the turn accordingly :)
*/
public void mouseClicked(MouseEvent arg0) {
Component button = arg0.getComponent();
//if it was one of the 9 buttons, handle it...
for(int x = 0; x < 3; x++) {
for(int y = 0; y < 3; y++) {
if(this.buttons[x][y].equals(button)) {
this.handleTurn(new int[]{x,y});
return;
}
}
}
if(button.equals(this.newGameButton)) {
this.onNewGame();
}
if(button.equals(this.repeatGameButton)) {
this.game.resetGame();
this.game.getView().drawField(this.game.getFieldSet());
this.game.processGame();
}
}
/**
* @param newGameDialog
*/
public void setNewGameDialog(NewGameDialog dialog) {
this.newGameDialog = dialog;
}
/**
* swap the windows - it should be that easy ;)
*/
private void onNewGame() {
this.setVisible(false);
this.newGameDialog.setVisible(true);
}
@Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}

View File

@ -0,0 +1,18 @@
package org.jpt.tictactoe.gui;
import javax.swing.JDialog;
public class Main {
/**
* Code entry point.
* @param args
*/
public static void main(String[] args) {
//show new game window...
NewGameDialog dialog = new NewGameDialog();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
}

View File

@ -0,0 +1,216 @@
package org.jpt.tictactoe.gui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import org.jpt.tictactoe.AbstractPlayer;
import org.jpt.tictactoe.Game;
import org.jpt.tictactoe.Game.PlayerType;
import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;
public class NewGameDialog extends JDialog implements MouseListener {
private static final long serialVersionUID = 1L;
private final JPanel contentPanel = new JPanel();
private JTextField player1Name;
private JTextField player2Name;
protected JTextField player1NameField;
protected JTextField player2NameField;
protected JComboBox player1TypeField;
protected JComboBox player2TypeField;
protected JButton okButton;
protected JButton cancelButton;
/**
* Create the dialog.
*/
public NewGameDialog() {
setTitle("Neues Spiel");
setBounds(100, 100, 450, 185);
getContentPane().setLayout(new BorderLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
contentPanel.setLayout(new BorderLayout(0, 0));
{
JPanel panel = new JPanel();
contentPanel.add(panel, BorderLayout.NORTH);
{
JLabel lblEinNeuesTictactoe = new JLabel("Ein neues TicTacToe beginnen!");
lblEinNeuesTictactoe.setFont(new Font("Tahoma", Font.PLAIN, 14));
panel.add(lblEinNeuesTictactoe);
}
}
{
JPanel panel = new JPanel();
contentPanel.add(panel, BorderLayout.CENTER);
FormLayout fl_panel = new FormLayout(new ColumnSpec[] {
FormFactory.RELATED_GAP_COLSPEC,
FormFactory.DEFAULT_COLSPEC,
FormFactory.RELATED_GAP_COLSPEC,
ColumnSpec.decode("default:grow"),
FormFactory.RELATED_GAP_COLSPEC,
FormFactory.DEFAULT_COLSPEC,
FormFactory.RELATED_GAP_COLSPEC,
ColumnSpec.decode("default:grow"),
FormFactory.RELATED_GAP_COLSPEC,
ColumnSpec.decode("default:grow"),},
new RowSpec[] {
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,
FormFactory.RELATED_GAP_ROWSPEC,
FormFactory.DEFAULT_ROWSPEC,});
panel.setLayout(fl_panel);
{
JLabel lblDeinName = new JLabel("Spieler 1");
panel.add(lblDeinName, "4, 2, right, default");
}
{
JLabel lblSpieler = new JLabel("Spieler 2");
panel.add(lblSpieler, "8, 2");
}
{
JLabel lblName = new JLabel("Name");
panel.add(lblName, "2, 4");
}
{
player1Name = new JTextField();
panel.add(player1Name, "4, 4, fill, fill");
player1Name.setColumns(10);
this.player1NameField = player1Name;
}
{
player2Name = new JTextField();
panel.add(player2Name, "8, 4, fill, default");
player2Name.setColumns(10);
this.player2NameField = player2Name;
}
{
JLabel lblTyp = new JLabel("Spielertyp");
panel.add(lblTyp, "2, 6, right, default");
}
{
JComboBox player1Type = new JComboBox();
player1Type.setModel(new DefaultComboBoxModel(PlayerType.values()));
panel.add(player1Type, "4, 6, fill, default");
this.player1TypeField = player1Type;
}
{
JComboBox player2Type = new JComboBox();
player2Type.setModel(new DefaultComboBoxModel(PlayerType.values()));
panel.add(player2Type, "8, 6, fill, default");
this.player2TypeField = player2Type;
}
}
{
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
JButton okButton = new JButton("Los geht's!");
this.okButton = okButton;
okButton.addMouseListener(this);
okButton.setActionCommand("OK");
buttonPane.add(okButton);
getRootPane().setDefaultButton(okButton);
}
{
JButton cancelButton = new JButton("Ach, doch keine Lust.");
this.cancelButton = cancelButton;
cancelButton.addMouseListener(this);
cancelButton.setActionCommand("Cancel");
buttonPane.add(cancelButton);
}
}
}
private void createNewGame() {
Game game = new Game();
String player1Name = this.player1NameField.getText();
String player2Name = this.player2NameField.getText();
PlayerType player1Type = (PlayerType) this.player1TypeField.getSelectedItem();
PlayerType player2Type = (PlayerType) this.player2TypeField.getSelectedItem();
AbstractPlayer player1 = game.createPlayerByEnum(player1Type, player1Name);
game.addPlayer(player1);
AbstractPlayer player2 = game.createPlayerByEnum(player2Type, player2Name);
game.addPlayer(player2);
//hide the other dialog.
this.setVisible(false);
GuiView guiView = new GuiView();
guiView.player1NameLabel.setText(player1Name);
guiView.player2NameLabel.setText(player2Name);
guiView.setNewGameDialog(this);
guiView.setVisible(true);
guiView.setGame(game);
game.setView(guiView);
game.processGame();
}
/**
* closes the window - exits the application.
*/
private void closeWindow() {
this.dispose();
System.exit(0);
}
public void mouseClicked(MouseEvent arg0) {
Component button = arg0.getComponent();
if(button.equals(this.okButton)) this.createNewGame();
if(button.equals(this.cancelButton)) this.closeWindow();
}
@Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}

View File

@ -0,0 +1,28 @@
package org.jpt.tictactoe.text;
import org.jpt.tictactoe.*;
public class Main {
/**
* Code entry point.
* @param args
*/
public static void main(String[] args) {
Game game = new Game();
AbstractView textView = new TextView();
textView.setGame(game);
game.setView(textView);
game.addPlayer(new HumanPlayer(game.getView().askPlayerForName()));
game.addPlayer(new DumbKi("Steve"));
//listen for event
while(game.isGameOver() == false) {
game.getActivePlayer().setNextTurn(game.getView().askPlayerForField());
game.getActivePlayer().takeTurn(game);
game.drawField();
game.processGame();
}
}
}

View File

@ -0,0 +1,94 @@
package org.jpt.tictactoe.text;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.jpt.tictactoe.*;
public class TextView implements AbstractView{
/**
* Contains the game. I need this to be consistent here.
* It's important for the Gui stuff.
* @var Game
*/
protected Game game;
/**
* @param game
*/
public void setGame(Game game) {
this.game = game;
}
/**
* uses system.out to print the field.
*/
public void drawField(FieldSet fieldSet) {
int[][] fields = fieldSet.getFieldSet();
String output = "";
String eol = "\r\n";
String horizontalLine = "-------------" + eol;
for(int i = 0; i<3; i++) {
output += horizontalLine;
for(int j = 0; j<3; j++) {
output += "| " + Integer.toString(fields[i][j]) + " ";
}
output += "|" + eol;
}
output += horizontalLine;
System.out.println(output);
}
/**
* @return int[] the coordinates.
*/
public int[] askPlayerForField() {
System.out.print("x,y >");
InputStreamReader converter = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(converter);
try {
String result = in.readLine();
String[] splitted = result.split(",");
int x = new Integer(splitted[0]);
int y = new Integer(splitted[1]);
int coords[] = new int[2];
coords[0] = x;
coords[1] = y;
this.message("You entered: " + result.toString());
return coords;
} catch (Exception e) {
this.message("Invalid turn - Please use the following format: [x,y] e.g. 2,1");
return this.askPlayerForField();
}
}
/**
* @return String
*/
public String askPlayerForName() {
System.out.print("Please enter your name: ");
InputStreamReader converter = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(converter);
try {
String result = in.readLine();
return result;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* Outputs the message.
* @param String msg
*/
public void message(String msg) {
System.out.println(msg);
}
}