[Mndiff-dev] [mndiff]: r12 - in trunk/TicTacToe: . IllegalMoveException.java README State.java TicTacToe.java empty.jpg emptyL.jpg o.jpg oL.jpg ttt.htm x.jpg xL.jpg

michael subversion at mplayerhq.hu
Mon May 7 02:30:29 CEST 2007


Author: michael
Date: Mon May  7 02:30:29 2007
New Revision: 12

Log:
This is a little java applet i wrote 8 years ago


Added:
   trunk/TicTacToe/
   trunk/TicTacToe/IllegalMoveException.java
   trunk/TicTacToe/README
   trunk/TicTacToe/State.java
   trunk/TicTacToe/TicTacToe.java
   trunk/TicTacToe/empty.jpg   (contents, props changed)
   trunk/TicTacToe/emptyL.jpg   (contents, props changed)
   trunk/TicTacToe/o.jpg   (contents, props changed)
   trunk/TicTacToe/oL.jpg   (contents, props changed)
   trunk/TicTacToe/ttt.htm
   trunk/TicTacToe/x.jpg   (contents, props changed)
   trunk/TicTacToe/xL.jpg   (contents, props changed)

Added: trunk/TicTacToe/IllegalMoveException.java
==============================================================================
--- (empty file)
+++ trunk/TicTacToe/IllegalMoveException.java	Mon May  7 02:30:29 2007
@@ -0,0 +1,3 @@
+class IllegalMoveException extends Exception
+	{
+	}

Added: trunk/TicTacToe/README
==============================================================================
--- (empty file)
+++ trunk/TicTacToe/README	Mon May  7 02:30:29 2007
@@ -0,0 +1,12 @@
+About:
+This is a little java applet i wrote 8 years ago (1999)
+pictures where generated with povray, sadly ive not found their .pov files
+
+License:
+GPL
+
+Compilation:
+javac *.java
+
+Execution
+open ttt.htm in your favorite browser
\ No newline at end of file

