c语言实现五子棋

最近要完成大作业,我设计了一个人机对战模式的五子棋游戏,其实五子棋除了人机对战模式其他的模式都很简单,只有人机对战模式最难。自己实现的这个程序电脑会判断是不是需要阻挡玩家,如果不需要电脑就会按照它自己的思路连成线,如果前两者都不可以,拿就用随机数函数在玩家最后一个棋子周围随机生成一个坐标。
不过自己写的这个程序,电脑还是不够智能,原因在于电脑决策前对于棋盘的遍历检查和判断的方式不够好,对于这个程序还是要进行优化,如果进行优化,就是对电脑下棋方式进行优化,在玩家落子之后进行怎么样的一个判断会更好。应该是把棋盘全部遍历一遍不仅仅关注玩家是否要赢,还要根据规则对整个棋盘进行一个完整的判断(在自己的算法能力提高以后再优化吧!)

//-----------------------五子棋游戏------------------------
//
//   实现一个五子棋的单机游戏,仅仅实现人机对战,人人对战十
//   分简单,没有实质性意义,在字符数字混合输入时,一定注意回车符
//
//   Y:完成一局之后继续下一局  N:退出游戏
//   游戏中若玩家输入两个0表示玩家想要退出游戏
//      越写发现情况越多,越无法解决这个问题。
//----------------------------------------------------------

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

//------------------------【全局变量声明】-------------------

//用了很多全局变量,目的是在各函数之间通信

char chessboard[16][16]; //存储棋盘数据
int side_1=0;  //记录棋手走的步数,当一局对战结束时应当置为0
int side_2=0;
char choice;

int row; int col; //记录某一方输入的位置
int flag_1=0; //记录玩家输赢的标志
int flag_2=0; //记录电脑输赢的标志
int sum[5];  //存放玩家或电脑下棋后四个方向的棋子数

int record_row=0,record_col=0; //记录电脑上一次下的地方
//-----------------------------------------------------------

//------------------------【实现函数声明】--------------------
void show_chessboard();
void model_input();
void play_input();
void com_input();  //是这个程序最难的地方

int judge();
int evaluate(int x,int y);

int ready_DSS();
//------------------------------------------------------------

//-------------------------【主程序入口】----------------------
int main()
{
    printf("----------------------------五子棋游戏--------------------------\n");
    printf("                 Y:打完一局之后继续   N:退出游戏\n");
    printf("                 玩家输入'0 0'表示玩家想中途退出\n");
    printf("----------------------------------------------------------------\n\n\n");

    tag_1: memset(chessboard,' ',500);
    printf("是否要开始对战?Y or N\n");
    model_input();
    if(choice=='Y')
    {
        show_chessboard();
        printf("玩家步数:%d    电脑步数:%d\n",side_1,side_2);
        while(1)
       {
            play_input();
            show_chessboard();
            printf("玩家步数:%d    电脑步数:%d\n",side_1,side_2);
            if((flag_1=evaluate(row,col))==1)
                break;

            com_input();
            show_chessboard();
            printf("玩家步数:%d    电脑步数:%d\n",side_1,side_2);
            if((flag_2=evaluate(row,col))==1)
               break;
       }

       if(flag_1==1)
           printf("聪明的玩家你赢啦!\n");
       else
           printf("不好意思你输了!\n");
       printf("继续玩吗? Y or N\n");
       model_input();
       if(choice=='Y')
         goto tag_1;
       else
          exit(1);
    }


    return 0;
}
//-------------------------------------------------------------

//-----------------------【打印棋盘的函数】--------------------
void show_chessboard()
{
    system("cls"); //先清理之前的,然后输出新的棋盘
    printf("        五子棋游戏,人机对战!\n\n");
    //i为列号,j为行号
    int i,j,k;

    for(i=0;i<=30;i++)
    {
        if(i==0)
        {
            for(j=0;j<=15;j++)
            {
                if(j==0)
                    printf("   ");
                else
                {   if(j<10)
                       printf("%d  ",j);
                    else
                       printf("%d ",j);
                }
            }
            printf("\n");
        }
        else
        {
            if(i%2==1)
            {
                printf("  |");

                for(j=1;j<=15;j++)
                {
                    printf("--|");
                }
            }
            else
            {
                printf("%d",i/2);

                if(i/2<10)
                    printf(" |");
                else
                printf("|");
                for(j=1;j<=15;j++)
                {
                    printf("%c |",chessboard[i/2][j]);
                }
            }
            printf("\n");
        }
    }
    for(k=0;k<=15;k++)
    {
        if(k==0)
            printf("  |");
        else
            printf("--|");
    }
    printf("\n");
}
//------------------------------------------------------------------------


