Alpha-Beta Prune
B.The problem
1. alpha-beta.cpp
file name: alpha-beta.cpp
#include <deque>
#include <iostream>
#include <ctime>
#include <string>
#include <cstdio>
#include <cstdlib>
using namespace std;
int index=0;
struct TreeNode;
typedef deque<TreeNode> NodesType;
const int MaxBranchNumber=4;
const int DefaultAlphaValue=-1000;
const int DefaultBetaValue=1000;
const int MaxSearchLevel=5;
enum TreeNodeType
{
MaxNode, MinNode
};
char* nodeName[2]= {"MaxNode", "MinNode"};
//assume max is root
struct TreeNode
{
friend void displayTree(const TreeNode& node);
friend void displayQueue(const deque<TreeNode>& sonQueue);
friend ostream& operator <<(ostream& os, const TreeNode& node)
{
os<<"name:"<<node.name<<endl;
os<<"number of sons:"<<node.sons.size()<<endl;
os<<"node type:"<<((node.nodeType==MaxNode)?"MaxNode":"MinNode")<<endl;
return os;
}
deque<TreeNode> sons;
TreeNodeType nodeType;
string name;
int data;
int minmax();
int pruneTree(int alpha, int beta, int level) const;
TreeNode prune();
void populate(int level);
void addSon(const TreeNode& oneSon);
};
TreeNode TreeNode::prune()
{
int value, current;
TreeNode result;
if (nodeType==MaxNode)
{
current=DefaultAlphaValue;
}
else
{
current=DefaultBetaValue;
}
for (NodesType::const_iterator it=sons.begin(); it!=sons.end(); it++)
{
value=(*it).pruneTree(DefaultAlphaValue, DefaultBetaValue, 0);
if ((nodeType==MaxNode&&value>current)||(nodeType==MinNode&&value<current))
{
result=*it;
current=value;
}
}
return result;
}
int TreeNode::minmax()
{
int value=-1, result=-1;
if (sons.size()==0)
{
return data;
}
for (deque<TreeNode>::iterator it=sons.begin(); it!=sons.end(); it++)
{
value=(*it).minmax();
if (result==-1)
{
result=value;
}
else
{
if (nodeType==MaxNode)
{
if (value>result)
{
result=value;
}
}
else
{
if (value<result)
{
result=value;
}
}
}
}
data=result;
return result;
}
int TreeNode::pruneTree(int alpha, int beta, int level) const
{
int value, result;
if (sons.size()==0||level==MaxSearchLevel)
{
return data;
}
if (nodeType==MaxNode)
{
result=alpha;
}
else
{
result=beta;
}
for (NodesType::const_iterator it=sons.begin(); it!=sons.end(); it++)
{
value=(*it).pruneTree(alpha, beta, level+1);
if (nodeType==MaxNode)
{
if (value>beta)
{
return value;
}
if (value>result)
{
result=value;
}
}
else
{
if (value<alpha)
{
return value;
}
if (value<result)
{
result=value;
}
}
}
return result;
}
void displayQueue(const deque<TreeNode>& sonQueue)
{
deque<TreeNode> myqueue;
if (sonQueue.empty())
{
return ;
}
for (deque<TreeNode>::const_iterator it=sonQueue.begin(); it!=sonQueue.end(); it++)
{
cout<<(*it).name<<"="<<(*it).data<<"("<<nodeName[(*it).nodeType]
<<(*it).sons.size()<<"), ";
myqueue.insert(myqueue.end(), (*it).sons.begin(), (*it).sons.end());
}
cout<<"\n";
displayQueue(myqueue);
// cout<<"\n";
}
void displayTree(const TreeNode& node)
{
//TreeNode ptr=node;
cout<<node.name<<"="<<node.data;
cout<<"("<<nodeName[node.nodeType]<<node.sons.size()<<") "<<"\n";
displayQueue(node.sons);
// cout<<"\n";
}
void TreeNode::addSon(const TreeNode& oneSon)
{
char nameBuf[10];
TreeNode son=oneSon;
if (son.name=="")
{
sprintf(nameBuf, "A%d", ++index);
son.name=string(nameBuf);
}
if (nodeType==MaxNode)
{
son.nodeType=MinNode;
}
else
{
son.nodeType=MaxNode;
}
sons.push_back(son);
}
void TreeNode::populate(int level)
{
int number, i;
TreeNode oneSon;
number=rand()%MaxBranchNumber;
if (number==0||level==0)
{
data=rand()%20;
return;
}
for (i=0; i<number; i++)
{
oneSon.data=-1;
addSon(oneSon);
sons[i].populate(level-1);
}
}
void construct424(TreeNode& root)
{
TreeNode node;
deque<TreeNode>::iterator it, sonIt, sonsonIt;
node.name="B";
node.data=-1;
root.addSon(node);
node.name="C";
node.data=-1;
root.addSon(node);
//level 2
it=root.sons.begin();//
node.name="D";
node.data=3;
(*it).addSon(node);
//it++;
node.name="E";
node.data=5;
(*it).addSon(node);
it++;
node.name="F";
node.data=-1;
(*it).addSon(node);
sonIt=(*it).sons.begin();
node.name="I";
node.data=-1;
(*sonIt).addSon(node);
sonsonIt=(*sonIt).sons.begin();
node.name="M";
node.data=0;
(*sonsonIt).addSon(node);
node.name="N";
node.data=7;
(*sonsonIt).addSon(node);
node.name="J";
node.data=5;
(*sonIt).addSon(node);
node.name="G";
node.data=-1;
(*it).addSon(node);
//sonsonIt=(*sonIt).sons.begin();
sonIt++;
node.name="K";
node.data=7;
(*sonIt).addSon(node);
node.name="L";
node.data=8;
(*sonIt).addSon(node);
node.name="H";
node.data=4;
(*it).addSon(node);
}
int main()
{
//srand(time(0));
TreeNode tree;//, temp;
tree.name=string("A");
tree.data=-1;
//tree.depth=0;
//tree.parent=NULL;
tree.nodeType=MaxNode;
construct424(tree);
//tree.populate(5);
cout<<"before pruning the tree is like this:\n";
displayTree(tree);
cout<<tree.prune()<<endl;
//temp=tree.prune();
//cout<<temp;
cout<<"and with minmax it like this:\n";
cout<<tree.minmax()<<endl;
displayTree(tree);
return 0;
}
2. The result is like following:(How to understand the format? Each line output is one level of tree. The display of a node is
at this sequence: name, data (Min-Max-Type, number of son nodes)
before pruning the tree is like this:
A=-1(MaxNode2)
B=-1(MinNode2), C=-1(MinNode3),
D=3(MaxNode0), E=5(MaxNode0), F=-1(MaxNode2), G=-1(MaxNode2), H=4(MaxNode0),
I=-1(MinNode2), J=5(MinNode0), K=7(MinNode0), L=8(MinNode0),
M=0(MaxNode0), N=7(MaxNode0),
name:C
number of sons:3
node type:MinNode
and with minmax it like this:
4
A=4(MaxNode2)
B=3(MinNode2), C=4(MinNode3),
D=3(MaxNode0), E=5(MaxNode0), F=5(MaxNode2), G=8(MaxNode2), H=4(MaxNode0),
I=0(MinNode2), J=5(MinNode0), K=7(MinNode0), L=8(MinNode0),
M=0(MaxNode0), N=7(MaxNode0),
Press any key to continue