Added: trunk/TicTacToe/State.java
==============================================================================
--- (empty file)
+++ trunk/TicTacToe/State.java	Mon May  7 02:30:29 2007
@@ -0,0 +1,354 @@
+//TicTacToe 1.0 Copyright (c) 1999 Michael Niedermayer
+
+/**
+ * @author Michael Niedermayer
+ */
+class State
+	{
+	private static final int [] POW3= {1, 3, 9, 27, 81, 243, 729, 2187, 6561};
+	private static final boolean DO_RANDOMIZE= true;
+	private static final double EPSILON= 1E-10;
+	private boolean [][] linePosArray= new boolean[3][];
+	protected static final int COMP= TicTacToe.COMP;
+	protected static final int USER= TicTacToe.USER;
+	protected static final int STATES= 19683;
+	protected int current=0;
+	protected int firstPlayer=-1;
+
+	private class Score
+		{
+		int nTies[]= {0,0};
+		int [][] nWins= {{0,0}, {0,0}};
+
+		Score(int iState)
+			{
+
+			if( !isLegal(iState) )
+				{
+				return;
+				}
+
+			int w= getWinner(iState);
+			if( w != -1 )
+				{
+				nWins[w^1][w]= 1;
+				return;
+				}
+			if( isFull(iState) )
+				{
+				nTies[0]= 1;
+				nTies[1]= 1;
+				return;
+				}
+
+			for(int x=0; x<3; x++)
+				{
+				for(int y=0; y<3; y++)
+					{
+					if( get(x, y, iState) != -1) continue;
+					try
+						{
+						int [] m= new int[2];
+						m[0]= set(x, y, iState, 0);
+						m[1]= set(x, y, iState, 1);
+//						System.out.print( m[0] + " " + m[1] + " ");
+						if(score[ m[0] ]==null) score[ m[0] ]= new Score( m[0] );
+						if(score[ m[1] ]==null) score[ m[1] ]= new Score( m[1] );
+//						System.out.print( "n ");
+
+						nTies[USER]   += score[ m[USER] ].nTies[COMP];
+						nWins[USER][0]+= score[ m[USER] ].nWins[COMP][0];
+						nWins[USER][1]+= score[ m[USER] ].nWins[COMP][1];
+						}
+					catch( IllegalMoveException e )
+						{
+						throw new IllegalStateException();
+						}
+					}
+				}
+
+//			System.out.print("is"+iState+ " ");
+			int bestMove= findBestMove(iState);
+			int m;
+			try
+				{
+				m= set(bestMove%3, bestMove/3, iState, COMP);
+				}
+			catch(IllegalMoveException e)
+				{
+				throw new IllegalStateException();
+				}
+				
+
+			nTies[COMP]   += score[ m ].nTies[USER];
+			nWins[COMP][0]+= score[ m ].nWins[USER][0];
+			nWins[COMP][1]+= score[ m ].nWins[USER][1];
+
+
+			}
+
+		}
+	private Score [] score= new Score[STATES];
+
+	State(int firstPlayer)
+		{
+		for(int i=0; i<3; i++)
+			{
+	 		linePosArray[i]= new boolean[3];
+			}
+
+		setFirstPlayer(firstPlayer);
+		score[0]= new Score(0);
+		}
+
+	private boolean isFull(int iState)
+		{
+		boolean b=true;
+
+		for(int x=0; x<3; x++)
+			{
+			for(int y=0; y<3; y++)
+				{
+				if( get(x, y, iState)==-1 ) b= false;
+				}
+			}
+
+		return b;
+		}
+
+	/**
+	 * returns the player+1, who has all three fields on the line (x, y) - (x + dx*2, y + dy*2) 
+	 * and sets the <code>linePosArray</code> to the line, or returns 0.
+	 */
+	private int getWinnerAt(int x, int y, int dx, int dy, int iState)
+		{
+		int winner= 
+			  ( get(x,      y     , iState) + 1 )
+			& ( get(x+dx  , y+dy  , iState) + 1 )
+			& ( get(x+dx*2, y+dy*2, iState) + 1 );
+
+		if(winner!=0 && winner!=3)
+			{
+			linePosArray[x     ][y     ]=
+			linePosArray[x+dx  ][y+dy  ]=
+			linePosArray[x+dx*2][y+dy*2]= true;
+			}
+		return winner;
+		}
+
+	/**
+	 * Gets the player, who has 3 in a line and sets the <code>linePosArray</code> to it.
+	 * @return The winner or -1 if no winner.
+	 * @throws IllegalStateException if multiple winners
+	 */
+	private int getWinner(int iState)
+		{
+		for(int x=0; x<3; x++)
+			{
+			for(int y=0; y<3; y++)
+				{
+				linePosArray[x][y]= false;
+				}
+			}
+
+		int r=
+			( 
+			  getWinnerAt(0, 0, 1, 0, iState)
+			| getWinnerAt(0, 1, 1, 0, iState)
+			| getWinnerAt(0, 2, 1, 0, iState)
+			| getWinnerAt(0, 0, 0, 1, iState)
+			| getWinnerAt(1, 0, 0, 1, iState)
+			| getWinnerAt(2, 0, 0, 1, iState)
+			| getWinnerAt(0, 0, 1, 1, iState)
+			| getWinnerAt(2, 0,-1, 1, iState)
+			) - 1;
+
+		if(r==2) throw( new IllegalStateException() );
+
+		return r;
+		}
+
+	private boolean isLegal(int iState)
+		{
+		int [] n= {0,0};
+
+		for(int x=0; x<3; x++)
+			{
+			for(int y=0; y<3; y++)
+				{
+				int p=get(x, y, iState);
+				if(p != -1) n[p]++;
+				}
+			}
+
+		int diff= n[0] - n[1];
+		if( diff<-1 || diff>1 ) return false;
+		else 					return true;
+		}
+
+	/**
+	 * Gets the player, who is on the Field (x, y), or -1 if the field is empty.
+	 */
+	private int get(int x, int y, int iState)
+		{
+		if(x<0 || x>2) throw new IllegalArgumentException();
+		if(y<0 || y>2) throw new IllegalArgumentException();
+		if(iState<0 || iState>=STATES) throw new IllegalArgumentException();
+		return (iState / POW3[x+y*3] ) % 3 - 1; 
+		}
+
+	/**
+	 * Sets the player for the Field (x, y).
+	 * @throws IllegalMoveException if the field is not empty.
+	 */
+	private int set(int x, int y, int iState, int v)  throws IllegalMoveException
+		{
+		v++;
+		if(x<0 || x>2) throw new IllegalArgumentException();
+		if(y<0 || y>2) throw new IllegalArgumentException();
+		if(v<1 || v>2) throw new IllegalArgumentException();
+		if(iState<0 || iState>=STATES) throw new IllegalArgumentException();
+
+		if( get(x, y, iState)!=-1 ) throw new IllegalMoveException();
+		
+		int p= POW3[x+y*3];
+		return iState - (get(x, y, iState) + 1) * p + v*p;
+		}
+
+	/**
+	 * Finds the Best Move for the Computer.
+	 * @return x + y*3
+	 * @throws IllegalArgumentException if no empty field left.
+	 */
+	private int findBestMove(int iState)
+		{
+		double bestQ= Double.NEGATIVE_INFINITY;
+		int bestX=-1, bestY=-1;
+
+		for(int x=0; x<3; x++)
+			{
+			for(int y=0; y<3; y++)
+				{
+				if( get(x,y, iState)!=-1 ) continue;
+				int m=0;
+				try
+					{
+					m=set(x, y, iState, COMP);
+					}
+				catch(IllegalMoveException e)
+					{
+					throw new IllegalStateException();
+					}
+
+				double q;
+
+				if(score[m].nWins[ USER ][ USER ] > 0)	
+					{
+					q=    (double)( -score[m].nWins[ USER ][ USER ] )
+						/ (double)(	  score[m].nTies[ USER ] 
+									+ score[m].nWins[ USER ][ COMP ] + EPSILON);
+					}
+				else 
+					{
+					q=    (double)(score[m].nWins[ USER ][ COMP ])
+						/ (double)(score[m].nTies[ USER ] + EPSILON);
+					}
+
+				if(DO_RANDOMIZE)
+					{
+						 if(q <= -0.9/EPSILON) q= -1.0/EPSILON;
+					else if(q <   0.0        ) q= -1.0;
+					else if(q <   0.9/EPSILON) q=  1.0;
+					else 					   q=  1.0/EPSILON;
+
+					q*= 1 + Math.random();
+					}
+
+				if(q>=bestQ)
+					{
+					bestQ= q;
+					bestX= x;
+					bestY= y;
+					}
+				}
+			}
+
+		if(bestX<0) throw new IllegalArgumentException( "No empty field left" );
+		return bestX + bestY*3;
+		}
+
+	/**
+	 * Gets the line on which one player has all three fields.
+	 */
+	public boolean [][] getLine()
+		{
+		getWinner(current);
+		return linePosArray;
+		}
+
+	public void makeEmpty()
+		{
+		current=0;
+		}
+
+	public boolean isEnd() 
+		{
+		if( !isLegal(current) ) throw new IllegalStateException();
+
+		if( isFull(current) ) return true;
+		if( getWinner(current) != -1 ) return true;
+
+		return false;
+		}
+
+	/**
+	 * Gets the player, who is currently on the Field (x, y), or -1 if the field is empty.
+	 */
+	public int get(int x, int y)
+		{
+		return get(x, y, current);
+		}
+
+	/**
+	 * Sets the player for the Field (x, y).
+	 * @throws IllegalMoveException if the field is not empty.
+	 */
+	public void set(int x, int y, int v) throws IllegalMoveException
+		{
+		current= set(x, y, current, v);
+		}
+
+	public int getNTie(int nextPlayer)
+		{
+		return score[current].nTies[ nextPlayer ];
+		}
+
+	public int getNCOMPWin(int nextPlayer)
+		{
+		return score[current].nWins[ nextPlayer ][COMP];
+		}
+
+	public void makeMove()
+		{
+		int best= findBestMove(current);
+		try
+			{
+			set(best%3, best/3, COMP);
+			}
+		catch(IllegalMoveException e)
+			{
+			throw new IllegalStateException();
+			}
+/*
+		System.out.print(	  score[current].nTies[USER]+ " "
+							+ score[current].nWins[USER][USER]+ " "
+							+ score[current].nWins[USER][COMP]+ "\n");
+*/
+		}
+
+	public void setFirstPlayer(int firstPlayer)
+		{
+		this.firstPlayer= firstPlayer;
+		}
+
+	}