//---------------------------【判定输赢的函数】---------------------------

int evaluate(int x,int y)
{
    //以(x,y)为中心判断输赢
    int i,j;

    sum[1]=0,sum[2]=0,sum[3]=0,sum[4]=0;

    //先查横边
    for(i=x,j=y-1;j>=1;j--) //向前
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum[1]++;
        else
            break; //因为棋子必须是连续的,所以这里必须跳出来
    }
    for(i=x,j=y+1;j<=20;j++) //向后
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum[1]++;
        else
            break;
    }

    if(sum[1]>=4)
        return 1;

    //查竖边
    for(i=x-1,j=y;i>=1;i--) //向上
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum[2]++;
        else
            break;
    }
    for(i=x+1,j=y;i<=20;i++) //向下
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum[2]++;
        else
            break;
    }

    if(sum[2]>=4)
        return 1;

    //查左方向斜边
    for(i=x-1,j=y-1;i>=1&&j>=i;i--,j--)
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum[3]++;
         else
            break;
    }
    for(i=x+1,j=y+1;i<=20&&j<=20;i++,j++)
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum[3]++;
        else
            break;
    }

    if(sum[3]>=4)
        return 1;

    //查右方向斜边
    for(i=x-1,j=y+1;i>=1&&j>=i;i--,j++)
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum[4]++;
        else
             break;
    }
    for(i=x+1,j=y-1;i<=20&&j<=20;i++,j--)
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum[4]++;
        else
            break;
    }

    if(sum[4]>=4)
        return 1;

    return 0;
}
//-------------------------------------------------------------------


//-------------------------【玩家输入棋子函数】----------------------

void play_input()
{
    //玩家对应的棋子标准为o
    printf("请落子:");
    scanf("%d %d",&row,&col);
    getchar();
    if(row==0&&col==0)
    {
       exit(1);
    }

    if(row<1||row>15||col<1||col>15||chessboard[row][col]!=' ')
    {

        printf("下错区域!");
        play_input();
    }
    else
    {
        chessboard[row][col]='o';
        printf("\n%d %d\n",row,col);
        side_1++;
    }
}
//-------------------------------------------------------------------

//-------------------------【模式选择输入函数】----------------------

void model_input()
{

    while(scanf("%c",&choice)==1)
    {
       getchar(); //拿走输入流中的换行符
       if(choice=='Y'||choice=='N')
       {
          break;
       }
        else
        {
          printf("请输入正确的选择:");
        }
     }
}
//--------------------------------------------------------------------


//--------------------------【电脑下棋函数】--------------------------

//利用随机数函数生成坐标,且坐标并不随意,根据玩家下棋的位置和前一次
//生成的坐标确定,使电脑选择的棋子位置有实际意义
int judge()
{
    int i;
    for(i=1;i<5;i++)
    {
        if(sum[i]>=2)
            return i;
    }
    return 0;
}

