einfacherer Algorithmus, der nur Eckzüge und gegnerische Mobilität in

Betracht zieht
This commit is contained in:
Trolli Schmittlauch 2015-03-13 10:54:32 +01:00
parent 88bf2f215a
commit c0d135fae2

View file

@ -22,38 +22,38 @@ send_move(int row, int col)
return 0; return 0;
} }
int //int
buildTree(gameTree *currentNode, cell (*field)[fieldSize], movesList *moves, int depth, char enemyc) { //buildTree(gameTree *currentNode, cell (*field)[fieldSize], movesList *moves, int depth, char enemyc) {
if (depth == 0 || moves->movesNumber == 0) // if (depth == 0 || moves->movesNumber == 0)
return 0; // return 0;
currentNode->numChildMoves = moves->movesNumber; // currentNode->numChildMoves = moves->movesNumber;
currentNode->childMove = new gameTree[maxMoves](); // currentNode->childMove = new gameTree[maxMoves]();
//switch stone char // //switch stone char
char ownc = getEnemyChar(enemyc); // char ownc = getEnemyChar(enemyc);
//
//#ifdef debugprint ////#ifdef debugprint
// printf("Depth %d: enemy: %c\n", depth, enemyc); //// printf("Depth %d: enemy: %c\n", depth, enemyc);
//#endif ////#endif
for(size_t i=0; i<moves->movesNumber; ++i) // for(size_t i=0; i<moves->movesNumber; ++i)
{ // {
currentNode->childMove[i].nodeMove = moves->list[i]; // currentNode->childMove[i].nodeMove = moves->list[i];
size_t fieldMemSize = fieldSize*fieldSize*sizeof(cell); // size_t fieldMemSize = fieldSize*fieldSize*sizeof(cell);
auto futureField = new cell[fieldSize][fieldSize](); // auto futureField = new cell[fieldSize][fieldSize]();
memcpy(futureField, field, fieldMemSize); // memcpy(futureField, field, fieldMemSize);
futureField[(moves->list[i].turnRow-1)][(moves->list[i].turnCol-1)].content=enemyc; // futureField[(moves->list[i].turnRow-1)][(moves->list[i].turnCol-1)].content=enemyc;
movesList *futureMoves = new movesList(); // movesList *futureMoves = new movesList();
findMoves(futureField, futureMoves, enemyc); // findMoves(futureField, futureMoves, enemyc);
buildTree(&(currentNode->childMove[i]), futureField, futureMoves, depth-1, getEnemyChar(enemyc)); // buildTree(&(currentNode->childMove[i]), futureField, futureMoves, depth-1, getEnemyChar(enemyc));
delete [] futureMoves; // delete [] futureMoves;
delete [] futureField; // delete [] futureField;
} // }
return 1; // return 1;
} //}
move move
maxEvalMove(std::vector<evalMove> *curMoves) { maxEvalMove(std::vector<evalMove> *curMoves) {
evalMove maxM; evalMove maxM;
maxM.evaluation = -9; maxM.evaluation = -99;
for(size_t i = 0; i < curMoves->size(); ++i) for(size_t i = 0; i < curMoves->size(); ++i)
{ {
if(curMoves->at(i).evaluation > maxM.evaluation) if(curMoves->at(i).evaluation > maxM.evaluation)
@ -65,59 +65,85 @@ maxEvalMove(std::vector<evalMove> *curMoves) {
return maxM.m; return maxM.m;
} }
int //int
maxInt(std::vector<int> *evaluations) { //maxInt(std::vector<int> *evaluations) {
int maxE = -10; // int maxE = -10;
for(size_t i = 0; i<evaluations->size(); ++i) // for(size_t i = 0; i<evaluations->size(); ++i)
{ // {
if(evaluations->at(i) > maxE) // if(evaluations->at(i) > maxE)
{ // {
maxE = evaluations->at(i); // maxE = evaluations->at(i);
} // }
} // }
return maxE; // return maxE;
} //}
//
//MiniMax Algorithmus ////MiniMax Algorithmus
int //int
eval(gameTree *currentNode, int depth) { //eval(gameTree *currentNode, int depth) {
if (depth == 0 || !currentNode->numChildMoves) // if (depth == 0 || !currentNode->numChildMoves)
{ // {
//gut: hohe Mobilität, Eckzüge. Schlecht: Züge auf Felder direkt vor der Ecke // //gut: hohe Mobilität, Eckzüge. Schlecht: Züge auf Felder direkt vor der Ecke
return (currentNode->numChildMoves + 5*isCornerField(currentNode->nodeMove) - 2*isCOrXField(currentNode->nodeMove)); // return (currentNode->numChildMoves + 5*isCornerField(currentNode->nodeMove) - 2*isCOrXField(currentNode->nodeMove));
} // }
//
std::vector<int> curEvals; // std::vector<int> curEvals;
for(size_t i = 0; i < currentNode->numChildMoves; ++i) // for(size_t i = 0; i < currentNode->numChildMoves; ++i)
{ // {
int curEval = -1 * eval(&(currentNode->childMove[i]), depth-1); // int curEval = -1 * eval(&(currentNode->childMove[i]), depth-1);
curEvals.push_back(curEval); // curEvals.push_back(curEval);
} // }
return maxInt(&curEvals); // return maxInt(&curEvals);
} //}
//
//move
//findBestMove(gameTree *currentNode, int depth) {
// std::vector<evalMove> curMoves;
// for(size_t i = 0; i < currentNode->numChildMoves; ++i)
// {
// evalMove m;
// m.evaluation = -1 * eval(&(currentNode->childMove[i]), depth-1);
// m.m = currentNode->childMove[i].nodeMove;
//#ifdef debugprint
// printf("findBest %d: %d, %d\n", m.evaluation, m.m.turnRow, m.m.turnCol);
//#endif
// curMoves.push_back(m);
// }
// return maxEvalMove(&curMoves);
//}
move move
findBestMove(gameTree *currentNode, int depth) { nFindBestMove(cell (*field)[fieldSize], movesList *moves, char enemyc) {
std::vector<evalMove> curMoves; std::vector<evalMove> curMoves;
for(size_t i = 0; i < currentNode->numChildMoves; ++i) printf("NumOwnMoves: %d\n", moves->movesNumber);
for(size_t i=0; i < moves->movesNumber; ++i)
{ {
evalMove m;
m.evaluation = -1 * eval(&(currentNode->childMove[i]), depth-1);
m.m = currentNode->childMove[i].nodeMove;
#ifdef debugprint #ifdef debugprint
printf("findBest %d: %d, %d\n", m.evaluation, m.m.turnRow, m.m.turnCol); printf("EnemyMove %d ", i);
#endif
size_t fieldMemSize = fieldSize*fieldSize*sizeof(cell);
auto futureField = new cell[fieldSize][fieldSize]();
memcpy(futureField, field, fieldMemSize);
futureField[(moves->list[i].turnRow-1)][(moves->list[i].turnCol-1)].content=enemyc;
movesList *futureMoves = new movesList();
findMoves(futureField, futureMoves, enemyc);
evalMove m;
m.m = moves->list[i];
//gut: Eckzüge. Schlecht: hohe Mobilität des Gegners, Züge auf Felder direkt vor der Ecke
m.evaluation = 5*isCornerField(m.m) - futureMoves->movesNumber - 2*(!endgame)*isCOrXField(m.m);
#ifdef debugprint
printf("eval: %d, move: %d, %d\n", m.evaluation, m.m.turnRow, m.m.turnCol);
#endif #endif
curMoves.push_back(m); curMoves.push_back(m);
#ifdef debugprint
printf("m: (%d, %d) hat %d\n", m.m.turnRow, m.m.turnCol, m.evaluation);
#endif
delete [] futureMoves;
delete [] futureField;
} }
return maxEvalMove(&curMoves); return maxEvalMove(&curMoves);
} }
//move
//nFindBestMove(cell (*field)[fieldSize], movesList *movesa) {
// std::vector<evalMove> curMoves;
int main(void) int main(void)
{ {
int done = 0; int done = 0;
@ -177,16 +203,21 @@ int main(void)
printf("Nope\n"); printf("Nope\n");
#endif #endif
} }
else else {
{ move finalMove;
if(moves->movesNumber == 1)
finalMove = moves->list[0];
else
{
if((numX+numO)>5*fieldSize*fieldSize/6) if((numX+numO)>5*fieldSize*fieldSize/6)
endgame = 1; endgame = 1;
gameTree *treeRoot = new gameTree(); //gameTree *treeRoot = new gameTree();
treeRoot->nodeMove.turnRow = 0; //treeRoot->nodeMove.turnRow = 0;
treeRoot->nodeMove.turnCol = 0; //treeRoot->nodeMove.turnCol = 0;
buildTree(treeRoot, field, moves, 1, getEnemyChar(enemyc)); //buildTree(treeRoot, field, moves, 1, getEnemyChar(enemyc));
move finalMove = findBestMove(treeRoot, 1); finalMove = nFindBestMove(field, moves, getEnemyChar(enemyc));
}
turn_row=finalMove.turnRow; turn_row=finalMove.turnRow;
turn_col=finalMove.turnCol; turn_col=finalMove.turnCol;