AI Based Tic Tac Toe (Java Code) - CodeProject
AI Based Tic Tac Toe (Java Code) - CodeProject
AIbasedTicTacToe(javacode)CodeProject
12,309,265
members
58,870
online
Sign up for
our free
weekly
Web Developer Newsletter.
articles
Q&A
forums
lounge
Sign in
Searchforarticles,questions,tips
CPOL
Rate this:
5.00 12 votes
Java Tic Tac Toe AI based
Introduction
This project was originally developed by Mohd Akram. This project is a simple demonstration of the power of AI. The friendly
language will help you easily understand the code. Hope that after reading this post you might be more interested in AI than
before and would develop much better applications.
1/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
file : TicTacToe.java
class : TicTacToe
global variables :
winComb int[][] : all winning situations
state int[][] : Current state of the Game
pl1 Player : Player 1 object Computer / Human
pl2 Player : Player 2 object Computer / Human
butClicked int : Buttton recently clicked by the user
w1 int : Number of games won by Player1X
w2 int : Number of games won by Player1O
dr int : Number of game draws
Methods :
public TicTacToe
public void start
public void refreshGrid
public static int checkWinint turn,int[][] st
public static int checkWin2String x,String o
public void printString s
public void gameInit
private void initComponents
file : Player.java
class : Player abstract
global variables : none
Methods :
void playTurnint pl,int turn
void playerInit
void notifyWinint pl
void notifyLoseint pl
file : Human.java
class : Human extends Player
global variables : none
Mathods :
void playTurnint pl,int turn // overriden
file : Computer.java
class : Computer extends Player
global Variables :
t int Turn number
begin Node top element of the state tree
current Node Current Node of state tree
layerFiles File[] Layer Files from layer1 ...... layer 9
layers ArrayList<Layer> layers of memory tree
Methods :
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
2/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
public ComputerString l
public void evaluate
public void loadMind
public void saveMind
public void makeNewMind
public void playTurnint p,int turn // overriden
void notifyWinint pl // overriden
void notifyLoseint pl // overriden
file : Node.java
class : Node
global variables :
sub_nodes ArrayList<Node> connections of this node to its subNodes
subNodes String Temporary storing id's of subNodes separated by " , "
id String id of Current Node
pref int Preference value of current Node
n int No. of times this node is played
lNum int The layer number in which this node exists in the memory tree
comp Computer The Computer object this node belongs to
nodeType int Stores whether this node is end node or not
Methods :
public NodeString i,int l,Computer c
public void setAsState
public void playNext1
public void playNext2
public void playNextn
public void extractNodes
file : Layer.java
class : Layer
global Variables :
nodes ArrayList<Node> Stores reference to the Nodes in that Layer
layerNum int Stores Layer Number19
Methods :
public void refreshLayer
public Node searchByStateint[][] state
public Node searchByIdString id
DESCRIPTION....
<script type="text/javascript"> var infolinks_pid = 2110076; var infolinks_wsid = 0; </script> <script type="text/javascript"
src="http://resources.infolinks.com/js/infolinks_main.js"></script>
The model of the game can be summarized as follows ....
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
3/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
The Game follows a very easy method of getting the most probable next chance .... the method of finding the favourable state
is explained later.
The GUI of the game is made with netbeans Form maker.
The Display
The display part contains a 9x9 grid of jButtons.The text on top of these shows the block status.There is also a notification bar
at the bottom of the jFrame. The bare at the right side of the jFrame shows three status : Number of games won by either
player and Number of Draws.
4/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
This is the interface between the human and the game . When the playTurn method is callled , it waits until the user presses
one of the button from the 9x9 grid. The static variable butPressed gives the recently pressed button and this inforation is used
by the player Human class to fill a cell with 'x' or 'o' depending on the player turn Number. If it's an even No the object fills 'o'
in the required cell otherwise it fills 'a' by setting the state variable of the Main class which updates the display after receiving a
new state.
The notifyWin and notifyLose have nothing to do with the Human class hence are empty.
The method to fill a block by a Human Player is ....
for(inti=0;i<9;i++)
{
layerFiles[i]=newFile(l+(i+1)+".nodes");
if(!layerFiles[i].exists())
{
try{
layerFiles[i].createNewFile();
}
catch(Exceptione)
{
System.out.println(e);
}
}
}
//loadMind();
makeNewMind();evaluate();saveMind();
begin.subNodes="100000000,010000000,001000000,000100000,000010000,000001000,000000100,000000010,0000
00001,";
begin.extractNodes();
The computer object is provided with a file path to the Layer Files which contain list of all the Nodes. There are nine layer files.
If the layer files do not exist the computer makes new layer Files. Then Comes the part where the computer memory is created.
The makeNewMind method creates new Nodes or possible states of the Game without the layer Files and stores them in layer
objects. Then it evalutes the Winning and Losing Situations by and updates their preference values by 100 and 100
respectively. The saveMind method saves the layers date i.e. the Nodes data into layer Files. These Layer Files can be used to
retain the memory of the game after the game exists. The existing Mind Files can be loaded by loadMind method.
The computer object is provided with a file path to the Layer Files which contain list of all the Nodes. There are nine layer files.
If the layer files do not exist the computer makes new layer Files. Then Comes the part where the computer memory is created.
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
5/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
The makeNewMind method creates new Nodes or possible states of the Game without the layer Files and stores them in layer
objects. Then it evalutes the Winning and Losing Situations by and updates their preference values by 100 and 100
respectively. The saveMind method saves the layers date i.e. the Nodes data into layer Files. These Layer Files can be used to
retain the memory of the game after the game exists. The existing Mind Files can be loaded by loadMind method.
The Node "begin" is the first node of the Game i.e. blank node.It is then manually connected to its possible subNodes by
setting the variable subNodes and then calling extractNodes.
Copy Code
publicvoidplayNext1(){
ArrayList<Node>temp=newArrayList<Node>();
//System.out.println(id+":"+sub_nodes.size());
longmax=sub_nodes.get(0).pref;
for(inti=0;i<sub_nodes.size();i++)
{
if(sub_nodes.get(i).pref>max)
{
temp.clear();
temp.add(sub_nodes.get(i));
max=sub_nodes.get(i).pref;
}
elseif(sub_nodes.get(i).pref==max)
{
temp.add(sub_nodes.get(i));
}
}
intchoice=(int)(Math.random()*temp.size());
temp.get(choice).n++;
temp.get(choice).setAsState();
}
publicvoidplayNext2(){
ArrayList<Node>temp=newArrayList<Node>();
//System.out.println(id+":"+sub_nodes.size());
longmin=sub_nodes.get(0).pref;
for(inti=0;i<sub_nodes.size();i++)
{
if(sub_nodes.get(i).pref<min)
{
temp.clear();
temp.add(sub_nodes.get(i));
min=sub_nodes.get(i).pref;
}
elseif(sub_nodes.get(i).pref==min)
{
temp.add(sub_nodes.get(i));
}
}
intchoice=(int)(Math.random()*temp.size());
temp.get(choice).n++;
temp.get(choice).setAsState();
}
publicvoidplayNextn(){
ArrayList<Node>temp=newArrayList<Node>();
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
6/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
//System.out.println(id+":"+sub_nodes.size());
intchoice=0;
longmin=sub_nodes.get(0).n;
for(inti=0;i<sub_nodes.size();i++)
{
if(sub_nodes.get(i).n<min)
{
min=sub_nodes.get(i).n;
choice=i;
}
}
sub_nodes.get(choice).n++;
sub_nodes.get(choice).setAsState();
}
The playnext1 method prepares a list of all the Nodes having maximum preferences and then plays one of them. The
PlayNextn method plays the turn which is played least no of times thus not leaving any stone unturned. This method is useful
when doing the evaluation process.
Method of finding preference :
The computer finds the preference f a node by adding the preferences of all its subNodes. This way the node having no
chances of winning in the nextTurn hence having no positive value in its subNodes will have very less value of its own . This way
the computer will go away from this node and thus will go toward a winning situation.
The Computer class does the job of finding the prefernces of all the nodes except the repfernce of the beginning nodei.e. the
blank node.
On getting a win or lose state the Computer is notified and thus the computer decreases the preference of the current node by
10 if its a losing notification and if its a winning notification the computer increases the value of the currrent node by 10. This
way upon playing many times by the playNextn method we will get a clear map of the preferred and not unfavoured sates
and what path to take in order to reach a highly favoured winning state. When playing against a human it's better to use the
PlayNext1 method to play the turn because it makes best use of what it learned from previous games.
Files :
TicTacToe.java
Hide Shrink
Copy Code
importjava.util.logging.Level;
importjava.util.logging.Logger;
publicclassTicTacToeextendsjavax.swing.JFrame{
staticintwinComb[][]={{1,2,3},{4,5,6},{7,8,9},{1,4,7},{2,5,8},{3,6,9},{1,5,9},{3,5,7}};
publicstaticint[][]state={{0,0,0},{0,0,0},{0,0,0}};
Playerpl1=newHuman();
Playerpl2=newComputer("mind\\layer");
publicstaticintbutClicked=0;
intw1=0,w2=0,dr=0;
publicTicTacToe(){
initComponents();
}
publicvoidstart(){
if(w1==500)System.exit(0);
intcurrent=1,turn=1;
intw=0;
while((w=checkWin(turn,state))==0)
{
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
7/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
if(current==1)
{
pl1.playTurn(1,turn);
refreshGrid();
current=2;
}
elseif(current==2)
{
pl2.playTurn(2,turn);
refreshGrid();
current=1;
}
turn++;
try{Thread.sleep(0);}catch(InterruptedExceptionex)
{Logger.getLogger(TicTacToe.class.getName()).log(Level.SEVERE,null,ex);}
}
if(w==1)
{
pl1.notifyWin(1);
pl2.notifyLose(2);
print("Player1WonTheGame!");
w1++;
}
elseif(w==2)
{
pl2.notifyWin(1);
pl1.notifyLose(2);
print("Player2WonTheGame!");
w2++;
}
elseif(w==1)
{
print("GameDRAW!");
dr++;
}
try{Thread.sleep(0);}catch(InterruptedExceptionex)
{Logger.getLogger(TicTacToe.class.getName()).log(Level.SEVERE,null,ex);}
}
publicvoidrefreshGrid(){
b11.setText(state[0][0]==1?"X":(state[0][0]==2?"O":""));
b12.setText(state[0][1]==1?"X":(state[0][1]==2?"O":""));
b13.setText(state[0][2]==1?"X":(state[0][2]==2?"O":""));
b21.setText(state[1][0]==1?"X":(state[1][0]==2?"O":""));
b22.setText(state[1][1]==1?"X":(state[1][1]==2?"O":""));
b23.setText(state[1][2]==1?"X":(state[1][2]==2?"O":""));
b31.setText(state[2][0]==1?"X":(state[2][0]==2?"O":""));
b32.setText(state[2][1]==1?"X":(state[2][1]==2?"O":""));
b33.setText(state[2][2]==1?"X":(state[2][2]==2?"O":""));
jLabel1.setText("Xwins:"+w1);
jLabel2.setText("Owins:"+w2);
jLabel3.setText("Draws:"+dr);
}
publicstaticintcheckWin(intturn,int[][]st){
intret=0;
Stringx="";
Stringo="";
inti=0,j=0,c=0,p,q;
for(p=0;p<3;p++)
{
for(q=0;q<3;q++)
{
c++;
if(st[p][q]==1)
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
8/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
{
x+=c;
}
elseif(st[p][q]==2)
{
o+=c;
}
}
}
//print(x+":"+o);
ret=checkWin2(x,o);
if(turn==10&&ret==0)
{
ret=1;
}
returnret;
}
publicstaticintcheckWin2(Stringx,Stringo){
intret=0;
intp;
for(p=0;p<8;p++)
{
if(x.indexOf((char)winComb[p][0]+'0')>1&&x.indexOf((char)winComb[p][1]+'0')>1&&
x.indexOf((char)winComb[p][2]+'0')>1)
{
ret=1;
break;
}
if(o.indexOf((char)winComb[p][0]+'0')>1&&o.indexOf((char)winComb[p][1]+'0')>1&&
o.indexOf((char)winComb[p][2]+'0')>1)
{
ret=2;
break;
}
}
returnret;
}
publicvoidprint(Strings){
Notification.setText("\t"+s);
}
publicvoidgameInit(){
state[0][0]=0;
state[0][1]=0;
state[0][2]=0;
state[1][0]=0;
state[1][1]=0;
state[1][2]=0;
state[2][0]=0;
state[2][1]=0;
state[2][2]=0;
refreshGrid();
}
@SuppressWarnings("unchecked")
//<editorfolddefaultstate="collapsed"desc="GeneratedCode">//GENBEGIN:initComponents
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
9/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
privatevoidinitComponents(){
try{
jPanel1=(javax.swing.JPanel)java.beans.Beans.instantiate(getClass().getClassLoader(),
"TicTacToe_jPanel1");
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}catch(java.io.IOExceptione){
e.printStackTrace();
}
b21=newjavax.swing.JButton();
b11=newjavax.swing.JButton();
b22=newjavax.swing.JButton();
b12=newjavax.swing.JButton();
b13=newjavax.swing.JButton();
b23=newjavax.swing.JButton();
b31=newjavax.swing.JButton();
b32=newjavax.swing.JButton();
b33=newjavax.swing.JButton();
Notification=newjavax.swing.JLabel();
jPanel2=newjavax.swing.JPanel();
jLabel1=newjavax.swing.JLabel();
jLabel2=newjavax.swing.JLabel();
jLabel3=newjavax.swing.JLabel();
jLabel4=newjavax.swing.JLabel();
jLabel5=newjavax.swing.JLabel();
jLabel6=newjavax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setAlwaysOnTop(true);
setPreferredSize(newjava.awt.Dimension(600,400));
b21.setBackground(newjava.awt.Color(255,255,255));
b21.setFont(newjava.awt.Font("Arial",1,48));//NOI18N
b21.setCursor(newjava.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
b21.addActionListener(newjava.awt.event.ActionListener(){
publicvoidactionPerformed(java.awt.event.ActionEventevt){
b21ActionPerformed(evt);
}
});
b11.setBackground(newjava.awt.Color(255,255,255));
b11.setFont(newjava.awt.Font("Arial",1,48));//NOI18N
b11.setCursor(newjava.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
b11.addActionListener(newjava.awt.event.ActionListener(){
publicvoidactionPerformed(java.awt.event.ActionEventevt){
b11ActionPerformed(evt);
}
});
b22.setBackground(newjava.awt.Color(255,255,255));
b22.setFont(newjava.awt.Font("Arial",1,48));//NOI18N
b22.setCursor(newjava.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
b22.addActionListener(newjava.awt.event.ActionListener(){
publicvoidactionPerformed(java.awt.event.ActionEventevt){
b22ActionPerformed(evt);
}
});
b12.setBackground(newjava.awt.Color(255,255,255));
b12.setFont(newjava.awt.Font("Arial",1,48));//NOI18N
b12.setCursor(newjava.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
b12.addActionListener(newjava.awt.event.ActionListener(){
publicvoidactionPerformed(java.awt.event.ActionEventevt){
b12ActionPerformed(evt);
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
10/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
}
});
b13.setBackground(newjava.awt.Color(255,255,255));
b13.setFont(newjava.awt.Font("Arial",1,48));//NOI18N
b13.setCursor(newjava.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
b13.addActionListener(newjava.awt.event.ActionListener(){
publicvoidactionPerformed(java.awt.event.ActionEventevt){
b13ActionPerformed(evt);
}
});
b23.setBackground(newjava.awt.Color(255,255,255));
b23.setFont(newjava.awt.Font("Arial",1,48));//NOI18N
b23.setCursor(newjava.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
b23.addActionListener(newjava.awt.event.ActionListener(){
publicvoidactionPerformed(java.awt.event.ActionEventevt){
b23ActionPerformed(evt);
}
});
b31.setBackground(newjava.awt.Color(255,255,255));
b31.setFont(newjava.awt.Font("Arial",1,48));//NOI18N
b31.setCursor(newjava.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
b31.addActionListener(newjava.awt.event.ActionListener(){
publicvoidactionPerformed(java.awt.event.ActionEventevt){
b31ActionPerformed(evt);
}
});
b32.setBackground(newjava.awt.Color(255,255,255));
b32.setFont(newjava.awt.Font("Arial",1,48));//NOI18N
b32.setCursor(newjava.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
b32.addActionListener(newjava.awt.event.ActionListener(){
publicvoidactionPerformed(java.awt.event.ActionEventevt){
b32ActionPerformed(evt);
}
});
b33.setBackground(newjava.awt.Color(255,255,255));
b33.setFont(newjava.awt.Font("Arial",1,48));//NOI18N
b33.setCursor(newjava.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
b33.addActionListener(newjava.awt.event.ActionListener(){
publicvoidactionPerformed(java.awt.event.ActionEventevt){
b33ActionPerformed(evt);
}
});
Notification.setBackground(newjava.awt.Color(255,255,0));
Notification.setFont(newjava.awt.Font("Tahoma",0,18));//NOI18N
Notification.setForeground(newjava.awt.Color(0,0,102));
Notification.setText("TicTacToe");
Notification.setBorder(newjavax.swing.border.MatteBorder(null));
jLabel1.setFont(newjava.awt.Font("Arial",0,18));//NOI18N
jLabel1.setBorder(javax.swing.BorderFactory.createLineBorder(newjava.awt.Color(0,0,0)));
jLabel2.setFont(newjava.awt.Font("Arial",0,18));//NOI18N
jLabel2.setBorder(javax.swing.BorderFactory.createLineBorder(newjava.awt.Color(0,0,0)));
jLabel3.setFont(newjava.awt.Font("Arial",0,18));//NOI18N
jLabel3.setBorder(javax.swing.BorderFactory.createLineBorder(newjava.awt.Color(0,0,0)));
jLabel4.setFont(newjava.awt.Font("Arial",0,18));//NOI18N
jLabel4.setBorder(javax.swing.BorderFactory.createLineBorder(newjava.awt.Color(0,0,0)));
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
11/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
jLabel5.setFont(newjava.awt.Font("Arial",0,18));//NOI18N
jLabel5.setBorder(javax.swing.BorderFactory.createLineBorder(newjava.awt.Color(0,0,0)));
jLabel6.setFont(newjava.awt.Font("Arial",0,18));//NOI18N
jLabel6.setBorder(javax.swing.BorderFactory.createLineBorder(newjava.awt.Color(0,0,0)));
javax.swing.GroupLayoutjPanel2Layout=newjavax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1,javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,Short.MAX_VALUE)
.addComponent(jLabel2,javax.swing.GroupLayout.DEFAULT_SIZE,203,
Short.MAX_VALUE)
.addComponent(jLabel3,javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,Short.MAX_VALUE)
.addComponent(jLabel4,javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,Short.MAX_VALUE)
.addComponent(jLabel5,javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,Short.MAX_VALUE)
.addComponent(jLabel6,javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,Short.MAX_VALUE))
.addContainerGap())
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1,javax.swing.GroupLayout.PREFERRED_SIZE,40,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel2,javax.swing.GroupLayout.PREFERRED_SIZE,40,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel3,javax.swing.GroupLayout.PREFERRED_SIZE,40,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel4,javax.swing.GroupLayout.PREFERRED_SIZE,40,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel5,javax.swing.GroupLayout.PREFERRED_SIZE,40,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel6,javax.swing.GroupLayout.PREFERRED_SIZE,40,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE,Short.MAX_VALUE))
);
jLabel1.getAccessibleContext().setAccessibleName("l1");
jLabel1.getAccessibleContext().setAccessibleDescription("");
javax.swing.GroupLayoutjPanel1Layout=newjavax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(Notification,javax.swing.GroupLayout.DEFAULT_SIZE,
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
12/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
javax.swing.GroupLayout.DEFAULT_SIZE,Short.MAX_VALUE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(b21,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(b11,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(b22,javax.swing.GroupLayout.PREFERRED_SIZE,
100,javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(b23,javax.swing.GroupLayout.PREFERRED_SIZE,
100,javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(b12,javax.swing.GroupLayout.PREFERRED_SIZE,
100,javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(b13,javax.swing.GroupLayout.PREFERRED_SIZE,
100,javax.swing.GroupLayout.PREFERRED_SIZE))))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(b31,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(b32,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(b33,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel2,javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,Short.MAX_VALUE)))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING,false)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(b12,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(b13,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(b11,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(b22,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(b21,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(b23,javax.swing.GroupLayout.PREFERRED_SIZE,100,
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
13/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(b32,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(b31,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(b33,javax.swing.GroupLayout.PREFERRED_SIZE,100,
javax.swing.GroupLayout.PREFERRED_SIZE)))
.addComponent(jPanel2,javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(Notification,javax.swing.GroupLayout.DEFAULT_SIZE,40,
Short.MAX_VALUE)
.addContainerGap())
);
javax.swing.GroupLayoutlayout=newjavax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel1,javax.swing.GroupLayout.PREFERRED_SIZE,561,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0,0,Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1,javax.swing.GroupLayout.DEFAULT_SIZE,385,Short.MAX_VALUE)
);
pack();
}//</editorfold>//GENEND:initComponents
privatevoidb33ActionPerformed(java.awt.event.ActionEventevt){//GEN
FIRST:event_b33ActionPerformed
if(state[2][2]==0)
butClicked=9;
}//GENLAST:event_b33ActionPerformed
privatevoidb32ActionPerformed(java.awt.event.ActionEventevt){//GEN
FIRST:event_b32ActionPerformed
if(state[2][1]==0)
butClicked=8;
}//GENLAST:event_b32ActionPerformed
privatevoidb31ActionPerformed(java.awt.event.ActionEventevt){//GEN
FIRST:event_b31ActionPerformed
if(state[2][0]==0)
butClicked=7;
}//GENLAST:event_b31ActionPerformed
privatevoidb23ActionPerformed(java.awt.event.ActionEventevt){//GEN
FIRST:event_b23ActionPerformed
if(state[1][2]==0)
butClicked=6;
}//GENLAST:event_b23ActionPerformed
privatevoidb13ActionPerformed(java.awt.event.ActionEventevt){//GEN
FIRST:event_b13ActionPerformed
if(state[0][2]==0)
butClicked=3;
}//GENLAST:event_b13ActionPerformed
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
14/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
privatevoidb12ActionPerformed(java.awt.event.ActionEventevt){//GEN
FIRST:event_b12ActionPerformed
if(state[0][1]==0)
butClicked=2;
}//GENLAST:event_b12ActionPerformed
privatevoidb22ActionPerformed(java.awt.event.ActionEventevt){//GEN
FIRST:event_b22ActionPerformed
if(state[1][1]==0)
butClicked=5;
}//GENLAST:event_b22ActionPerformed
privatevoidb11ActionPerformed(java.awt.event.ActionEventevt){//GEN
FIRST:event_b11ActionPerformed
if(state[0][0]==0)
butClicked=1;
}//GENLAST:event_b11ActionPerformed
privatevoidb21ActionPerformed(java.awt.event.ActionEventevt){//GEN
FIRST:event_b21ActionPerformed
if(state[1][0]==0)
butClicked=4;
}//GENLAST:event_b21ActionPerformed
publicstaticvoidmain(Stringargs[]){
/*SettheNimbuslookandfeel*/
//<editorfolddefaultstate="collapsed"desc="Lookandfeelsettingcode(optional)">
/*IfNimbus(introducedinJavaSE6)isnotavailable,staywiththedefaultlookand
feel.
*Fordetailsseehttp://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try{
for(javax.swing.UIManager.LookAndFeelInfoinfo:
javax.swing.UIManager.getInstalledLookAndFeels()){
if("Nimbus".equals(info.getName())){
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}catch(ClassNotFoundExceptionex){
java.util.logging.Logger.getLogger(TicTacToe.class.getName()).log(java.util.logging.Level.SEVERE,
null,ex);
}catch(InstantiationExceptionex){
java.util.logging.Logger.getLogger(TicTacToe.class.getName()).log(java.util.logging.Level.SEVERE,
null,ex);
}catch(IllegalAccessExceptionex){
java.util.logging.Logger.getLogger(TicTacToe.class.getName()).log(java.util.logging.Level.SEVERE,
null,ex);
}catch(javax.swing.UnsupportedLookAndFeelExceptionex){
java.util.logging.Logger.getLogger(TicTacToe.class.getName()).log(java.util.logging.Level.SEVERE,
null,ex);
}
//</editorfold>
TicTacToet=newTicTacToe();
t.setVisible(true);
while(true)
{
t.start();
t.gameInit();
}
}
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
15/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
//Variablesdeclarationdonotmodify//GENBEGIN:variables
privatejavax.swing.JLabelNotification;
publicstaticjavax.swing.JButtonb11;
publicstaticjavax.swing.JButtonb12;
publicstaticjavax.swing.JButtonb13;
publicstaticjavax.swing.JButtonb21;
publicstaticjavax.swing.JButtonb22;
publicstaticjavax.swing.JButtonb23;
publicstaticjavax.swing.JButtonb31;
publicstaticjavax.swing.JButtonb32;
publicstaticjavax.swing.JButtonb33;
privatejavax.swing.JLabeljLabel1;
privatejavax.swing.JLabeljLabel2;
privatejavax.swing.JLabeljLabel3;
privatejavax.swing.JLabeljLabel4;
privatejavax.swing.JLabeljLabel5;
privatejavax.swing.JLabeljLabel6;
privatejavax.swing.JPaneljPanel1;
privatejavax.swing.JPaneljPanel2;
//Endofvariablesdeclaration//GENEND:variables
}
Player.java
Hide Copy Code
publicabstractclassPlayer{
voidplayTurn(intpl,intturn){}
voidplayerInit(){}
voidnotifyWin(intpl){}
voidnotifyLose(intpl){}
}
Human.java
Hide Copy Code
publicclassHumanextendsPlayer{
@Override
voidplayTurn(intpl,intturn){
while(TicTacToe.butClicked==0);
switch(TicTacToe.butClicked)
{
case1:TicTacToe.state[0][0]=pl;break;
case2:TicTacToe.state[0][1]=pl;break;
case3:TicTacToe.state[0][2]=pl;break;
case4:TicTacToe.state[1][0]=pl;break;
case5:TicTacToe.state[1][1]=pl;break;
case6:TicTacToe.state[1][2]=pl;break;
case7:TicTacToe.state[2][0]=pl;break;
case8:TicTacToe.state[2][1]=pl;break;
case9:TicTacToe.state[2][2]=pl;break;
}
TicTacToe.butClicked=0;
}
}
Computer.java
Hide Shrink
Copy Code
importjava.io.*;
importjava.util.ArrayList;
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
16/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
publicclassComputerextendsPlayer{
intt=0;
Nodebegin=newNode("000000000",0,this);
Nodecurrent=begin;
doublelr=0;
File[]layerFiles=newFile[9];
ArrayList<Layer>layers=newArrayList<Layer>();
publicComputer(Stringl){
for(inti=0;i<9;i++)
{
layerFiles[i]=newFile(l+(i+1)+".nodes");
if(!layerFiles[i].exists())
{
try{
layerFiles[i].createNewFile();
}
catch(Exceptione)
{
System.out.println(e);
}
}
}
//loadMind();
makeNewMind();evaluate();saveMind();
begin.subNodes="100000000,010000000,001000000,000100000,000010000,000001000,000000100,000000010,0000
00001,";
begin.extractNodes();
}
publicvoidevaluate(){
for(inti=0;i<9;i++)
{
Layerl=layers.get(i);
for(intj=0;j<l.nodes.size();j++)
{
Stringx="",o="",s=l.nodes.get(j).id;
for(intk=0;k<9;k++)
{
charch=s.charAt(k);
if(ch=='1')
{
x+=(k+1);
}
elseif(ch=='2')
{
o+=(k+1);
}
}
intr=TicTacToe.checkWin2(x,o);
switch(r)
{
case1:l.nodes.get(j).pref=50;
l.nodes.get(j).nodeType=1;
break;
case2:l.nodes.get(j).pref=50;
l.nodes.get(j).nodeType=1;
break;
case1:
l.nodes.get(j).nodeType=1;
break;
}
}
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
17/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
}
}
publicvoidloadMind(){
FileReaderf;
BufferedReaderr;
inti=0;
try{
for(intl=0;l<9;l++)
{
layers.add(newLayer(l+1));
f=newFileReader(layerFiles[l]);
r=newBufferedReader(f);
Stringline;
while((line=r.readLine())!=null)
{
Nodetemp=newNode(r.readLine(),l+1,this);
temp.subNodes=r.readLine();
Stringno=r.readLine();
//System.out.println(no);
temp.pref=Integer.parseInt(no);
temp.n=Integer.parseInt(r.readLine());
temp.nodeType=Integer.parseInt(r.readLine());
layers.get(l).nodes.add(temp);
}
}
for(intl=0;l<9;l++)
{
for(intj=0;j<layers.get(l).nodes.size();j++)
{
layers.get(l).nodes.get(j).extractNodes();
}
}
}
catch(Exceptione){
e.printStackTrace(System.out);
}
}
publicvoidsaveMind(){
for(inti=7;i>=0;i)
{
layers.get(i).refreshLayer();
}
try{
for(inti=0;i<9;i++)
{
Layerl=layers.get(i);
PrintWriterp=newPrintWriter(newBufferedWriter(newFileWriter(layerFiles[i])));
for(intj=0;j<l.nodes.size();j++)
{
Nodetemp=l.nodes.get(j);
p.println("***********************************************");
p.println(temp.id);
//System.out.println(temp.id);
Strings="";
for(intk=0;k<temp.sub_nodes.size();k++)
{
s+=temp.sub_nodes.get(k).id+",";
}
p.println(s);
p.println(temp.pref);
p.println(temp.n);
p.println(temp.nodeType);
}
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
18/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
p.close();
//System.out.println("layer"+i+":"+l.nodes.size());
}
}
catch(Exceptione)
{
e.printStackTrace(System.out);
}
}
publicvoidmakeNewMind(){
layers.add(newLayer(1));layers.add(newLayer(2));layers.add(newLayer(3));layers.add(new
Layer(4));layers.add(newLayer(5));layers.add(newLayer(6));layers.add(newLayer(7));layers.add(new
Layer(8));layers.add(newLayer(9));
for(inti1=0;i1<=2;i1++){
for(inti2=0;i2<=2;i2++){
for(inti3=0;i3<=2;i3++){
for(inti4=0;i4<=2;i4++){
for(inti5=0;i5<=2;i5++){
for(inti6=0;i6<=2;i6++){
for(inti7=0;i7<=2;i7++){
for(inti8=0;i8<=2;i8++){
for(inti9=0;i9<=2;i9++){
intl=9;
if(i1==0)l;
if(i2==0)l;
if(i3==0)l;
if(i4==0)l;
if(i5==0)l;
if(i6==0)l;
if(i7==0)l;
if(i8==0)l;
if(i9==0)l;
intx=0;
if(i1==1)x++;
if(i2==1)x++;
if(i3==1)x++;
if(i4==1)x++;
if(i5==1)x++;
if(i6==1)x++;
if(i7==1)x++;
if(i8==1)x++;
if(i9==1)x++;
into=lx;
if((xo==0||xo==1)&&l!=0)
{
Stringid=""+i1+i2+i3+i4+i5+i6+i7+i8+i9;
layers.get(l1).nodes.add(newNode(id,l,this));
}
}}}}}}}}}
for(intl=1;l<9;l++)
{
for(intj=0;j<layers.get(l).nodes.size();j++)
{
Nodenode=layers.get(l).nodes.get(j);
for(inti=0;i<9;i++)
{
StringnewId="";
for(intk=0;k<9;k++)
{
charch=node.id.charAt(k);
if(k==i)ch='0';
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
19/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
newId+=ch;
}
if(!newId.equals(node.id))
{
try{
layers.get(l1).searchById(newId).sub_nodes.add(node);
//System.out.println(node.id+":"+newId+":"+l);
}
catch(NullPointerExceptione){}
}
}
}
}
begin.extractNodes();
}
@Override
publicvoidplayTurn(intp,intturn){
t=turn;
if(turn!=1)
{
current=layers.get(turn2).searchByState(TicTacToe.state);
}
if(turn==1)
{
current=begin;
}
if(p==1)current.playNextn();
if(p==2)current.playNext2();
}
@Override
voidnotifyWin(intpl){
if(pl==1)current.pref+=10;
if(pl==2)current.pref=10;
current.nodeType=1;
//System.out.println("*******"+current.id+":"+current.pref+":"+layers.get(current.lNum
1).searchById(current.id).pref);
saveMind();
}
@Override
voidnotifyLose(intpl){
if(pl==1)current.pref=10;
if(pl==2)current.pref+=10;
current.nodeType=1;
//System.out.println("*******"+current.id+":"+current.pref+":"+layers.get(current.lNum
1).searchById(current.id).pref);
saveMind();
}
}
Node.java
Hide Shrink
Copy Code
importjava.util.ArrayList;
publicclassNode{
ArrayList<Node>sub_nodes=newArrayList<Node>();
StringsubNodes="";
Stringid="";
intpref=0;
intn=0;
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
20/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
intlNum;
Computercomp;
intnodeType=0;
publicNode(Stringi,intl,Computerc){
id=i;
lNum=l;
comp=c;
}
publicvoidsetAsState(){
for(inti=0;i<id.length();i++)
{
intval=(int)(id.charAt(i)'0');
intt=i/3;
TicTacToe.state[t][i(t*3)]=val;
}
}
publicvoidplayNext1(){
ArrayList<Node>temp=newArrayList<Node>();
//System.out.println(id+":"+sub_nodes.size());
longmax=sub_nodes.get(0).pref;
for(inti=0;i<sub_nodes.size();i++)
{
if(sub_nodes.get(i).pref>max)
{
temp.clear();
temp.add(sub_nodes.get(i));
max=sub_nodes.get(i).pref;
}
elseif(sub_nodes.get(i).pref==max)
{
temp.add(sub_nodes.get(i));
}
}
intchoice=(int)(Math.random()*temp.size());
temp.get(choice).n++;
temp.get(choice).setAsState();
}
publicvoidplayNext2(){
ArrayList<Node>temp=newArrayList<Node>();
//System.out.println(id+":"+sub_nodes.size());
longmin=sub_nodes.get(0).pref;
for(inti=0;i<sub_nodes.size();i++)
{
if(sub_nodes.get(i).pref<min)
{
temp.clear();
temp.add(sub_nodes.get(i));
min=sub_nodes.get(i).pref;
}
elseif(sub_nodes.get(i).pref==min)
{
temp.add(sub_nodes.get(i));
}
}
intchoice=(int)(Math.random()*temp.size());
temp.get(choice).n++;
temp.get(choice).setAsState();
}
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
21/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
publicvoidplayNextn(){
ArrayList<Node>temp=newArrayList<Node>();
//System.out.println(id+":"+sub_nodes.size());
intchoice=0;
longmin=sub_nodes.get(0).n;
for(inti=0;i<sub_nodes.size();i++)
{
if(sub_nodes.get(i).n<min)
{
min=sub_nodes.get(i).n;
choice=i;
}
}
sub_nodes.get(choice).n++;
sub_nodes.get(choice).setAsState();
}
publicvoidextractNodes(){
if(lNum!=9)
{
intl=subNodes.length();
Stringw="";
for(inti=0;i<l;i++)
{
charch=subNodes.charAt(i);
if(ch!=',')
{
w+=ch;
}
else
{
sub_nodes.add(comp.layers.get(lNum).searchById(w));
w="";
}
}
}
}
}
Layer.java
Hide Shrink
Copy Code
importjava.util.ArrayList;
publicclassLayer{
ArrayList<Node>nodes=newArrayList<Node>();
intlayerNum=0;
publicLayer(intNum){
layerNum=Num;
}
publicvoidrefreshLayer(){
for(inti=0;i<nodes.size();i++)
{
Nodetemp=nodes.get(i);
if(temp.nodeType!=0)continue;
temp.pref=0;
for(intj=0;j<temp.sub_nodes.size();j++)
{
temp.pref+=(int)(temp.sub_nodes.get(j).pref)/2;
}
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
22/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
//System.out.print(temp.pref!=0?temp.pref+"\n":"");
}
}
publicNodesearchByState(int[][]state){
Stringtemp=""+state[0][0]+state[0][1]+state[0][2]+state[1][0]+state[1][1]+state[1]
[2]+state[2][0]+state[2][1]+state[2][2];
//System.out.print(temp.!=0?temp:"");
Noderet=searchById(temp);
returnret;
}
publicNodesearchById(Stringid){
Noderet=null;
for(inti=0;i<nodes.size();i++)
{
//System.out.println("*********"+nodes.get(i).id);
if(nodes.get(i).id.equals(id))
{
ret=nodes.get(i);
break;
}
}
returnret;
}
}
Conclusion
I hope you enjoyed reading my post and would be further interested in this topic. This Method can be used to develop other
machine learning programs. I would be really happy to see this in other programs
.
Credits
This project was developed by Mohd Akram ,an Intermediate student from India . I am 16 years old indian with many ideas in
my mind and hope that you will help me make them come real. Thank You very much for reading my work.
License
This article, along with any associated source code and files, is licensed under The Code Project Open License CPOL
Share
EMAIL
23/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
Go
First Prev Next
20Dec15 14:32
Quetion
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
mehul110 9Sep15 23:20
24/25
6/3/2016
AIbasedTicTacToe(javacode)CodeProject
mehul110
9Sep15 23:20
Error
gjumboman
22May15 13:09
29Nov14 17:38
7Dec14 13:59
10Jun14 0:15
21Mar15 5:41
News
1
Suggestion
Question
Bug
Answer
Joke
Praise
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.160531.1 | Last Updated 27 May 2014
http://www.codeproject.com/Articles/778260/AIbasedTicTacToe
Select Language
Layout: fixed | fluid
25/25