void com_input()
{
    int k,i,j,y=0;//y作为防止电脑练下两步的关键字

    int max=ready_DSS();
    if(max==0)
        goto tag_2;

    if((k=judge())!=0&&max!=4)  //首先要做的就是判断是不是要挡一下玩家
    {
        if(k==2)
        {
            for(i=row-1,j=col;i>=1;i--)
            {
                if(chessboard[i][j]==' ')
                {
                    chessboard[i][j]='x';
                    side_2++;
                    row=i; col=j;  //为了让判断输赢的函数能够判断
                    y=1;
                    break;
                }
                if(chessboard[i][j]=='x')
                    break;
            }
            if(y==0)
            {
                for(i=row+1,j=col;i<=15;i++)
                {
                     if(chessboard[i][j]==' ')
                    {
                        chessboard[i][j]='x';
                        side_2++;
                        row=i; col=j;
                        break;
                    }
               }
            }
        }
        else if(k==1)
        {
            for(i=row,j=col-1;j>=1;j--)
            {
                if(chessboard[i][j]==' ')
                {
                    chessboard[i][j]='x';
                    side_2++;
                    row=i; col=j;  //为了让判断输赢的函数能够判断
                    y=1;
                    break;
                }
                if(chessboard[i][j]=='x')
                    break;
            }
            if(y==0)
            {
                for(i=row,j=col+1;j<=15;j++)
                {
                     if(chessboard[i][j]==' ')
                    {
                        chessboard[i][j]='x';
                        side_2++;
                        row=i; col=j;
                        break;
                    }
               }
            }
        }
        else if(k==3)
        {
            for(i=row-1,j=col-1;j>=1&&i>=1;j--,i--)
            {
                if(chessboard[i][j]==' ')
                {
                    chessboard[i][j]='x';
                    side_2++;
                    row=i; col=j;
                    y=1;
                    break;
                }
                if(chessboard[i][j]=='x')
                    break;
            }
            if(y==0)
            {
                for(i=row+1,j=col+1;i<=15&&j<=15;j++,i++)
                {
                     if(chessboard[i][j]==' ')
                    {
                        chessboard[i][j]='x';
                        side_2++;
                        row=i; col=j;
                        break;
                    }
               }
            }
        }
        else if(k==4)
        {
            for(i=row-1,j=col+1;j<=15&&i>=1;j++,i--)
            {
                if(chessboard[i][j]==' ')
                {
                    chessboard[i][j]='x';
                    side_2++;
                    row=i; col=j;
                    y=1;
                    break;
                }
                if(chessboard[i][j]=='x')
                    break;
            }
            if(y==0)
            {
                for(i=row+1,j=col-1;i<=15&&j>=1;j--,i++)
                {
                     if(chessboard[i][j]==' ')
                    {
                        chessboard[i][j]='x';
                        side_2++;
                        row=i; col=j;
                        break;
                    }
               }
            }
        }
    }
    else
    {
        int execute=0; //这个用于判断后续操作是否需要执行
        int s=record_row,t=record_col,sum=1;

        for(i=s,j=t-1;j>=1;j--) //向前
        {
            if(chessboard[i][j]==chessboard[s][t])
                sum++;
            else
                break;
        }
        for(i=s,j=t+1;j<=20;j++) //向后
        {
             if(chessboard[i][j]==chessboard[s][t])
                sum++;
              else
                break;
         }
         if(max==sum)
         {
             if(chessboard[i][j]==' ')
             {
                 chessboard[i][j]='x';
                 side_2++;
                 row=i; col=j;
                 record_row=i; record_col=j;
                 execute=1;
             }
             else
             {
                 if(chessboard[i][j-max-1]==' ')
                 {
                     chessboard[i][j-max-1]='x';
                     side_2++;
                     row=i; col=j-max-1;
                     record_row=i;
                     record_col=j-max-1;
                     execute=1;
                 }
             }
         }

        if(execute==0)
        {
            sum=1;   //这个初始化相当重要,不能忘记
            for(i=s-1,j=t;i>=1;i--) //向上
            {
                if(chessboard[i][j]==chessboard[s][t])
                     sum++;
                else
                     break;
             }
             for(i=s+1,j=t;i<=20;i++) //向下
             {
                 if(chessboard[i][j]==chessboard[s][t])
                     sum++;
                 else
                     break;
             }
             if(max==sum)
             {
                 if(chessboard[i][j]==' ')
                 {
                     chessboard[i][j]='x';
                     side_2++;
                     row=i; col=j;
                     record_row=i; record_col=j;
                     execute=1;
                  }
                  else
                  {
                      if(chessboard[i-max-1][j]==' ')
                     {
                          chessboard[i-max-1][j]='x';
                          side_2++;
                          row=i-max-1; col=j;
                          record_row=i-max-1;
                          record_col=j;
                         execute=1;
                      }
                  }
              }
        }

        if(execute==0)
        {
            sum=1;
            for(i=s-1,j=t-1;i>=1&&j>=1;i--,j--) //向左上
            {
                if(chessboard[i][j]==chessboard[s][t])
                     sum++;
                else
                     break;
             }
             for(i=s+1,j=t+1;i<=20&&j<=20;i++,j++) //向下
             {
                 if(chessboard[i][j]==chessboard[s][t])
                     sum++;
                 else
                     break;
             }
             if(max==sum)
             {
                 if(chessboard[i][j]==' ')
                 {
                     chessboard[i][j]='x';
                     side_2++;
                     row=i; col=j;
                     record_row=i; record_col=j;
                     execute=1;
                  }
                  else
                  {
                      if(chessboard[i-max-1][j-max-1]==' ')
                     {
                          chessboard[i-max-1][j-max-1]='x';
                          side_2++;
                          row=i-max-1; col=j-max-1;
                          record_row=i-max-1;
                          record_col=j-max-1;
                         execute=1;
                      }
                  }
              }
        }

         if(execute==0)
         {
            sum=1;
            for(i=s+1,j=t-1;i<=20&&j>=1;i++,j--) //向左下
            {
                if(chessboard[i][j]==chessboard[s][t])
                     sum++;
                else
                     break;
             }
             for(i=s-1,j=t+1;i>=1&&j<=20;i--,j++) //向下
             {
                 if(chessboard[i][j]==chessboard[s][t])
                     sum++;
                 else
                     break;
             }
             if(max==sum)
             {
                 if(chessboard[i][j]==' ')
                 {
                     chessboard[i][j]='x';
                     side_2++;
                     row=i; col=j;
                     record_row=i; record_col=j;
                     execute=1;
                  }
                  else
                  {
                      if(chessboard[i+max+1][j-max-1]==' ')
                     {
                          chessboard[i+max+1][j-max-1]='x';
                          side_2++;
                          row=i+max+1; col=j-max-1;
                          record_row=i+max+1;
                          record_col=j-max-1;
                         execute=1;
                      }
                  }
              }
         }


        if(execute==0)
        {
            tag_2: srand((unsigned int)time(NULL));//不需要挡对手自己也无法连在一起
            int m,n;
            while(1)
            {
                m=rand()%5+row-2;
                n=rand()%5+col-2;
                if(chessboard[m][n]==' ')
                {
                    chessboard[m][n]='x';
                    row=m; col=n;
                    side_2++;
                    record_row=m;
                    record_col=n;
                    break;
                 }
            }
        }

    }


}
//---------------------------------------------------------------------


