double Player::minimax(Board *b, int depth, bool max_player) { if(depth == 0 || b->isDone()) return b->score(side); double best_score; if(max_player) { best_score = -INF; vector<Move *> moves = b->possibleMoves(side); for(auto &m : moves) { Board *child = b->copy(); child->doMove(m, side); double v = minimax(child, depth - 1, false); best_score = max(best_score, v); } } else { best_score = INF; vector<Move *> moves = b->possibleMoves(opp_side); for(auto &m : moves) { Board *child = b->copy(); child->doMove(m, opp_side); double v = minimax(child, depth - 1, true); best_score = min(best_score, v); } } return best_score; }
/* Basically the same code as minimax. It initiates the move making process. */ void AI::make_move(int current_player, Board* game_board) { //Defines max and min possible scores. int alpha = -2000; int beta = 2000; //The depth is initially 0. This will be incremented after every recursive call to minimax. int depth = 0; //Defines the best possible score so far and a default position. int best_score; int position = 4; //If player is X. if (current_player == 1) { //We try to get a better score than alpha, so we default to alpha in the beginning. best_score = alpha; //We basically perform all 7 (at most) possible moves. for (int i = 1; i < 8; ++i) { //Only if i is a valid move. if (valid_move(i)) { //It plays the move i in the vector and simply recursively calls minimax to maximize (or minimize) its score and revert all moves. play(current_player, i); int score = minimax(best_score, beta, -current_player, game_board, depth); if (score > best_score) { //Score and position are stored. best_score = score; position = i; } //Move is reverted. revert(current_player, i); //Here we perform alpha beta pruning, which enables us to discard large sections of the Search Tree. if (beta <= best_score) { break; } } } } //Same process as with 1. else if (current_player == -1) { best_score = beta; for (int i = 1; i < 8; ++i) { if (valid_move(i)) { play(current_player, i); int score = minimax(alpha, best_score, -current_player, game_board, depth); if (score < best_score) { best_score = score; position = i; } revert(current_player, i); if (best_score <= alpha) { break; } } } } //After determining the best position (from the best score), it makes that move. play(current_player, position); }
void zz::bot::set_depth() { // figure out how long it takes to calculate the heuristic value of a leaf, by timing a // minimax run and counting the leafs at that depth, since 99% of a minimax // run is actually spent calculating the heuristic value of the leafs clock_t leaf_calc_time = 0; clock_t timer = 0; int test_depth = 2; zz::map::__minimax_leafs = 0; while( zz::map::__minimax_leafs < 100 ) { timer = clock( ); minimax( test_depth ); timer = clock( ) - timer; leaf_calc_time += timer; #ifdef DEBUG_BOT fprintf( stderr, " test_depth: %d | leafs: %8d | %-.4fs\n", test_depth, zz::map::__minimax_leafs, (float) timer / CLOCKS_PER_SEC ); #endif if( zz::map::__minimax_leafs == 0 ) { // minimax solved the board using test_depth _depth = test_depth; return; } else { ++test_depth; } } #ifdef DEBUG_BOT fprintf( stderr, " total time calcing leafs: %-.4fs\n", (float) leaf_calc_time / CLOCKS_PER_SEC ); #endif // calculate the max number of leafs we can handle in 1 second int leafs = zz::map::__minimax_leafs; float clocks_per_leaf = ( float ) timer / leafs; int max_leafs = ( (CLOCKS_PER_SEC - leaf_calc_time) / clocks_per_leaf) * 0.50; // give up 50%, just in case we understimated the cost of calcing a leaf // find the max minimax depth, with fewer than max_leafs bool gone_over = false; int cost = 0; do { // see how many leafs are at the current depth timer = clock( ); minimax( _depth, false ); cost = ( clock( ) - timer ) / clocks_per_leaf; // we burned some time max_leafs -= cost; leafs = zz::map::__minimax_leafs; #ifdef DEBUG_BOT fprintf( stderr, " leafs: %8d | max_leafs: %8d | depth: %2d | %-.4fs | cost: %d\n", leafs, max_leafs, _depth, (float) ( clock( ) - timer ) / CLOCKS_PER_SEC, leafs + cost * 4 ); #endif // test deeper, if we have enough max leafs left for double the cost that this depth took if( leafs + cost * 2 < max_leafs ) { _depth++; } if( leafs > max_leafs ) { _depth--; gone_over = true; } } while( leafs > 0 && max_leafs > 0 && !gone_over && leafs + cost * 2 < max_leafs ); }
/*------------------------------------------------------------------------------*\ ( ) - \*------------------------------------------------------------------------------*/ void BmCheckControl::_InitSize() { ResizeToPreferred(); float width, height; GetPreferredSize(&width, &height); // if there's no label, just use the space required for the checkbox if (Label() == NULL) ct_mpm = minimax(17, int(height), 17, int(height)); else ct_mpm = minimax(int(width), int(height), 1E5, int(height)); }
static void find_move() { int best, val, besti[9], i, bestcount = 0; time_t t1; best = 1000000; for (i=0; i<9; i++) { if (board[i] == '-') { board[i] = 'o'; val = minimax(1, 1); if (val == best) { best = val; besti[bestcount++] = i; } else if (val < best) { best = val; bestcount = 0; besti[bestcount++] = i; } board[i] = '-'; } } (void) time(&t1); srandom((long)t1); i = random()%bestcount; difficulty--; board[besti[i]] = 'o'; drawXO(besti[i], BLACK,'o'); }
void threadStarter(char thread) { char newSuperBoardSpot = doMove(tData[thread].subBoard, tData[thread].superBoard, tData[thread].opPlayer, tData[thread].move); long result = minimax(tData[thread].subBoard, tData[thread].superBoard, newSuperBoardSpot, MINIMIZE, tData[thread].opPlayer, tData[thread].levels, -9999999999, 9999999999); //undoMove(tData[thread].subBoard, tData[thread].superBoard, tData[thread].move); trData[thread].score = result; trData[thread].move = tData[thread].move; }
// Negamax cu alpha-beta // http://algopedia.ro/wiki/index.php/Note_de_curs,_clasele_9-10,_22_mai_2014#Alpha-beta int minimax(char board[TABLE_WIDTH][TABLE_WIDTH], char depth, int alpha, int beta, char player, char computerPlayer) { plyCounter++; int rc; int lin, col; int val; struct TableStatus status; getTableStatus(board, &status); if (depth == 0 || status.freeTiles == 0 || getTime() - programStart > STOP_PROGRAM) { rc = status.scores[player + 1] - status.scores[-player + 1]; //printf("%d\t", rc); return rc; } lin = 0; while (lin < TABLE_WIDTH && alpha < beta) { col = 0; while (col < TABLE_WIDTH && alpha < beta) { if (board[lin][col] == GOL) { board[lin][col] = player; val = -minimax(board, depth - 1, -beta, -alpha, -player, computerPlayer); alpha = max(alpha, val); board[lin][col] = GOL; } col++; } lin++; } rc = min(alpha, beta); return rc; }
void zz::bot::move( ) { _moved = false; #ifdef DEBUG_BOT fprintf( stderr, "(%d,%d) vs (%d,%d) calculating move:\n", _map.player_one().x(), _map.player_one().y(), _map.player_two().x(), _map.player_two().y() ); #endif // determins the basic strategy of minimax vs solomax if( _players_are_connected ) { _players_are_connected = _map.locations_are_connected( _map.player_one( ), _map.player_two( ) ); if( !_players_are_connected ) _depth = 3; // we are gonna switch from minimax to solomax, solomax can't alpha-beta prune, so we need to start low again } set_depth(); // find the best possible hueristic solution to the board using _depth clock_t timer = clock( ); minimax( _depth ); timer = clock( ) - timer; #ifdef DEBUG_BOT fprintf( stderr, " %move: [" ); for( int i = 0; i < _count_moves; ++i ) { fprintf( stderr, "%d", _moves[i] ); if( i != _count_moves - 1) fprintf( stderr, ", " ); } fprintf( stderr, "]\n" ); #endif if( !_moved ) { choose_by_walls(); } }
void makeComputerMove(char *board, char computerPiece) { int i, min, move; char playerPiece = getOpponentPiece(computerPiece); min = 2; move = -1; for(i = 0; i < 9; i ++) { if(board[i] == NONE) { board[i] = computerPiece; int val = minimax(board, playerPiece, computerPiece, 1, 2, -2);//maxAgent(board, playerPiece, computerPiece); board[i] = NONE; if(min > val) { min = val; move = i; } //-1 is the least possible value that a maxAgent can return so no need to check further. if(val == -1) { break; } } } //make the move. if(move != -1) { board[move] = computerPiece; } }
void computer_move() { int pos = -26; int i, j, best_i = 1, best_j = 1; int points = 25, move_points = 0; printf("\n\nZ3TA plays position: "); for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) { if(!board[i][j]) { board[i][j] = -1; move_points = minimax(board, 1); //printf("%d\n", move_points); the magic happens here! if(points > move_points) { points = move_points; pos = i*3 + j + 1; best_i = i; best_j = j; } board[i][j] = 0; } } } board[best_i][best_j] = -1; printf("%d\n", pos); }
move getminimaxmove( const dtype board[16][16], const dtype available[2][21], const int player, const dtype maxsearchdepth){ move moves[2000]; int movesFound, i; movesFound = getMoveList( moves, board, available, player, score ); int move_num = -1; float alpha = -FLT_MAX, beta = FLT_MAX; for( i = 0; i < movesFound; i++ ){ dtype n_board[16][16]; dtype n_available[2][21]; int n_score[2]; int n_player; simulateMove( moves[i], board, available, score, player, n_board, n_available, n_score, &n_player ); float newUtility = minimax( n_board, n_available, n_score, n_player, maxsearchdepth, alpha, beta ); if( player == player_max ) { if( newUtility > alpha ) { alpha = newUtility; move_num = i; } } else if( newUtility < beta ) { beta = newUtility; move_num = i; } } if(move_num == -1) move_num = 0; move m = moves[move_num]; score[player-1] += piece_sizes[m.piece]; return m; }
int AI::minimax(Board *b, char m){ int tmp, mmx; if (b->checkPlayerWin(m)) return (m == 'o') ? 1 : -1; if (b->countBlank() == 0) return 0; m = (m == 'o') ? 'x' : 'o'; mmx = (m == 'x') ? 10 : -10; // dla x - min dla o - max tmp = 0; for (int i = 0; i < 9; i++){ if (b->board[i] == ' '){ b->board[i] = m; tmp = minimax(b, m); b->board[i] = ' '; if (((m == 'x') && (tmp < mmx)) || ((m == 'o') && (tmp > mmx))) mmx = tmp; } } return mmx; }
int computer_move(char **board, char piece1, char piece2) { int i, j; int bestValue = INT_MIN; int bestMoves[9][2], bestLen = 0; // randomizes equal-valued moves for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) if (board[i][j] == BLANK) { board[i][j] = piece1; // try out a square // int score = min(board, piece1, piece2, INT_MIN, INT_MAX); int score = minimax(board, piece1, piece2, INT_MIN, INT_MAX, -1); if (score > bestValue) { // new maximum bestValue = score; bestLen = 1; // reset number of ties bestMoves[0][0] = i; // store move bestMoves[0][1] = j; // store move } else if (score == bestValue) { // move tie bestMoves[bestLen][0] = i; // store move bestMoves[bestLen][1] = j; // store move bestLen++; } board[i][j] = BLANK; // return square to its original state } // choose a random move from the best moves bestLen = rand() % bestLen; i = bestMoves[bestLen][0]; j = bestMoves[bestLen][1]; board[i][j] = piece1; return 1; //this means the computer made a move (computer always has to make a move, no need to change this line) }
int get_score_func(gameState* state, piece board[BOARD_SIZE][BOARD_SIZE], int depth, move* user_move){ board_t tmp_board; copyStoS(tmp_board, board); int score; int colo_mult = 1; int best_depth = depth; // in case we are in const minimax depth mode makeMoveInPlace(state->board, user_move); if (state->turn == BLACK){ colo_mult = -1; } if (depth == 1){ score = scoreOfBoard(state)*colo_mult; } else{ state->turn = getEnemyColor(state->turn); if (depth == 5){ // need to decide what is the best depth best_depth = get_best_depth(state); } score = minimax(state, best_depth - 1, 0).value; state->turn = getEnemyColor(state->turn); } copyStoS(state->board, tmp_board); // update the state->board to the original board return score; }
Value Connect4::minimax(const GameState& board) { Depth depth = board.getDepth(); Value value = board.evaluate(); #ifdef DEBUG assert(board.isValid()); assert(depth <= DEPTH_MAX); #endif if(value != VALUE_UNKNOWN) { return value; } else if (depth == config.width*config.height) { return VALUE_DRAW; } else { GameState buffer[WIDTH]; board.children(buffer, config.width, config.height); value = VALUE_UNKNOWN; for(int i=0; i<WIDTH; i++) { if(buffer[i].isValid()) { Value val = minimax(buffer[i]); if(value == VALUE_UNKNOWN || (board.getPlayer() == PLAYER_MAX && val > value) || (board.getPlayer() == PLAYER_MIN && val < value)) { value = val; } } } return value; } }
void umjogador(char **board) { system("clear"); print_usage1(); int hor, vert, alpha; move best_move = (move) malloc (sizeof(struct legal_move)); print_board(board); while (!game_over(board) && (!someone_wins(board, 'X'))) { if (jogada(board,0)) { system("clear"); printf("A posição depois de sua última jogada:\n"); print_board(board); alpha = minimax(board, 1, best_move); update_board(board, best_move -> hor, best_move -> vert, 1); printf("A posição depois da última jogada do computador:\n"); print_board(board); } } if (someone_wins(board, 'X')) { ai_wins(); } else { cats_game(); } }
//Almost identical to make_move, except we increment depth since it is being called recursively. int AI::minimax(int alpha, int beta, int current_player, Board* game_board, int depth) { if (game_board->checkWin()) return current_player * -1000; else if (game_board->checkDraw()) return 0; if (depth == 7) { if (player == -1) return evaluate(game_board); else if (player == 1) return -(evaluate(game_board)); } ++depth; int best_score; if (current_player == 1) { best_score = alpha; for (int i = 1; i < 8; ++i) { if (valid_move(i)) { play(current_player, i); int score = minimax(best_score, beta, -current_player, game_board, depth); if (score > best_score) best_score = score; revert(current_player, i); if (beta <= best_score) { break; } } } } else if (current_player == -1) { best_score = beta; for (int i = 1; i < 8; ++i) { if (valid_move(i)) { play(current_player, i); int score = minimax(alpha, best_score, -current_player, game_board, depth); if (score < best_score) best_score = score; revert(current_player, i); if (best_score <= alpha) { break; } } } } return best_score; }
/*Minimax*/ int minimax(int giocatore, int profondita) { if(controlla(2)) return INT_MAX; if(controlla(1)==-1) return INT_MIN; int res,tmp; if(giocatore==1) { res=1; for(i=0; i<M; i++) { for(k=0; k<M; k++) { if(!tabella[i][k]) { tabella[i][k]=1; if(controlla(1)) { if(profondita==20) { tabella[i][k]=0; return INT_MIN; } else res-=2; } else if(((tmp=minimax(2,profondita-1))<res) || (tmp==INT_MIN)) res=tmp; tabella[i][k]=0; } } } } else { res=-1; for(i=0; i<M; i++) { for(k=0; k<M; k++) { if(!tabella[i][k]) { tabella[i][k]=2; if(controlla(2)) res+=2; else if(((tmp=minimax(1,profondita-1))>res) || (tmp==INT_MAX)) res=tmp; tabella[i][k]=0; } } } } return res; }
/*------------------------------------------------------------------------------*\ ( ) - \*------------------------------------------------------------------------------*/ void BmTextControl::InitSize( const char* label, int32 fixedTextLen, int32 minTextLen, BmMenuControllerBase* popup) { ResizeToPreferred(); BRect b = Bounds(); float divPos = 0; if (label) divPos = StringWidth(label) + (mLabelIsMenu ? 27 : 3); inherited::SetDivider( divPos); BFont font; mTextView->GetFont( &font); if (fixedTextLen) { mTextView->SetMaxBytes( fixedTextLen); float width = divPos + font.StringWidth("W")*float(fixedTextLen); ct_mpm = minimax( int(width), int(b.Height()+4), int(width), int(b.Height()+4)); } else { if (minTextLen) ct_mpm = minimax( int(divPos + font.StringWidth("W")*float(minTextLen)), int(b.Height()+4), 100000, int(b.Height()+4)); else ct_mpm = minimax( int(divPos + font.StringWidth("W")*10), int(b.Height()+4), 100000, int(b.Height()+4)); } if (mLabelIsMenu) { float width, height; GetPreferredSize( &width, &height); // if (!popup) // popup = new BmMenuControllerBase( label, true, false); if (BeamOnDano) mMenuField = new BMenuField( BRect( 2,2,Divider(),height), NULL, label, popup, true, B_FOLLOW_NONE, B_WILL_DRAW); else mMenuField = new BMenuField( BRect( 2,0,Divider(),height), NULL, label, popup, true, B_FOLLOW_NONE, B_WILL_DRAW); mMenuField->SetDivider( 0); AddChild( mMenuField); } SetModificationMessage( new BMessage(BM_TEXTFIELD_MODIFIED)); }
void makeComputerMove() { GLint currMaxPts=0; //array of maximum points associated with a move GLint newMaxPts=0; //array of maximum points associated with a move GLint currMaxSlot=-1; //make the move gamePiece player= player1Turn==true?player1GamePiece:player2GamePiece; vector<int> alphaBeta(2); alphaBeta[0] = -2; alphaBeta[1] = 2; Outcome best = minimax( (int)player, game, alphaBeta,0 ); makeMove(Move(best.second.first,best.second.second),player); }
minmax_t Minimax::minimax(Node * node, unsigned int depth, bool isMax) { if (depth == 0 || node->isLeaf()) { node->setHeuristic(getHeuristic(node->getMove())); minmax_t ret; ret.node = node; ret.heuristc = node->getHeuristic(); return ret; } if (isMax) { uint8_t best = INT8_MAX; for (int i = 0; i < node->getLength(); ++i) { minmax_t val = minimax(node->getNodeAt(i), depth - 1, true); best = std::min(best, val.heuristc); } minmax_t ret; ret.node = node; ret.heuristc = best; return ret; } else { uint8_t best = INT8_MIN; for (int i = 0; i < node->getLength(); ++i) { minmax_t val = minimax(node->getNodeAt(i), depth - 1, false); best = std::max(best, val.heuristc); } minmax_t ret; ret.node = node; ret.heuristc = best; return ret; } }
int minimax(int b[3][3], int player) { int val = check_win(b); int i, j; int points = 25, move_points = 0; if(player == 1) points = -points; if(val || board_full(b)) { return val; } for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) { if(!b[i][j]) { if(player == -1) { b[i][j] = -1; move_points = minimax(b, 1); if(points > move_points) { points = move_points; } } else { b[i][j] = 1; move_points = minimax(b, -1); if(points < move_points) { points = move_points; } } b[i][j] = 0; } } } return points; }
//Minimax, performs the minimax algorithm from the node down to the depth specified int minimax(struct BFTreeNode* node, int depth, int player) { int value; struct QueueNode* child; //THE FOLLOWING PART WONT WORK FOR CONSECUTIVE TURNS... (but maybe that's moot?) if (node->nodeWrapped->evaluation != NULL ) { return node->nodeWrapped->evaluation; } // Return if at the bottom. if (depth == 0 || node->nodeWrapped->children->length == 0) { node->nodeWrapped->evaluation = getEvaluation(node); return node->nodeWrapped->evaluation; } // Recursively call and pass up the max or the min dependent on the player if (player == MAX_PLAYER) { int bestValue = INT_MIN; child = node->nodeWrapped->children->head; while (child) { value = minimax(child->thisNode, depth - 1, MIN_PLAYER); bestValue = max(bestValue, value); child = child->nextNode; } node->nodeWrapped->evaluation = bestValue; return bestValue; } else { int bestValue = INT_MAX; child = node->nodeWrapped->children->head; while (child) { value = minimax(child->thisNode, depth - 1, MAX_PLAYER); bestValue = min(bestValue, value); child = child->nextNode; } node->nodeWrapped->evaluation = bestValue; return bestValue; } }
int main(){ board_t board; stdin_to_board(&board); long int count = 0; int best_outcome; turn_t* best_turn = minimax(&board, 0, &best_outcome, &count, 0); stats(&board, best_turn, best_outcome, count); cleanup(&board); return 0; }
/*------------------------------------------------------------------------------*\ ( ) - \*------------------------------------------------------------------------------*/ BmToolbarButton::BmToolbarButton( const char *label, float width, float height, BMessage *message, BHandler *handler, const char* tipText, bool needsLatch, const char* resourceName) : inherited( minimax( int(width), int(height), -1 ,-1), &BmDummyPicture, &BmDummyPicture, message, handler) , mHighlighted( false) , mNeedsLatch( needsLatch) , mUpdateVariationsFunc( NULL) , mLabel( label) , mResourceName( resourceName ? resourceName : label) { SetFlags(Flags() & ~B_NAVIGABLE); TheBubbleHelper->SetHelp( this, tipText); }
/*------------------------------------------------------------------------------*\ ( ) - \*------------------------------------------------------------------------------*/ void BmToolbarButton::CreateAllPictures( float width, float height) { ct_mpm = minimax( int(width), int(height), -1, -1); BPicture* off_pic = CreatePicture( STATE_OFF, width, height); BPicture* on_pic = CreatePicture( STATE_ON, width, height); BPicture* dis_pic = CreatePicture( STATE_DISABLED, width, height); SetEnabledOff( off_pic); SetEnabledOn( on_pic); SetDisabledOff( dis_pic); delete off_pic; delete on_pic; delete dis_pic; }
/* find and return the best computer's next move acording to minimax algorithm. * in case of an error - return a move with .steps_len = -1 * (envelope function that calls minimax()) */ moves best_next_moves(settings set, int maximizer) { // minimax function moves best_moves = { 0 }; move * temp_best_move; moves possible_moves = make_all_moves(&set); int best_score = INT_MIN; int curr_alpha = INT_MIN; if (possible_moves.len == -1) { //error return possible_moves; } int is_best_difficulty = (set.minimax_depth == BEST_DIFFICULTY); int depth = (!is_best_difficulty) ? set.minimax_depth : get_best_depth(&set, maximizer); move_node * curr = possible_moves.first; while (curr != NULL) { //get the score of each next possible moves, according to minimax algorithm settings next_set; memcpy(&next_set, &set, sizeof(settings)); next_set.next = other_player(set.next); board_copy(((move*)curr->data)->board, next_set.board); int curr_score = minimax(next_set, curr_alpha, INT_MAX, FALSE, depth - 1, is_best_difficulty); if (curr_score == SCORE_ERROR) { free_list(&possible_moves, &free); free_list(&best_moves, &free); return error_moves; } if (curr_score > curr_alpha) curr_alpha = curr_score; temp_best_move = curr->data; if (curr_score > best_score) { // if new score is higher - free previous best moves free_list(&best_moves, &free); best_score = curr_score; } if (!(curr_score < best_score)) { if (!add_node(&best_moves, temp_best_move, sizeof(move))) { free_list(&best_moves, &free); free_list(&possible_moves, &free); return error_moves; } } curr = curr->next; } free_list(&possible_moves, &free); if (DEBUG) printf("CHOSEN SCORE: %d\n", best_score); return best_moves; }
int main() { /* Set up global variables: board and best move */ int i; char **board = (char **) malloc (sizeof(char *) * 3); for (i=0; i<3; i++) { board[i] = (char *) malloc (sizeof(char) * 3); } /* Begin the game by printing usage instructions and initializing the board */ print_usage(); init_board(board); /* Play the game */ int hor, vert, alpha; move best_move = (move) malloc (sizeof(struct legal_move)); print_board(board); while (!game_over(board) && (!someone_wins(board, 'X'))) { scanf("%d %d", &hor, &vert); hor -= 1; // adjust input values to match array indeces vert -= 1; if ((hor > 2) || (vert > 2) || (hor < 0) || (vert < 0)) { printf("Sorry, that square does not exist.\n"); } else if (board[hor][vert] != '-') { printf("Sorry, that square is already occupied.\n"); } else { update_board(board, hor, vert, 0); printf("The position after your last move:\n"); print_board(board); alpha = minimax(board, 1, best_move); update_board(board, best_move -> hor, best_move -> vert, 1); printf("The position after the computer's last move:\n"); print_board(board); } } if (someone_wins(board, 'X')) { ai_wins(); } else { cats_game(); } return 0; // control should never reach here }
int main() { char matrix[3][3][3][3]; char main_matrix[3][3]; int iplay,jplay,turn,move; char temp; scanf("%c",&turn); scanf("%c",&temp); scanf("%d %d",&iplay,&jplay); scanf("%c",&temp); int i,j,k,l,a,b,c,d; for(i=0;i<3;i++) { for(j=0;j<3;j++) { for(k=0;k<3;k++) { for(l=0;l<3;l++) { scanf("%c",&matrix[i][k][j][l]); if(matrix[i][k][j][l]=='X')matrix[i][k][j][l]='x'; else if(matrix[i][k][j][l]=='O')matrix[i][k][j][l]='o'; else if(matrix[i][k][j][l]=='-')matrix[i][k][j][l]='s'; } } scanf("%c",&temp); } } for (i=0;i<3;i++) { for(j=0;j<3;j++) { main_matrix[i][j]=check_winner(matrix[i][j]); } } struct Node *root= (struct Node *) malloc(sizeof(struct Node)); move=minimax(root,turn,matrix,main_matrix,iplay,jplay,1,1,82); a=move/1000; b=move/100 - a*10; c=move/10 - a*100 - b*10; d=move-a*1000 - b*100 - c*10; printf("%d %d %d %d",a,b,c,d); return 0; }
int turn_ia(t_env *e) { board_insert(e, minimax(e, MAX_DEPTH), 2); e->counter_ai--; if (check_win(e, 2) == 1) { disp_win(e, AI); return (1); } if (board_complete(e) == 1 || (e->counter_ai == 0 && e->counter_hu == 0 && check_win(e, 2) == 0)) { disp_win(e, NONE); return (1); } board_disp(e); return (0); }