Added: trunk/TicTacToe/TicTacToe.java
==============================================================================
--- (empty file)
+++ trunk/TicTacToe/TicTacToe.java	Mon May  7 02:30:29 2007
@@ -0,0 +1,151 @@
+//TicTacToe 1.0 Copyright (c) 1999 Michael Niedermayer
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * @author Michael Niedermayer
+ */
+public class TicTacToe extends JApplet implements ActionListener, KeyListener
+	{
+	protected static final int COMP=0;
+	protected static final int USER=1;
+	private int mouseX=-1, mouseY=-1;
+	protected JButton [][] aJButton= new JButton[3][];
+	protected ImageIcon [] icon= new ImageIcon[6];
+	protected int firstPlayer= 1;
+	protected State state= new State( firstPlayer );
+
+	private void initPicsFromState()
+		{
+		boolean [][] line= state.getLine();
+		for(int x=0; x<3; x++)
+			{
+			for(int y=0; y<3; y++)
+				{
+				int s= state.get(x, y) + 1;
+
+				aJButton[x][y].setRolloverIcon(icon[s+3]);
+//				aJButton[x][y].setSelectedIcon(icon[s+3]);
+
+				if(line[x][y])
+					{
+					aJButton[x][y].setIcon(icon[s+3]);
+					}
+				else
+					{
+					aJButton[x][y].setIcon(icon[s]);
+					}
+				}
+			}
+		}
+
+	public void init() 
+		{
+		try
+			{
+			icon[0]= new ImageIcon( new URL( getCodeBase(), "empty.jpg"	) );
+		 	icon[1]= new ImageIcon( new URL( getCodeBase(), "x.jpg"		) ); 
+			icon[2]= new ImageIcon( new URL( getCodeBase(), "o.jpg"		) );
+	  		icon[3]= new ImageIcon( new URL( getCodeBase(), "emptyL.jpg"	) );
+			icon[4]= new ImageIcon( new URL( getCodeBase(), "xL.jpg"		) );     
+			icon[5]= new ImageIcon( new URL( getCodeBase(), "oL.jpg"		) );
+			}
+		catch( MalformedURLException e)
+			{
+			System.err.println("Cant load Image " + e.getMessage());
+			System.exit(1);
+			}
+
+		Container cp= getContentPane();
+
+		cp.setLayout( new GridLayout(3, 3) );
+
+		for(int x=0; x<3; x++)
+			{
+			aJButton[x]= new JButton[3];
+			}
+
+		for(int y=0; y<3; y++)
+			{
+			for(int x=0; x<3; x++)
+				{
+				JButton jb= new JButton(icon[0]);
+				aJButton[x][y]= jb;
+				jb.setBorder( BorderFactory.createRaisedBevelBorder() );
+				jb.setRolloverEnabled(true);
+				cp.add(jb);
+
+				jb.putClientProperty("xPos", new Integer(x));
+				jb.putClientProperty("yPos", new Integer(y));
+				jb.addActionListener(this);
+				jb.addKeyListener(this);
+				}
+			}
+
+		aJButton[1][1].requestFocus();
+		initPicsFromState();
+		}
+
+	public void actionPerformed(ActionEvent e)
+		{
+		JButton jButton= (JButton)e.getSource();
+
+		int x= ((Integer)jButton.getClientProperty("xPos")).intValue();
+		int y= ((Integer)jButton.getClientProperty("yPos")).intValue();
+
+		if(state.isEnd())
+			{
+		 	state.makeEmpty();
+
+			firstPlayer^= 1;
+			state.setFirstPlayer(firstPlayer);
+
+			if(firstPlayer==COMP)
+				state.makeMove();
+			}
+		else
+			{
+			try
+				{
+				state.set(x, y, USER);
+				}
+			catch(IllegalMoveException e2)
+				{
+				return;
+				}
+			if(!state.isEnd())
+				state.makeMove();
+			}
+
+		initPicsFromState();
+		}
+	public void keyTyped(KeyEvent e){}
+	public void keyPressed(KeyEvent e)
+		{
+		JButton jButton= (JButton)e.getSource();
+
+		int x= ((Integer)jButton.getClientProperty("xPos")).intValue();
+		int y= ((Integer)jButton.getClientProperty("yPos")).intValue();
+
+		if(e.getKeyCode() == e.VK_LEFT) x--;
+		if(e.getKeyCode() == e.VK_RIGHT) x++;
+		if(e.getKeyCode() == e.VK_DOWN) y++;
+		if(e.getKeyCode() == e.VK_UP) y--;
+
+		x+=3;
+		y+=3;
+		x%=3;
+		y%=3;
+
+		aJButton[x][y].requestFocus();
+		}
+	public void keyReleased(KeyEvent e){}
+	public String getAppletInfo()
+		{
+		return "TicTacToe 1.0 Copyright (c) 1999 Michael Niedermayer\n";
+		}
+	}

Added: trunk/TicTacToe/empty.jpg
==============================================================================
Binary file. No diff available.

Added: trunk/TicTacToe/emptyL.jpg
==============================================================================
Binary file. No diff available.

Added: trunk/TicTacToe/o.jpg
==============================================================================
Binary file. No diff available.

Added: trunk/TicTacToe/oL.jpg
==============================================================================
Binary file. No diff available.

Added: trunk/TicTacToe/ttt.htm
==============================================================================
--- (empty file)
+++ trunk/TicTacToe/ttt.htm	Mon May  7 02:30:29 2007
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+
+<HTML>
+
+<HEAD>
+<TITLE>TicTacToe</TITLE>
+<META NAME="GENERATOR" CONTENT="Arachnophilia 3.9">
+<META NAME="FORMATTER" CONTENT="Arachnophilia 3.9">
+</HEAD>
+
+<BODY style="text-align: center">
+
+        <APPLET code="TicTacToe.class" width=320 height=320>
+	</APPLET>
+
+</BODY>
+
+</HTML>

Added: trunk/TicTacToe/x.jpg
==============================================================================
Binary file. No diff available.

Added: trunk/TicTacToe/xL.jpg
==============================================================================
Binary file. No diff available.



More information about the Mndiff-dev mailing list