diff --git a/helpers/helpers.c b/helpers/helpers.c
index 8d5a750811b485ed539fb9399117e83b6231c226..0cceed2ebf0e843a260cd1272337e221866efa19 100755
--- a/helpers/helpers.c
+++ b/helpers/helpers.c
@@ -62,12 +62,12 @@ void request_cofig(int *size, int *mode)
     printInColor("white", "please choose game mode:\n");
     printf("-[1] for player vs player normal mode\n");
     printf("-[2] for player vs computer normal mode \n");
-    printf("-[3] for player vs computer smartAI Machine start the game (MIN_MAX)\n");
-    printf("-[4] for player vs computer smartAI Player start the game (MIN_MAX)\n");
+    printf("-[3] for player vs computer smartAI Minimax (normal)\n");
+    printf("-[4] for player vs computer smartAI  Minimax (Alpha beta)\n");
     printf("---------------------------------------------------------------------------\n");
     scanf("%d", mode);
 
-    while (*mode <= 0 || *mode > 5)
+    while (*mode <= 0 || *mode > 4)
     {
         printInColor("red", "please choose the correct option ! \n");
         printInColor("white", " ");
diff --git a/main.c b/main.c
index 66a3b24cca62f44c051fd6d11786615da55d9918..1ead9566768f61b3913f15e162d9dc3734a8cbca 100755
--- a/main.c
+++ b/main.c
@@ -11,7 +11,7 @@ int main()
 {
 
     int size, mode;
-    request_cofig(&size, &mode);
+    request_cofig(&size, &mode); // display menu & request bord size
 
     board brd = board_alloc(size, size);
     switch (mode)
@@ -23,14 +23,10 @@ int main()
         player_random_AI(brd);
         break;
     case 3:
-        player_vs_smart_ai_mini_max_machine_start(brd);
+        player_vs_smart_ai_mini_max(brd, false);
         break;
     case 4:
-        player_vs_smart_ai_mini_max_player_start(brd);
-        break;
-
-    case 5:
-        ai_vs_ai(brd);
+        player_vs_smart_ai_mini_max(brd, true);
         break;
 
     default:
diff --git a/play/play.c b/play/play.c
index 2df0ae2daf7cc693508eaffef2039452390883f6..688a1ffb605597d5985ff9ea116d5a3ed0a4fc47 100755
--- a/play/play.c
+++ b/play/play.c
@@ -292,29 +292,81 @@ int remaining_case(board brd)
 
 int min(int a, int b)
 {
-    return (a < b) ? a : b;
+    return (a <= b) ? a : b;
 }
 
 int max(int a, int b)
 {
-    return (a > b) ? a : b;
+    return (a >= b) ? a : b;
 }
 
 int mini_max(board brd, bool is_max, int depth)
 {
 
-    if (brd->row >= 4)
+    int score = evaluate(brd);
+
+    // if maximizer has won
+    if (score == 1)
+        return score * (remaining_case(brd) + 1);
+
+    // if minimizer has won
+    if (score == -1)
+        return score * (remaining_case(brd) + 1);
+
+    if (board_is_full(brd))
+    {
+        return 0;
+    }
+    if (is_max)
+    {
+        int best_score = _MIN_INF_;
+        for (int i = 0; i < brd->row; i++)
+        {
+            for (int j = 0; j < brd->col; j++)
+            {
+                // the case is available
+                if (case_is_available(brd->matrix[i][j]))
+                {
+                    // make a move
+                    add_to_board(brd, i + 1, j + 1, PC);
+
+                    // calculate score of this move
+                    best_score = max(best_score, mini_max(brd, false, depth + 1));
+                    // undo move
+                    add_to_board(brd, i + 1, j + 1, (char)0);
+                }
+            }
+        }
+        return best_score;
+    }
+    else
     {
-        if (depth >= 7)
+        int best_score = _MAX_INF_;
+
+        for (int i = 0; i < brd->row; i++)
         {
-            return 0;
+            for (int j = 0; j < brd->col; j++)
+            {
+                // the case is available
+                if (case_is_available(brd->matrix[i][j]))
+                {
+                    // make a move
+                    add_to_board(brd, i + 1, j + 1, PLAYER);
+
+                    best_score = min(best_score, mini_max(brd, true, depth + 1));
+                    // undo move
+                    add_to_board(brd, i + 1, j + 1, (char)0);
+                }
+            }
         }
+        return best_score;
     }
+}
+int mini_max_alpha(board brd, bool is_max, int depth, int *alpha, int *beta)
+{
 
     int score = evaluate(brd);
 
-    // if the board is full
-
     // if maximizer has won
     if (score == 1)
         return score * (remaining_case(brd) + 1);
@@ -323,8 +375,10 @@ int mini_max(board brd, bool is_max, int depth)
     if (score == -1)
         return score * (remaining_case(brd) + 1);
 
-    if (board_is_full(brd))
+    if (board_is_full(brd) || depth == brd->row)
+    {
         return 0;
+    }
     if (is_max)
     {
         int best_score = _MIN_INF_;
@@ -339,9 +393,17 @@ int mini_max(board brd, bool is_max, int depth)
                     add_to_board(brd, i + 1, j + 1, PC);
 
                     // calculate score of this move
-                    best_score = max(best_score, mini_max(brd, false, depth + 1));
+                    best_score = max(best_score, mini_max_alpha(brd, false, depth + 1, alpha, beta));
+                    // int score = mini_max(brd, false, depth + 1, alpha, beta);
                     // undo move
                     add_to_board(brd, i + 1, j + 1, (char)0);
+                    // best_score = max(score, best_score);
+
+                    *alpha = max(*alpha, best_score);
+                    if (best_score >= *beta)
+                    {
+                        return best_score;
+                    }
                 }
             }
         }
@@ -361,11 +423,15 @@ int mini_max(board brd, bool is_max, int depth)
                     // make a move
                     add_to_board(brd, i + 1, j + 1, PLAYER);
 
-                    // calculate score of this move
-                    best_score = min(best_score, mini_max(brd, true, depth + 1));
-
+                    best_score = min(best_score, mini_max_alpha(brd, true, depth + 1, alpha, beta));
                     // undo move
                     add_to_board(brd, i + 1, j + 1, (char)0);
+
+                    *beta = min(*beta, best_score);
+                    if (best_score <= *alpha)
+                    {
+                        return best_score;
+                    }
                 }
             }
         }
