• 井字棋(人机对战版)


    游戏介绍

    井字棋,英文名叫Tic-Tac-Toe,是一种在3*3格子上进行的连珠游戏,和五子棋类似。然后由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X),任意三个标记形成一条直线(包括行、列、对角线、反对角线),则为获胜。

    解决策略

    重点在于电脑方如何下棋,我们采取估计棋局每个位置的权重,首先要对棋局进行分类。

    ---3个为空,重要性最低,权值设置为1    //视为暂时不管

    ---2个空1个对方,重要性次低,权值为10    //一下三个区别不大,可比较随意的设置

    ----1个空格1个对方1个己方,重要行较低,权值50 

    ----2个空格1个己方,重要性较高,权值为100

    ---1个空格2个对方,重要性次高,权值500  //不堵住会输

    ---1个空格2个己方,重要性最高,权值1000    //可以直接赢

    注意几点:

    1、权值之间的间距可以设大一点

    2、对每个空位置,权值等于行权值+列权值+对角线权值+反对角线权值,这4中权值都可以用上面的估算,但不做改进会出bug

    考虑如下情况:

    (1,3)-->(3,1)-->(1,1)-->(2,1)电脑就输了

    ---->--->-->-->人获胜

    关键在于第二步,应该选择一个非角的位置,原因在于此时右上角位置的权值大于中上位置,分析权值的来源

    右上角时,10+10+100(对角线己方),而中上时,10+100(行己方),所以同样是2空1己方时,己方位于行或列的权重应大于己方位于对角线

    所以按行或列计算时,2空1己方的权值可改为200

    代码实现

      1 #include<stdio.h>
      2 #include<Windows.h>
      3 
      4 const int ROW = 3;
      5 const int COL = 3;
      6 int chessboard[ROW][COL];
      7 int score[ROW][COL];
      8 
      9 void Initmap();
     10 void Showmap();        //打印棋局
     11 bool isWin();        //判断是否有一方获胜
     12 bool isFull();        //判断棋盘是否为满
     13 void PcPlay();        //电脑下棋
     14 void HumanPlay();    //人下棋
     15 
     16 int main()
     17 {
     18     Initmap();
     19     Showmap();
     20     while ((!isFull()) && (!isWin()))
     21     {
     22         HumanPlay();
     23         system("cls");
     24         Showmap();
     25         if (isWin())
     26             break;
     27 
     28         Sleep(500);    //模拟实际过程,让电脑慢点,hh
     29         PcPlay();
     30         system("cls");
     31         Showmap();
     32     }
     33 
     34     if (isFull())
     35         printf("
    
    平局
    ");
     36 
     37     system("pause");
     38     return 0;
     39 }
     40 
     41 void Initmap()
     42 {
     43     for (int i = 0; i < ROW; i++)
     44         for (int j = 0; j < COL; j++)
     45             chessboard[i][j] = 1;
     46 }
     47 
     48 void Showmap()
     49 {
     50     for (int i = 0; i < ROW; i++)
     51     {
     52         for (int j = 0; j < COL; j++)
     53         {
     54             if (chessboard[i][j] == 1)    //"1"代表空
     55                 printf("");
     56             if (chessboard[i][j] == 2)    //"2"代表人
     57                 printf("");
     58             if (chessboard[i][j] == 5)    //"5"代表电脑
     59                 printf("");
     60         }
     61         printf("
    ");
     62     }
     63 }
     64 
     65 bool isWin()
     66 {
     67     int sum = 0;
     68     for (int i = 0; i < ROW; i++)      //对每行判断是否获胜
     69     {
     70         for (int j = 0; j < COL; j++)
     71             sum += chessboard[i][j];
     72 
     73         if (sum == 6)
     74         {
     75             printf("人获胜!
    ");
     76             return true;
     77         }
     78         if (sum == 15)
     79         {
     80             printf("电脑获胜!
    ");
     81             return true;
     82         }
     83         sum = 0;
     84     }
     85 
     86     for (int j = 0; j < ROW; j++)      //对每列判断是否获胜
     87     {
     88         for (int i = 0; i < COL; i++)
     89             sum += chessboard[i][j];
     90 
     91         if (sum == 6)
     92         {
     93             printf("人获胜!
    ");
     94             return true;
     95         }
     96         if (sum == 15)
     97         {
     98             printf("电脑获胜!
    ");
     99             return true;
    100         }
    101         sum = 0;
    102     }
    103 
    104     for (int i = 0; i < ROW; i++)     //对对角线判断是否获胜
    105         sum += chessboard[i][i];
    106     if (sum == 6)
    107     {
    108         printf("人获胜!
    ");
    109         return true;
    110     }
    111     if (sum == 15)
    112     {
    113         printf("电脑获胜!
    ");
    114         return true;
    115     }
    116 
    117     sum = 0;
    118     for (int i = 0; i < ROW; i++)     //对反对角线判断是否获胜
    119         sum += chessboard[i][2 - i];
    120     if (sum == 6)
    121     {
    122         printf("人获胜!
    ");
    123         return true;
    124     }
    125     if (sum == 15)
    126     {
    127         printf("电脑获胜!
    ");
    128         return true;
    129     }
    130 
    131     return false;
    132 }
    133 
    134 bool isFull()
    135 {
    136     for (int i = 0; i < ROW; i++)
    137         for (int j = 0; j < COL; j++)
    138             if (chessboard[i][j] == 1)
    139                 return false;
    140     return true;
    141 }
    142 
    143 void HumanPlay()
    144 {
    145     int x, y;
    146     printf("请输入棋子的横坐标X:");
    147     scanf_s("%d", &x);
    148     printf("请输入棋子的纵坐标Y:");
    149     scanf_s("%d", &y);
    150 
    151     while (x < 1 || x>3 || y < 1 || y>3)
    152     {
    153         printf("
    请正确输入!
    ");
    154         printf("x,y均属于1~3
    
    ");
    155 
    156         printf("请输入棋子的横坐标X:");
    157         scanf_s("%d", &x);
    158         printf("请输入棋子的纵坐标Y:");
    159         scanf_s("%d", &y);
    160     }
    161 
    162     while (chessboard[3 - y][x - 1] != 1)
    163     {
    164         printf("
    
    该位置已被占用!
    ");
    165         printf("请选择正确的位置
    
    ");
    166         Sleep(1000);
    167 
    168         printf("
    请输入棋子的横坐标X:");
    169         scanf_s("%d", &x);
    170         printf("请输入棋子的纵坐标Y:");
    171         scanf_s("%d", &y);
    172     }
    173 
    174     chessboard[3 - y][x - 1] = 2;
    175 }
    176 
    177 void PcPlay()
    178 {
    179     int sum = 0;
    180     for (int i = 0; i < ROW; i++)
    181         for (int j = 0; j < COL; j++)
    182             score[i][j] = 0;
    183 
    184     // 对每行进行分数统计
    185     for (int i = 0; i < ROW; i++)
    186     {
    187         for (int j = 0; j < COL; j++)
    188             sum += chessboard[i][j];
    189 
    190         switch (sum)
    191         {
    192         case 3:                     //1+1+1;重要性:最低;权重:1
    193             for (int k = 0; k < COL; k++)
    194             {
    195                 if (chessboard[i][k] == 1)
    196                     score[i][k] += 1;
    197             }
    198             break;
    199         case 4:                     //1+1+2;重要性:次低;权重:10
    200             for (int k = 0; k < COL; k++)
    201             {
    202                 if (chessboard[i][k] == 1)
    203                     score[i][k] += 10;
    204             }
    205             break;
    206         case 8:                    //1+2+5;重要性:较低,权值50
    207             for (int k = 0; k < COL; k++)
    208             {
    209                 if (chessboard[i][k] == 1)
    210                     score[i][k] += 50;
    211             }
    212             break;
    213         case 7:                     //1+1+5;重要性:较高;权重:200
    214             for (int k = 0; k < COL; k++)
    215             {
    216                 if (chessboard[i][k] == 1)
    217                     score[i][k] += 200;     //把行列的重要性比对角线高
    218             }
    219             break;
    220         case 5:                     //1+2+2;重要性:次高;权重:500
    221             for (int k = 0; k < COL; k++)
    222             {
    223                 if (chessboard[i][k] == 1)
    224                     score[i][k] += 500;
    225             }
    226             break;
    227         case 11:                     //1+5+5;重要性:最高;权重:1000
    228             for (int k = 0; k < COL; k++)
    229             {
    230                 if (chessboard[i][k] == 1)
    231                     score[i][k] += 1000;
    232             }
    233             break;
    234         }
    235         sum = 0;
    236     }
    237 
    238     // 对每列进行分数统计
    239     for (int j = 0; j < COL; j++)
    240     {
    241         for (int i = 0; i < ROW; i++)
    242             sum += chessboard[i][j];
    243 
    244         switch (sum)
    245         {
    246         case 3:                   
    247             for (int k = 0; k < COL; k++)
    248             {
    249                 if (chessboard[k][j] == 1)
    250                     score[k][j] += 1;
    251             }
    252             break;
    253         case 4:                    
    254             for (int k = 0; k < COL; k++)
    255             {
    256                 if (chessboard[k][j] == 1)
    257                     score[k][j] += 10;
    258             }
    259             break;
    260         case 8:                    
    261             for (int k = 0; k <
    262                 COL; k++)
    263             {
    264                 if (chessboard[k][j] == 1)
    265                     score[k][j] += 50;
    266             }
    267             break;
    268         case 7:                    
    269             for (int k = 0; k < COL; k++)
    270             {
    271                 if (chessboard[k][j] == 1)     //1+1+5;重要性:较高;权重:200
    272                     score[k][j] += 200;  
    273             }
    274             break;
    275         case 5:                    
    276             for (int k = 0; k < COL; k++)
    277             {
    278                 if (chessboard[k][j] == 1)
    279                     score[k][j] += 500;
    280             }
    281             break;
    282         case 11:                  
    283             for (int k = 0; k < COL; k++)
    284             {
    285                 if (chessboard[k][j] == 1)
    286                     score[k][j] += 1000;
    287             }
    288             break;
    289         }
    290         sum = 0;
    291     }
    292 
    293     // 对对角线进行分数统计
    294     for (int i = 0; i < ROW; i++)
    295         sum += chessboard[i][i];
    296     switch (sum)
    297     {
    298     case 3:                    
    299         for (int i = 0; i < COL; i++)
    300         {
    301             if (chessboard[i][i] == 1)
    302                 score[i][i] += 1;
    303         }
    304         break;
    305     case 4:                   
    306         for (int i = 0; i < COL; i++)
    307         {
    308             if (chessboard[i][i] == 1)
    309                 score[i][i] += 10;
    310         }
    311         break;
    312     case 8:                
    313         for (int i = 0; i < COL; i++)
    314         {
    315             if (chessboard[i][i] == 1)
    316                 score[i][i] += 50;
    317         }
    318         break;
    319     case 7:                     //1+1+5;权重:100
    320         for (int i = 0; i < COL; i++)
    321         {
    322             if (chessboard[i][i] == 1)
    323                 score[i][i] += 100;
    324         }
    325         break;
    326     case 5:                
    327         for (int i = 0; i < COL; i++)
    328         {
    329             if (chessboard[i][i] == 1)
    330                 score[i][i] += 500;
    331         }
    332         break;
    333     case 11:                    
    334         for (int i = 0; i < COL; i++)
    335         {
    336             if (chessboard[i][i] == 1)
    337                 score[i][i] += 1000;
    338         }
    339         break;
    340     }
    341 
    342     // 对反对角线进行分数统计
    343     sum = 0;
    344     for (int i = 0; i < ROW; i++)
    345         sum += chessboard[i][2 - i];
    346     switch (sum)
    347     {
    348     case 3:                    
    349         for (int i = 0; i < COL; i++)
    350         {
    351             if (chessboard[i][2 - i] == 1)
    352                 score[i][2 - i] += 1;
    353         }
    354         break;
    355     case 4:                    
    356         for (int i = 0; i < COL; i++)
    357         {
    358             if (chessboard[i][2 - i] == 1)
    359                 score[i][2 - i] += 10;
    360         }
    361         break;
    362     case 8:
    363         for (int i = 0; i < COL; i++)
    364         {
    365             if (chessboard[i][2 - i] == 1)
    366                 score[i][2 - i] += 50;
    367         }
    368         break;
    369     case 7:                     
    370         for (int i = 0; i < COL; i++)
    371         {
    372             if (chessboard[i][2 - i] == 1)    //1+1+5;权重:100
    373                 score[i][2 - i] += 100;
    374         }
    375         break;
    376     case 5:                   
    377         for (int i = 0; i < COL; i++)
    378         {
    379             if (chessboard[i][2 - i] == 1)
    380                 score[i][2 - i] += 500;
    381         }
    382         break;
    383     case 11:                    
    384         for (int i = 0; i < COL; i++)
    385         {
    386             if (chessboard[i][2 - i] == 1)
    387                 score[i][2 - i] += 1000;
    388         }
    389         break;
    390     }
    391 
    392     int maxRow = 0, maxCol = 0;
    393     for (int i = 0; i < ROW; i++)
    394         for (int j = 0; j < COL; j++)
    395         {
    396             if (score[i][j] > score[maxRow][maxCol])
    397             {
    398                 maxRow = i;
    399                 maxCol = j;
    400             }
    401         }
    402     chessboard[maxRow][maxCol] = 5;
    403 }
  • 相关阅读:
    MVC梳理与总结
    《岛上书店》
    PIL简单图片处理(上)
    Day 3---快捷键
    Day 2---控制快捷键
    Day 1--快捷键
    每天学点Emacs
    swift写ios mvc的小demo
    hexo博客部署到github无法上传的问题
    Django Web开发【7】 投票与评论
  • 原文地址:https://www.cnblogs.com/lfri/p/9880328.html
Copyright © 2020-2023  润新知