Tic Tac Toe minimax algoritma c programlama (alıntı)
#include "stdio.h" #include "stdlib.h" #include "string.h" /* int board[25] = { :,:,:,:,:, :,O,-,X,:, :,X,-,-,:, :,-,-,-,:, :,:,:,:,:, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14, 15,16,17,18,19, 20,21,22,23,24 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14, 15,16,17,18,19, 20,21,22,23,24 } */ enum { NOUGHTS, CROSSES, BORDER, EMPTY }; enum { HUMANWIN, COMPWIN, DRAW }; const int Directions[4] = { 1, 5, 4, 6 }; const int ConvertTo25[9] = { 6, 7, 8, 11,12,13, 16,17,18 }; const int InMiddle = 4; const int Corners[4] = { 0, 2, 6, 8 }; int ply = 0; int positions = 0; int maxPly = 0; int GetNumForDir(int startSq, const int dir, const int *board, const int us) { int found = 0; while(board[startSq] != BORDER) { if(board[startSq] != us) { break; } found++; startSq += dir; } return found; } int FindThreeInARow(const int *board, const int ourindex, const int us) { int DirIndex = 0; int Dir = 0; int threeCount = 1; for(DirIndex = 0; DirIndex < 4; ++DirIndex) { Dir = Directions[DirIndex]; threeCount += GetNumForDir(ourindex + Dir, Dir, board, us); threeCount += GetNumForDir(ourindex + Dir * -1, Dir * -1, board, us); if(threeCount == 3) { break; } threeCount = 1; } return threeCount; } int FindThreeInARowAllBoard(const int *board, const int us) { int threeFound = 0; int index; for(index = 0; index < 9; ++index) { if(board[ConvertTo25[index]] == us) { if(FindThreeInARow(board, ConvertTo25[index], us) == 3) { threeFound = 1; break; } } } return threeFound; } int EvalForWin(const int *board, const int us) { if(FindThreeInARowAllBoard(board, us) != 0) return 1; if(FindThreeInARowAllBoard(board, us ^ 1) != 0) return -1; return 0; } int MinMax(int *board, int side) { // check is a win // gen all moves for side // loop moves, make move, mimax() on move to get score // assess bestscore // end moves return bestscore int MoveList[9]; int MoveCount = 0; int bestScore = -2; int score = -2; int bestMove = -1; int Move; int index; if(ply > maxPly) maxPly = ply; positions++; if(ply > 0) { score = EvalForWin(board, side); if(score != 0) { return score; } } // fill Move List for(index = 0; index < 9; ++index) { if( board[ConvertTo25[index]] == EMPTY) { MoveList[MoveCount++] = ConvertTo25[index]; } } // loop all moves for(index = 0; index < MoveCount; ++index) { Move = MoveList[index]; board[Move] = side; ply++; score = -MinMax(board, side^1); if(score > bestScore) { bestScore = score; bestMove = Move; } board[Move] = EMPTY; ply--; } if(MoveCount==0) { bestScore = FindThreeInARowAllBoard(board, side); } if(ply!=0) return bestScore; else return bestMove; } void InitialiseBoard(int *board) { int index = 0; for(index = 0; index < 25; ++index) { board[index] = BORDER; } for(index = 0; index < 9; ++index) { board[ConvertTo25[index]] = EMPTY; } } void PrintBoard(const int *board) { int index = 0; char pceChars[] = "OX|-"; printf("\n\nBoard:\n\n"); for(index = 0; index < 9; ++index) { if(index!=0 && index%3==0) { printf("\n\n"); } printf("%4c",pceChars[board[ConvertTo25[index]]]); } printf("\n"); } int HasEmpty(const int *board) { int index = 0; for(index = 0; index < 9; ++index) { if( board[ConvertTo25[index]] == EMPTY) return 1; } return 0; } void MakeMove(int *board, const int sq, const side) { board[sq] = side; } int GetNextBest(const int *board) { int ourMove = ConvertTo25[InMiddle]; if(board[ourMove] == EMPTY) { return ourMove; } int index = 0; ourMove = -1; for(index = 0; index < 4; index++) { ourMove = ConvertTo25[Corners[index]]; if(board[ourMove] == EMPTY) { break; } ourMove = -1; } return ourMove; } int GetWinningMove(int *board, const int side) { int ourMove = -1; int winFound = 0; int index = 0; for(index = 0; index < 9; ++index) { if( board[ConvertTo25[index]] == EMPTY) { ourMove = ConvertTo25[index]; board[ourMove] = side; if(FindThreeInARow(board, ourMove, side) == 3) { winFound = 1; } board[ourMove] = EMPTY; if(winFound == 1) { break; } ourMove = -1; }; } return ourMove; } int GetComputerMove(int *board, const int side) { ply=0; positions=0; maxPly=0; int best = MinMax(board, side); printf("Finished Searching positions:%d maxDepth:%d bestMove:%d\n",positions,maxPly,best); return best; } int GetHumanMove(const int *board) { char userInput[4]; int moveOk = 0; int move = -1; while (moveOk == 0) { printf("Please enter a move from 1 to 9:"); fgets(userInput, 3, stdin); fflush(stdin); if(strlen(userInput) != 2) { printf("Invalid strlen()\n"); continue; } if( sscanf(userInput, "%d", &move) != 1) { move = -1; printf("Invalid sscanf()\n"); continue; } if( move < 1 || move > 9) { move = -1; printf("Invalid range\n"); continue; } move--; // Zero indexing if( board[ConvertTo25[move]]!=EMPTY) { move=-1; printf("Square not available\n"); continue; } moveOk = 1; } printf("Making Move...%d\n",(move+1)); return ConvertTo25[move]; } void RunGame() { int GameOver = 0; int Side = CROSSES; int LastMoveMade = 0; int board[25]; InitialiseBoard(&board[0]); PrintBoard(&board[0]); while(!GameOver) { if(Side==NOUGHTS) { LastMoveMade = GetHumanMove(&board[0]); MakeMove(&board[0],LastMoveMade,Side); Side=CROSSES; } else { LastMoveMade = GetComputerMove(&board[0], Side); MakeMove(&board[0],LastMoveMade,Side); Side=NOUGHTS; PrintBoard(&board[0]); } // if three in a row exists Game is over if( FindThreeInARow(board, LastMoveMade, Side ^ 1) == 3) { printf("Game over!\n"); GameOver = 1; if(Side==NOUGHTS) { printf("Computer Wins\n"); } else { printf("Human Wins\n"); } } // if no more moves, game is a draw if(!HasEmpty(board)) { printf("Game over!\n"); GameOver = 1; printf("It's a draw\n"); } } PrintBoard(&board[0]); } int main() { srand(time(NULL)); RunGame(); return 0; }
Hiç yorum yok:
Yorum Gönder
Her yorum bilgidir. Araştırmaya devam...