@@ -402,13 +468,16 @@ void make_move(board brd, bool turn, int *i, int *j)
     *j = tmp_j;
 }
 
-void best_move(board brd)
+void best_move(board brd, bool machine_starts, bool prun)
 {
     int best_score = _MIN_INF_;
     move bst_move;
     bst_move.row = -1;
     bst_move.col = -1;
 
+    int alpha = _MIN_INF_;
+    int beta = _MAX_INF_;
+
     // for available case add and undo -> to see best score
     for (int i = 0; i < brd->row; i++)
     {
@@ -421,8 +490,8 @@ void best_move(board brd)
                 add_to_board(brd, i + 1, j + 1, PC);
 
                 // find max score
-                int score = mini_max(brd, false, 0);
-                printf("row: %d col: %d score : %d\n", i, j, score);
+                int score = (prun) ? mini_max_alpha(brd, machine_starts, 0, &alpha, &beta) : mini_max(brd, !machine_starts, 0);
+
                 // undo move
                 add_to_board(brd, i + 1, j + 1, (char)0);
                 // find the case with max probab
@@ -569,12 +638,27 @@ void player_random_AI(board brd)
         }
     }
 }
-
-void player_vs_smart_ai_mini_max_machine_start(board brd)
+void player_vs_smart_ai_mini_max(board brd, bool prun)
 {
     bool win = false;
     bool turn = true; // computer starts
 
+    printInColor("blue", "who starts the game :\n");
+    printInColor("white", "[1] : you\n[2]: Machine ? \n");
+    int t;
+    bool machin_start = false;
+    scanf("%d", &t);
+
+    if (t == 1)
+    {
+        turn = false;
+    }
+    else
+    {
+        turn = true;
+        machin_start = true;
+    }
+
     while (!win)
     {
         bool is_full = board_is_full(brd);
@@ -582,7 +666,7 @@ void player_vs_smart_ai_mini_max_machine_start(board brd)
         {
             if (turn)
             {
-                best_move(brd);
+                best_move(brd, machin_start, prun);
                 print_board(brd);
 
                 if (evaluate(brd) == 1)
@@ -628,198 +712,3 @@ void player_vs_smart_ai_mini_max_machine_start(board brd)
         }
     }
 }
-
-void player_vs_smart_ai_mini_max_player_start(board brd)
-{
-
-    bool win = false;
-
-    while (!win)
-    {
-
-        bool is_full = board_is_full(brd);
-        if (!is_full)
-        {
-            int row, col;
-            printf("please choose the case by [row][col] :\n");
-            scanf("%d %d", &row, &col);
-
-            if (case_is_available(brd->matrix[row - 1][col - 1]))
-            {
-                add_to_board(brd, row, col, PLAYER);
-                print_board(brd);
-
-                if (evaluate(brd) == -1)
-                {
-                    printf("you win the game !!!\n");
-                    return;
-                }
-                // continue;
-            }
-            else
-            {
-                printInColor("red", "choose another box this box is taking\n");
-                printInColor("white", " ");
-                continue;
-            }
-
-            if (!board_is_full(brd))
-            {
-
-                best_move(brd);
-                print_board(brd);
-
-                if (evaluate(brd) == 1)
-                {
-                    printf("computer win the game !!!");
-                    return;
-                }
-            }
-        }
-        else
-        {
-            printf("the game is draw !!! \n");
-            return;
-        }
-    }
-}
-
-int min_max_double(board brd, bool is_max, int depth, bool turn)
-{
-
-    if (brd->row >= 4)
-    {
-        if (depth > 8)
-        {
-            return 0;
-        }
-    }
-
-    int score = evaluate(brd);
-
-    // if the board is full
-
-    // if maximizer has won
-    if (score == 1)
-        return score * (remaining_case(brd) + 1);
-
-    // if minimizer has won
-    if (score == -1)
-        return score * (remaining_case(brd) + 1);
-
-    if (board_is_full(brd))
-        return 0;
-    if (is_max)
-    {
-        int best_score = _MIN_INF_;
-        for (int i = 0; i < brd->row; i++)
-        {
-            for (int j = 0; j < brd->col; j++)
-            {
-                // the case is available
-                if (case_is_available(brd->matrix[i][j]))
-                {
-                    // make a move
-                    add_to_board(brd, i + 1, j + 1, (turn) ? PC : PLAYER);
-
-                    // calculate score of this move
-                    best_score = max(best_score, mini_max(brd, false, depth + 1));
-                    // undo move
-                    add_to_board(brd, i + 1, j + 1, (char)0);
-                }
-            }
-        }
-        return best_score;
-    }
-    else
-    {
-        int best_score = _MAX_INF_;
-
-        for (int i = 0; i < brd->row; i++)
-        {
-            for (int j = 0; j < brd->col; j++)
-            {
-                // the case is available
-                if (case_is_available(brd->matrix[i][j]))
-                {
-                    // make a move
-                    add_to_board(brd, i + 1, j + 1, (turn) ? PC : PLAYER);
-
-                    // calculate score of this move
-                    best_score = min(best_score, mini_max(brd, true, depth + 1));
-
-                    // undo move
-                    add_to_board(brd, i + 1, j + 1, (char)0);
-
-                    // min(score, best_score_score);
-                }
-            }
-        }
-        return best_score;
-    }
-}
-
-void best_move_o(board brd, bool turn)
-{
-    int best_score = _MIN_INF_;
-    move bst_move;
-    bst_move.row = -1;
-    bst_move.col = -1;
-
-    // for available case add and undo -> to see best score
-    for (int i = 0; i < brd->row; i++)
-    {
-        for (int j = 0; j < brd->col; j++)
-        {
-            // the case is available
-            if (case_is_available(brd->matrix[i][j]))
-            {
-                // add move to evalaute
-                add_to_board(brd, i + 1, j + 1, (turn) ? PC : PLAYER);
-
-                // find max score
-                int score = min_max_double(brd, false, 0, turn);
-                printf("row: %d col: %d score : %d\n", i, j, score);
-                // undo move
-                add_to_board(brd, i + 1, j + 1, (char)0);
-                // find the case with max probab
-                if (score > best_score)
-                {
-                    bst_move.row = i;
-                    bst_move.col = j;
-                    best_score = score;
-                }
-            }
-        }
-    }
-    add_to_board(brd, bst_move.row + 1, bst_move.col + 1, (turn) ? PC : PLAYER);
-
-    printf("\nmove : %d move : %d\n", bst_move.row, bst_move.col);
-}
-void ai_vs_ai(board brd)
-{
-    bool win = false;
-    bool turn = true;
-    while (!win)
-    {
-
-        bool is_full = board_is_full(brd);
-        if (!is_full)
-        {
-            best_move_o(brd, !turn);
-            print_board(brd);
-            sleep(1);
-            turn = !turn;
-            if (evaluate(brd) == 1)
-            {
-                printf("pc 1 win the game !!!");
-                return;
-            }
-        }
-        else
-        {
-            printf("the game is draw !!! \n");
-            return;
-        }
-    }
-}
diff --git a/play/play.h b/play/play.h
index 5c7b928a4c5ef4e63d8e114020f8ae9d7215bda5..48d8edda19e8f3d1b5a50facdf15cfaefac3290a 100755
--- a/play/play.h
+++ b/play/play.h
@@ -31,15 +31,14 @@ int check_win(board brd);
 bool case_is_available(char chr);
 void case_to_coordinates(board brd, int cas, int *i, int *j);
 bool board_is_full(board brd);
+
 int mini_max(board brd, bool is_max, int depth);
-void best_move(board brd);
+int mini_max_alpha(board brd, bool is_max, int depth, int *alpha, int *beta);
+void best_move(board brd, bool machine_starts, bool prun);
 
 void two_player(board brd);
 void player_random_AI(board brd);
-void player_vs_smart_ai_mini_max_machine_start(board brd);
-
-void player_vs_smart_ai_mini_max_player_start(board brd);
 
-void ai_vs_ai(board brd);
+void player_vs_smart_ai_mini_max(board brd, bool prun);
 
 #endif
\ No newline at end of file