//---------------------------【局势判断函数】--------------------------

//这个函数帮助电脑决策应该怎么下,是阻挡玩家,随机生成还是完成一条线。

int ready_DSS()
{
    int i,j,x=record_row,y=record_col;

    int sum1=1,sum2=1,sum3=1,sum4=1,max;

    if(x==0&&y==0)
    {
        max=0;
        return max;
    }
    //先查横边
    for(i=x,j=y-1;j>=1;j--) //向前
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum1++;
        else
            break; //因为棋子必须是连续的,所以这里必须跳出来
    }
    for(i=x,j=y+1;j<=20;j++) //向后
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum1++;
        else
            break;
    }
    max=sum1;



    //查竖边
    for(i=x-1,j=y;i>=1;i--) //向上
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum2++;
        else
            break;
    }
    for(i=x+1,j=y;i<=20;i++) //向下
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum2++;
        else
            break;
    }

    if(sum2>max)
        max=sum2;

    //查左方向斜边
    for(i=x-1,j=y-1;i>=1&&j>=i;i--,j--)
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum3++;
         else
            break;
    }
    for(i=x+1,j=y+1;i<=20&&j<=20;i++,j++)
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum3++;
        else
            break;
    }

    if(sum3>max)
        max=3;

    //查右方向斜边
    for(i=x-1,j=y+1;i>=1&&j>=i;i--,j++)
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum4++;
        else
             break;
    }
    for(i=x+1,j=y-1;i<=20&&j<=20;i++,j--)
    {
        if(chessboard[i][j]==chessboard[x][y])
            sum4++;
        else
            break;
    }

    if(sum4>max)
        max=sum4;

    return max;
}

猜你喜欢

转载自blog.csdn.net/qq_39785575/article/details/80930185
今日推荐