Noam_15

ארבע בשורה אדם נגד מחשב - די חכם

Jul 5th, 2017
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.03 KB | None | 0 0
  1. // V0.40 // ארבע בשורה אדם נגד מחשב
  2. #include <iostream>
  3. #include <windows.h>
  4. #include <ctime> // עבור מספר רנדומלי
  5. // #define Difficulty  5
  6. using namespace std;
  7. int Difficulty;
  8.  
  9.  
  10. //  מדריך צבעים https://www.youtube.com/watch?v=IXtm7cI21vM
  11. void setcolor(unsigned short color){
  12.     HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
  13.     SetConsoleTextAttribute(hcon, color);
  14. }
  15.  
  16.  
  17. enum status{empty, white, black};
  18. enum status main_board [7][6]; ///  i,j     // הוא 0 j השורה הכי עליונה היא השורה בה
  19.  
  20. void reset_board(enum status board [7][6]){
  21.     for(int i=0; i<7; i++){
  22.         for(int j=0; j<6; j++){
  23.             board[i][j] = empty;
  24.         }
  25.     }
  26. }
  27.  
  28. enum status get_Color_at_the_top_position(enum status board [7][6], int loc){ // show פונקצית עזר ל
  29.     for(int j=0; j<6; j++){
  30.         if(board[loc][j] == empty) continue;
  31.         return board[loc][j];
  32.     }
  33.     cout<<"error in get_Color_at_the_top_position\n";
  34.     return empty; // שורה מיותר ליתר ביטחון אם מקבלים עמודה ריקה
  35. }
  36.  
  37. void show(enum status board [7][6], int lastLoc = -1){
  38.     cout<<"\n\n";
  39.     if(lastLoc==-1) cout<<"1 2 3 4 5 6 7";
  40.     else{ // כל זה על מנת להציד איפה הניח התור הקודם
  41.         enum status lastStat = get_Color_at_the_top_position(board, lastLoc);
  42.         for(int i=0; i<7; i++) {
  43.             if(i!=lastLoc) cout<<i+1<<" ";
  44.             else{
  45.                 if(lastStat == white){
  46.                     setcolor(11);
  47.                     cout<<i+1<<" ";
  48.                     setcolor(7);
  49.                 }
  50.                 else{
  51.                     setcolor(12);
  52.                     cout<<i+1<<" ";
  53.                     setcolor(7);
  54.                 }
  55.             }
  56.         }
  57.     }
  58.     cout<<"\n_____________\n";
  59.     for(int j=0; j<6; j++){
  60.         for(int i=0; i<7; i++){
  61.             if(board[i][j]== empty) cout<<"O ";
  62.             else if (board[i][j]== white) {
  63.                 setcolor(11);
  64.                 cout<<"O ";  // w
  65.                 setcolor(7);
  66.             }
  67.             else {
  68.                 setcolor(12);
  69.                 cout<<"O "; // b
  70.                 setcolor(7);
  71.             }
  72.         }
  73.         cout<<"\n";
  74.     }
  75.     cout<<"\n";
  76. }
  77.  
  78.  
  79. int get_from_player(enum status stat){
  80.     if (stat==white) cout<<"-White move.\n";
  81.     else cout<<"-Black move.\n";
  82.  
  83.     int location;
  84.     cout <<"Enter location:  ";
  85.     cin>> location;
  86.     while(location<1 || location>7 ||  main_board[location-1][0] != empty){
  87.         cout<<"Please enter a legal location:  ";
  88.         cin >> location;
  89.     }
  90.     cout<<"\n";
  91.     return location-1;
  92. }
  93.  
  94. void Put_in_a_move(enum status board [7][6], int location, enum status stat){
  95.     for(int j=5; j>=0; j--){
  96.         if (board[location][j] == empty){
  97.             board[location][j] = stat;
  98.             break;
  99.         }
  100.     }
  101. }
  102.  
  103. enum status Victory_check (enum status board [7][6]){
  104.  
  105.     for(int j=5; j>=0; j--){
  106.         for(int i=0; i<4; i++){
  107.             if (board[i][j]==empty) continue;
  108.             for(int b=i+1, q=0; q<3; q++, b++){
  109.                 if (board[i][j]!=board[b][j]) break;
  110.                 if(q==2) return board[i][j];
  111.             }
  112.         }
  113.     }
  114.     // עד כאן בדיקת ניצחונות אופקיים
  115.  
  116.  
  117.     for(int i=0; i<7; i++){
  118.         for(int j=5; j>2; j--){
  119.             if (board[i][j]==empty) continue;
  120.  
  121.             for(int b=j-1, q=0; q<3; q++, b--){
  122.                 if (board[i][j]!=board[i][b]) break;
  123.                 if(q==2) return board[i][j];
  124.             }
  125.         }
  126.     }
  127.     // עד כאן בדיקת ניצחונות ישרים
  128.  
  129.  
  130.  
  131.     for(int j=5; j>2; j--){
  132.         for(int i=0; i<4; i++){
  133.             if (board[i][j]==empty) continue;
  134.             for(int q=1; q<4; q++){
  135.                 if (board[i][j]!=board[i+q][j-q]) break;
  136.                 if(q==3) return board[i][j];
  137.             }
  138.         }
  139.     }
  140.     // עד כאן אלכסון משמאל נמוך לימין גבוה
  141.  
  142.  
  143.     for(int j=5; j>2; j--){
  144.         for(int i=3; i<7; i++){
  145.             if (board[i][j]==empty) continue;
  146.             for(int q=1; q<4; q++){
  147.                 if (board[i][j]!=board[i-q][j-q]) break;
  148.                 if(q==3) return board[i][j];
  149.             }
  150.         }
  151.     }
  152.     // עד כאן אלכסון מימין נמוך לשמאל גבוה
  153.    
  154.     return empty;
  155. }
  156.  
  157.  
  158.  
  159.  
  160.     /* מכאן פונקציות לאדם נגד מחשב */
  161.  
  162.  
  163.  
  164. void clear_location(enum status board [7][6], int loc){
  165.         for(int j=0; j<6; j++){
  166.         if (board[loc][j] != empty){
  167.             board[loc][j] = empty;
  168.             break;
  169.         }
  170.     }
  171. }
  172.  
  173. int get_first_empty_location_with_bad_array(enum status board [7][6], int arr[7]){
  174.     for(int i=0; i<7; i++){
  175.         if(board[i][0]!=empty || arr[i] == -1)continue;
  176.         return i;
  177.     }
  178.     cout<<"Error in get_first_empty_location_with_bad_array\n";
  179. }
  180.  
  181. int get_first_empty_location(enum status board [7][6]){
  182.     for(int i=0; i<7; i++){
  183.         if(board[i][0]!=empty)continue;
  184.         return i;
  185.     }
  186.     cout<<"Error in get_first_empty_location\n";
  187.     return -1;
  188. }
  189.  
  190.  
  191. int get_random_location(enum status board [7][6], int arr[7] = NULL){
  192.     int x;
  193.     int fan = 0;
  194.     if(arr==NULL){
  195.         while(1){
  196.             x = rand() % 11;
  197.             if(x==10)x=3;
  198.             else if(x>6) x-=5;
  199.             if(board[x][0]!=empty) continue;
  200.             return x;
  201.         }
  202.     }
  203.     else{
  204.         while(1){
  205.             fan++;
  206.             if (fan==2000) {
  207.                 cout<<"ERROR2\nARRAY BAD:\n";
  208.                 for(int i=0; i<7; i++){
  209.                     if(arr[i]==-1)cout<<i<<". ";
  210.                 }cout<<"\n";
  211.                 show(board);
  212.             }
  213.             x = rand() % 11;
  214.             if(x==10)x=3;
  215.             else if(x>6) x-=5;
  216.             if(arr[x]==-1) continue;
  217.             if(board[x][0]!=empty)continue;
  218.             return x;
  219.         }
  220.     }
  221.  
  222.  
  223. }
  224.  
  225. int check_for_winning_location(enum status board [7][6], enum status stat){
  226.     enum status VictoryFlag = empty;
  227.     for(int i=0; i<7; i++){
  228.         if(board[i][0] != empty) continue;
  229.         Put_in_a_move(board, i, stat);
  230.         VictoryFlag = Victory_check(board);
  231.         clear_location(board, i); // מחזירים את הלוח לאיך שהוא היה לפני השינוי
  232.         if(VictoryFlag == stat) return i;
  233.     }
  234.     return -1; // המשמעות היא שאין מיקום שיניב ניצחון לצבע הזה
  235. }
  236.  
  237. void copy_boards(enum status board1 [7][6], enum status board2 [7][6]){
  238.     for (int i=0; i<7; i++)
  239.         for(int j=0; j<6; j++)
  240.             board1 [i][j] = board2 [i][j];
  241. }
  242.  
  243.  
  244.  
  245.  
  246. int get_from_AI(enum status board [7][6], enum status stat, int Count_of_actions, int diff){
  247.     int loc;
  248.     enum status enemy_color = (stat==white)? black : white;
  249.    
  250.     //if(Count_of_actions == 42) return -1;
  251.     if (Count_of_actions == 0 || Count_of_actions == 1) return 3; // תור ראשון ושני לשים באמצע
  252.     if (Count_of_actions == 2) return (rand()%3)+2; // אחד משלושת המקומות האמצעיים
  253.  
  254.     loc = check_for_winning_location(board, stat); // נצח אם אפשר
  255.     if(loc!=-1) return loc;
  256.     loc = check_for_winning_location(board, enemy_color); // חסום ניצחון מיידי של היריב
  257.     if(loc!=-1) return loc;
  258.    
  259.  
  260.  
  261.     if(Count_of_actions == 41) // הוא המהלך האחרון AI אם זה מתקיים אזי המהלך הנוכחי של ה
  262.         return get_first_empty_location(board); // זה מוצא את המקום הפנוי הראשון והיחיד שנותר
  263.        
  264.     if(diff <= 0) return get_random_location(board);
  265.     if(Count_of_actions >= 3 && Count_of_actions <=6 && diff>3) diff = 3; // כדי שתחילת המשחק לא תהיה איטית
  266.     if(Count_of_actions >= 7 && Count_of_actions <=8 && diff>4) diff = 4;
  267.  
  268.  
  269.  
  270.     int Array_Of_BAD_position[7] = {0}, flag=0; // המערך ממלא ב -1 מקומות שנפסיד אם נשים בהם
  271.     int score=0; //  ככל שיותר גבוה פירושו פחות מהלכים נחוצים עד לניצחון
  272.     enum status tmp_board [7][6];
  273.  
  274.     for(int i=0; i<7; i++){
  275.         int Count_of_actions_TMP = Count_of_actions, diff_TMP = diff;
  276.         copy_boards(tmp_board, board);
  277.         if(tmp_board[i][0]!=empty) continue;
  278.         Put_in_a_move(tmp_board, i, stat);
  279.         Count_of_actions_TMP++;
  280.         goto TAB;
  281.        
  282.         do{
  283.             Put_in_a_move(tmp_board, get_from_AI(tmp_board, stat, Count_of_actions_TMP, diff-1), stat); // מהלך העתידי שלנו
  284.             Count_of_actions_TMP++;
  285.             if( Victory_check(tmp_board) == stat){
  286.                 if(score<diff_TMP) {score = diff_TMP;  loc = i;}
  287.                 break;
  288.             }
  289.             if(Count_of_actions_TMP == 42) break;
  290.  
  291. TAB:
  292.             // מהלך של היריב
  293.             Put_in_a_move(tmp_board, get_from_AI(tmp_board, enemy_color, Count_of_actions_TMP, diff-1), enemy_color); // מהלך העתידי של היריב
  294.             Count_of_actions_TMP++;
  295.             if( Victory_check(tmp_board) == enemy_color){
  296.                 Array_Of_BAD_position[i]=-1;
  297.                 flag++;
  298.                 break;
  299.             }
  300.             if(Count_of_actions_TMP == 42) break;
  301.             diff_TMP--;
  302.         }while(diff_TMP>0);
  303.     }
  304.  
  305.     if(score>0) return loc;
  306.     /*  .כלומר אם יש מקום באמצעותו ננצח בעתיד - נשים שם
  307.     אם יש יותר ממקום אחד לניצחון כזה - נשים במקום שבו הניצחון הכי מהיר   */
  308.  
  309.  
  310.  
  311.     // עכשיו נספור כמה עמודות לא מלאות יש
  312.     int OK_LOC=0;
  313.     for(int i=0; i<7; i++){
  314.         if(board[i][0] == empty) OK_LOC++;
  315.     }
  316.     if(OK_LOC == 0) cout<<"ERROR IN OK_LOC\n";
  317.     if(OK_LOC == flag){ //ברמת קושי קטנה ב1 משלנו AI כלומר כל מקום שנשים בו בסופו של דבר נפסיד נגד יריב
  318.         /*
  319.         אפשר להכניס כאן קוד שבוחר את המקום שיש בו
  320.          AI את הסיכויי הכי גבוה לנצח (כלומר את הסיכוי הכי קטן להפסיד) נגד יריב שאינו
  321.          flag ו Array_Of_BAD_position קוד זה צריך לעשות בדיוק את אותה לולאה שעשינו למעלה אבל בלי החלק של  
  322.  
  323.          תיקון:
  324.          לעשות כך שהוא מחשב גם את כמות השלבים עד להפסד עבור כל הפסד.
  325.          אחרי הלולאה הוא בודק
  326.          אם אין בכלל סיכוי לניצחון - עושה את הפעולה להפסד הכי איטי (אם הכל אותו דבר אז עושה אחד מהם) כמובן
  327.          אם יש סיכוי לניצחון:
  328.             אם יש פחות שלבים עד ניצחון אפשרי הכי מהיר מאשר כמות שלבים עד ההפסד הכי מהיר:
  329.                 עושה פעולה לניצחון אפשרי הכי מהיר.
  330.             אחרת:
  331.                 עושה פעולה להפסד הכי איטי
  332.         */
  333.  
  334.  
  335.  
  336.         /// ניסיון
  337.        
  338.         int Array[7] = {0}, flag=0;
  339.         int score_bad = Difficulty, score_good = 0, loc_good;
  340.         enum status tmp_board [7][6];
  341.  
  342.         for(int i=0; i<7; i++){
  343.             int Count_of_actions_TMP = Count_of_actions, diff_TMP = diff;
  344.             copy_boards(tmp_board, board);
  345.             if(tmp_board[i][0]!=empty) continue;
  346.             Put_in_a_move(tmp_board, i, stat);
  347.             Count_of_actions_TMP++;
  348.             goto TAB2;
  349.  
  350.             do{
  351.                 Put_in_a_move(tmp_board, get_from_AI(tmp_board, stat, Count_of_actions_TMP, diff-1), stat); // מהלך העתידי שלנו
  352.                 Count_of_actions_TMP++;
  353.                 if( Victory_check(tmp_board) == stat){
  354.                     if(score_good<diff_TMP) {score_good = diff_TMP;  loc_good = i;}
  355.                     break;
  356.                 }
  357.                 if(Count_of_actions_TMP == 42) break;
  358.  
  359. TAB2:
  360.                 // מהלך של היריב
  361.                 Put_in_a_move(tmp_board, get_from_AI(tmp_board, enemy_color, Count_of_actions_TMP, diff-1), enemy_color); // מהלך העתידי של היריב
  362.                 Count_of_actions_TMP++;
  363.                 diff_TMP--;
  364.                 if( Victory_check(tmp_board) == enemy_color){
  365.                     if(score_bad>diff_TMP) {score_bad = diff_TMP;  loc = i;}
  366.                     break;
  367.                 }
  368.                 if(Count_of_actions_TMP == 42) break;
  369.             }while(diff_TMP>0);
  370.         }
  371.         if(score_good>0) return loc_good;
  372.         if(score_bad<Difficulty) return loc;
  373.  
  374.  
  375.  
  376.         /// עד כאן ניסיון
  377.         //cout<<"Error in  nisayon 2\n";
  378.         return get_random_location(board); // זו האפשרות למתכנת העצלן
  379.     }
  380.  
  381.  
  382.     if(flag>0) return get_random_location(board, Array_Of_BAD_position);  // מקום אקראי שאינו אחד מהמקומות הרעים
  383.  
  384.     return get_random_location(board); // ייתכן שאפשר לוותר על השורה זאת
  385. }
  386.  
  387. int get_from_AI_with_show(enum status board [7][6], enum status stat, int Count_of_actions, int diff = Difficulty){
  388.     if (stat==white) cout<<"-White AI move...\n";
  389.     else cout<<"-Black AI move...\n";
  390.     //Sleep(1100);
  391.     Sleep(600);
  392.  
  393.     int location = get_from_AI(board, stat, Count_of_actions, diff);
  394.     cout <<"location (AI):  "<<location+1<<"\n\n";
  395.     Beep(540,80);
  396.     return location;
  397. }
  398.  
  399.  
  400. void main(){
  401.     srand(time(0)); // עבור מספר רנדומלי
  402.     enum status VictoryFlag = empty;
  403.     char strMODE[10];
  404.     reset_board(main_board);
  405.  
  406.     int Count_of_actions = 0, loc=-1; //  לא תציג צבע בלופ ראשון show מאותחל ל -1 כדי שהפונקציה loc המשתנה
  407.     do{
  408.         cout<<"AI or Friend mode (A/F): ";
  409.         cin>>strMODE;
  410.     }while(strMODE[0] != 'a' && strMODE[0] != 'A' && strMODE[0] != 'f' && strMODE[0] != 'F');
  411.  
  412.  
  413.     if(strMODE[0] == 'f' || strMODE[0] == 'F'){ // אם זה אדם נגד אדם
  414.         do{
  415.             show(main_board, loc);
  416.             loc = get_from_player(white);
  417.             Put_in_a_move(main_board, loc, white);
  418.             VictoryFlag = Victory_check(main_board);
  419.             if (VictoryFlag != empty) break;
  420.             Count_of_actions++;
  421.             if(Count_of_actions==42) break;
  422.  
  423.             show(main_board, loc);
  424.             loc = get_from_player(black);
  425.             Put_in_a_move(main_board, loc, black);
  426.             VictoryFlag = Victory_check(main_board);
  427.             if (VictoryFlag != empty) break;
  428.             Count_of_actions++;
  429.  
  430.         }while(Count_of_actions<42);
  431.     }
  432.  
  433.     else{ // אם זה אדם נגד מחשב
  434.         do{
  435.             cout<<"Select level [A/B/C/D]: ";
  436.             cin>>strMODE;
  437.         }while(!((strMODE[0] >= 'a' && strMODE[0] <= 'e') || (strMODE[0] >= 'A' && strMODE[0] <= 'E'))); // רק המתכנת יודע שאפשר, אבל מאוד איטי E
  438.         if(strMODE[0] >='A' && strMODE[0] <='Z') Difficulty = strMODE[0] - 'A' + 2;
  439.         else Difficulty = strMODE[0] - 'a' + 2;
  440.  
  441.  
  442.         do{
  443.             cout<<"First or second? (F/S): ";
  444.             cin>>strMODE;
  445.         }while(strMODE[0] != 's' && strMODE[0] != 'S' && strMODE[0] != 'f' && strMODE[0] != 'F');
  446.  
  447.  
  448.         if(strMODE[0] == 's' || strMODE[0] == 'S') goto S_TART;
  449.         do{
  450.             show(main_board, loc);
  451.             loc = get_from_player(white);
  452.             Put_in_a_move(main_board, loc, white);
  453.             VictoryFlag = Victory_check(main_board);
  454.             if (VictoryFlag != empty) break;
  455.             Count_of_actions++;
  456.             if(Count_of_actions==42) break;
  457.  
  458. S_TART:
  459.             show(main_board, loc);
  460.             loc = get_from_AI_with_show(main_board, black, Count_of_actions);
  461.             Put_in_a_move(main_board, loc, black);
  462.             VictoryFlag = Victory_check(main_board);
  463.             if (VictoryFlag != empty) break;
  464.             Count_of_actions++;
  465.  
  466.         }while(Count_of_actions<42);
  467.     }
  468.  
  469.     show(main_board, loc);
  470.     if (VictoryFlag==white) {setcolor(11); cout<<"White won!!!!!\n\n\n\n"; setcolor(7);}
  471.     else if (VictoryFlag==black) {setcolor(12); cout<<"Black won!!!!!\n\n\n\n"; setcolor(7);}
  472.     else {setcolor(15); cout<<"End! No win.\n\n\n\n"; setcolor(7);}
  473. }
Advertisement
Add Comment
Please, Sign In to add comment