2017五子棋游戏课程设计

来源:互联网 发布:随机抽号软件 编辑:程序博客网 时间:2024/06/09 18:55



   五子棋课程设计代码


#include<stdio.h>#include<string.h>#include<stdlib.h>#define SPA 0                   /*空位置设为0,*/#define MAN 1                   /*玩家下的位置设为1,*/#define COM 2                   /*电脑下的位置设为2 ,*/int qipan[15][15];              /* 15*15的棋盘 ,*/int a,b,c,d,x;                  /* a b为玩家下子坐标 ,c d为电脑下子坐标 x为剩余空位置*/void start();                   /* 程序的主要控制函数 */void draw();                    /* 画棋盘 */int win(int p,int q);           /* 判断胜利 p q为判断点坐标 */void AI(int *p,int *q);         /* 电脑下子 p q返回下子坐标 */int value(int p,int q);         /* 计算空点p q的价值 */int qixing(int n,int p,int q);  /* 返回空点p q在n方向上的棋型 n为1-8方向 从右顺时针开始数 */void yiwei(int n,int *i,int *j);/* 在n方向上对坐标 i j 移位 n为1-8方向 从右顺时针开始数  */int main(){    char k;    do    {        x=225;        start();        printf("还要再来一局吗?输入y或n:");        getchar();        scanf("%c",&k);        while(k!='y'&&k!='n')        {            printf("输入错误,请重新输入\n");            scanf("%c",&k);        }        system("cls");    }    while(k=='y');    printf("谢谢使用!\n");}void start(){    int i,j,a1,b1,c1,d1,choice;   /* a1 b1储存玩家上手坐标 c1 d1储存电脑上手坐标 */    char ch;    system("color E3");//设置颜色    printf("\t 欢迎使用五子棋对战程序     希望你玩的愉快开心     \n");    printf("\t\t1、为人机对战模式\n\t\t2、为人人对战模式\n");    printf("\t\t请输入1 或2 :");    scanf("%d",&choice);          /* 选择模式:人机或人人 */    while(choice!=1&&choice!=2)    {        printf("输入错误,请重新输入:");        scanf("%d",&choice);    }    if(choice==1)                 /* 人机模式 */    {        system("cls");        printf("欢迎使用五子棋人机对战!下子请输入坐标(如13 6)。悔棋请输入15 15。\n\n\n");        memset(qipan,0,sizeof(qipan))  ;       /* 置棋盘全为空 */        draw();        printf("先下请按1,后下请按2:");        scanf("%d",&i);        while(i!=1&&i!=2)        {            printf("输入错误,请重新输入:");            scanf("%d",&i);        }        if(i==1)                     /* 如果玩家先手下子 */        {            printf("请下子:");            scanf("%d%d",&a,&b);            while((a<0||a>14)||(b<0||b>14))            {                printf("坐标错误!请重新输入:");                scanf("%d%d",&a,&b);            }            a1=a;            b1=b;            x--;            qipan[b][a]=MAN;            system("cls");            draw();        }        while(x!=0)        {            if(x==225)                /* 电脑先下就下在7 7 */            {                c=7;                d=7;                qipan[d][c]=COM;                x--;                system("cls");                draw();            }            else            {                AI(&c,&d);             /* 电脑下子 */                qipan[d][c]=COM;                x--;                system("cls");                draw();            }            c1=c;            d1=d;                      /* 储存电脑上手棋型 */            if(win(c,d))               /* 电脑赢 */            {                printf("要悔棋吗?请输入y或n:");                getchar();                scanf("%c",&ch);                while(ch!='y'&&ch!='n')                {                    printf("输入错误,请重新输入:");                    scanf("%c",&ch);                }                if(ch=='n')                {                    printf("电脑赢!\n");                    return;                }                else                    /* 悔棋 */                {                    x+=2;                    qipan[d][c]=SPA;                    qipan[b1][a1]=SPA;                    system("cls");                    draw();                }            }            printf("电脑下在%d %d\n请输入:",c,d);            scanf("%d%d",&a,&b);        /* 玩家下子 */            if(a==15&&b==15)            /* 悔棋 */            {                x+=2;                qipan[d][c]=SPA;                qipan[b1][a1]=SPA;                system("cls");                draw();                printf("请输入:");                scanf("%d%d",&a,&b);            }            while((a<0||a>14)||(b<0||b>14)||qipan[b][a]!=SPA)            {                printf("坐标错误或该位置已有子!请重新输入:");                scanf("%d%d",&a,&b);            }            a1=a;            b1=b;            x--;            qipan[b][a]=MAN;            system("cls");            draw();            if(win(a,b))                /* 玩家赢 */            {                printf("电脑输!!!\n");                return;            }        }        printf("和局\n");    }    if(choice==2)    {        system("cls");        printf("欢迎使用五子棋人人对战!下子请输入坐标(如13 6)。悔棋请输入15 15。 \n\n\n");        for(j=0; j<15; j++)            for(i=0; i<15; i++)                qipan[j][i]=SPA;         /* 置棋盘全为空 */        draw();        while(x!=0)        {            printf("1P请输入:");            scanf("%d%d",&a,&b);            if(a==15&&b==15)            {                x+=2;                qipan[d][c]=SPA;                qipan[b1][a1]=SPA;                system("cls");                draw();                printf("1P请输入:");                scanf("%d%d",&a,&b);            }            while((a<0||a>14)||(b<0||b>14)||qipan[b][a]!=SPA)            {                printf("坐标错误或该位置已有子!请重新输入:");                scanf("%d%d",&a,&b);            }            a1=a;            b1=b;            x--;            qipan[b][a]=MAN;            system("cls");            draw();            printf("1P下在%d %d。\n",a,b);            if(win(a,b))                  /* 玩家1赢 */            {                printf("你真棒!!!\n");                return;            }            printf("2P请输入:");            scanf("%d%d",&c,&d);            if(c==15&&d==15)            {                x+=2;                qipan[b][a]=SPA;                qipan[d1][c1]=SPA;                system("cls");                draw();                printf("2P请输入:");                scanf("%d%d",&c,&d);            }            while((c<0||c>14)||(d<0||d>14)||qipan[d][c]!=SPA)            {                printf("坐标错误或该位置已有子!请重新输入:");                scanf("%d%d",&c,&d);            }            c1=c;            d1=d;            x--;            qipan[d][c]=COM;            system("cls");            draw();            printf("2P下在%d %d。\n",c,d);            if(win(c,d))            {                printf("你真棒!!!\n");                return;            }                           /* 玩家2赢 */        }        printf("和局\n");    }}void draw()                            /* 画棋盘 */{    char map[15][15];    int i,j;    printf("      ------------------------------------------------------->X\n");    for(i=0; i<15; i++)    {        if(i==0)            printf("      0  1   2   3   4   5   6   7   8   9   10  11  12  13  14\n");        if(i>=1&&i<=14)            printf("     ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃\n");        if(i<10)            printf("Y0%d  ",i);        else printf("Y%d  ",i);        for(j=0; j<15; j++)        {            if(qipan[i][j]==1)//1为黑子                printf("●");            else if(qipan[i][j]==2)//2为白子                printf("○");            else if(i==0&&j==0)//以下为边缘棋盘样式                printf("┏");            else if(i==14&&j==0)                printf("┗");            else if(i==14&&j==14)                printf("┛");            else if(i==0&&j==14)                printf("┓");            else if(j==0)                printf("┠");            else if(i==14)                printf("┷");            else if(i==0)                printf("┯");            else if(j==14)                printf("┨");            else printf("┼");//中间的空位            if(j!=14)                printf("━");        }        printf("\n");    }}int win(int p,int q)         /* 判断胜利 p q为判断点坐标,胜利返回1,否则返回0 */{    int k,n=1,m,P,Q;        /* k储存判断点p q的状态COM或MAN。P Q储存判断点坐标。n为判断方向。m为个数。 */    P=p;    Q=q;    k=qipan[q][p];    while(n!=5)    {        m=0;        while(k==qipan[q][p])        {            m++;            if(m==5)                return 1;            yiwei(n,&p,&q);            if(p<0||p>14||q<0||q>14) break;        }        n+=4;        m-=1;        p=P;        q=Q;                      /* 转向判断 */        while(k==qipan[q][p])        {            m++;            if(m==5) return 1;            yiwei(n,&p,&q);            if(p<0||p>14||q<0||q>14) break;        }        n-=3;        p=P;        q=Q;                     /* 不成功则判断下一组方向 */    }    return 0;}void AI(int *p,int *q)           /* 电脑下子 *p *q返回下子坐标 */{    int i,j,k,max=0,I,J;         /* I J为下点坐标 */    for(j=0; j<15; j++)        for(i=0; i<15; i++)            if(qipan[j][i]==SPA)            {                /* 历遍棋盘,遇到空点则计算价值,取最大价值点下子。 */                k=value(i,j);                if(k>=max)                {                    I=i;                    J=j;                    max=k;                }            }    *p=I;    *q=J;}int value(int p,int q)            /* 计算空点p q的价值 以k返回 */{    int n=1,k=0,k1,k2,K1,K2,X1,Y1,Z1,X2,Y2,Z2,temp;    int  a[2][4][4]= {40,400,3000,10000,6,10,600,10000,20,120,200,0,6,10,500,0,30,300,2500,5000,2,8,300,8000,26,160,0,0,4,20,300,0};        /* 数组a中储存己方和对方共32种棋型的值  己方0对方1    活0冲1空活2空冲3    子数0-3(0表示1个子,3表示4个子) */    while(n!=5)    {        k1=qixing(n,p,q);        n+=4;                     /* k1,k2为2个反方向的棋型编号 */        k2=qixing(n,p,q);        n-=3;        if(k1>k2)        {            temp=k1;            k1=k2;            k2=temp;        }                         /* 使编号小的为k1,大的为k2 */        K1=k1;        K2=k2;                    /* K1 K2储存k1 k2的编号 */        Z1=k1%10;        Z2=k2%10;        k1/=10;        k2/=10;        Y1=k1%10;        Y2=k2%10;        k1/=10;        k2/=10;        X1=k1%10;        X2=k2%10;                  /* X Y Z分别表示 己方0对方1    活0冲1空活2空冲3    子数0-3(0表示1个子,3表示4个子) */        if(K1==-1)        {            if(K2<0)            {                k+=0;                continue;            }            else k+=a[X2][Y2][Z2]+5;            continue;        };                          /* 空棋型and其他 */        if(K1==-2)        {            if(K2<0)            {                k+=0;                continue;            }            else                k+=a[X2][Y2][Z2]/2;            continue;        };                           /* 边界冲棋型and其他 */        if(K1==-3)        {            if(K2<0)            {                k+=0;                continue;            }            else                k+=a[X2][Y2][Z2]/3;            continue;        };                           /* 边界空冲棋型and其他 */        if(((K1>-1&&K1<4)&&((K2>-1&&K2<4)||(K2>9&&K2<14)))||((K1>99&&K1<104)&&((K2>99&&K2<104)||(K2>109&&K2<114))))        {            /* 己活己活 己活己冲 对活对活 对活对冲 的棋型赋值*/            if(Z1+Z2>=2)            {                k+=a[X2][Y2][3];                continue;            }            else            {                k+=a[X2][Y2][Z1+Z2+1];                continue;            }        }        if(((K1>9&&K1<14)&&(K2>9&&K2<14))||((K1>109&&K1<114)&&(K2>109&&K2<114)))        {            /* 己冲己冲 对冲对冲 的棋型赋值*/            if(Z1+Z2>=2)            {                k+=10000;                continue;            }            else            {                k+=0;                continue;            }        }        if(((K1>-1&&K1<4)&&((K2>99&&K2<104)||(K2>109&&K2<114)))||((K1>9&&K1<14)&&((K2>99&&K2<104)||(K2>109&&K2<114))))        {            /* 己活对活 己活对冲 己冲对活 己冲对冲 的棋型赋值*/            if(Z1==3||Z2==3)            {                k+=10000;                continue;            }            else            {                k+=a[X2][Y2][Z2]+a[X1][Y1][Z1]/4;                continue;            }        }        else        {            k+=a[X1][Y1][Z1]+a[X2][Y2][Z2];            continue;        }                           /* 其他棋型的赋值 */    }    return k;}int qixing(int n,int p,int q)/* 返回空点p q在n方向上的棋型号 n为1-8方向 从右顺时针开始数 */{    int k,m=0;               /* 棋型号注解:  己活000-003 己冲010-013 对活100-103 对冲110-113 己空活020-023 己空冲030-033 对空活120-123 对空冲130-133 空-1 边界冲-2 边界空冲-3*/    yiwei(n,&p,&q);    if(p<0||p>14||q<0||q>14)        k=-2;                         /* 边界冲棋型 */    switch(qipan[q][p])    {    case COM:    {        m++;        yiwei(n,&p,&q);        if(p<0||p>14||q<0||q>14)        {            k=m+9;            return k;        }        while(qipan[q][p]==COM)        {            m++;            yiwei(n,&p,&q);            if(p<0||p>14||q<0||q>14)            {                k=m+9;                return k;            }        }        if(qipan[q][p]==SPA)            k=m-1;                    /* 己方活棋型 */        else            k=m+9;                    /* 己方冲棋型 */    }    break;    case MAN:    {        m++;        yiwei(n,&p,&q);        if(p<0||p>14||q<0||q>14)        {            k=m+109;            return k;        }        while(qipan[q][p]==MAN)        {            m++;            yiwei(n,&p,&q);            if(p<0||p>14||q<0||q>14)            {                k=m+109;                return k;            }        }        if(qipan[q][p]==SPA)            k=m+99;                    /* 对方活棋型 */        else k=m+109;                  /* 对方冲棋型 */    }    break;    case SPA:    {        yiwei(n,&p,&q);        if(p<0||p>14||q<0||q>14)        {            k=-3;                      /* 边界空冲棋型 */            return k;        }        switch(qipan[q][p])        {        case COM:        {            m++;            yiwei(n,&p,&q);            if(p<0||p>14||q<0||q>14)            {                k=m+29;                return k;            }            while(qipan[q][p]==COM)            {                m++;                yiwei(n,&p,&q);                if(p<0||p>14||q<0||q>14)                {                    k=m+29;                    return k;                }            }            if(qipan[q][p]==SPA)                k=m+19;                  /* 己方空活棋型 */            else k=m+29;                 /* 己方空冲棋型 */        }        break;        case MAN:        {            m++;            yiwei(n,&p,&q);            if(p<0||p>14||q<0||q>14)            {                k=m+129;                return k;            }            while(qipan[q][p]==MAN)            {                m++;                yiwei(n,&p,&q);                if(p<0||p>14||q<0||q>14)                {                    k=m+129;                    return k;                }            }            if(qipan[q][p]==SPA)                k=m+119;                  /* 对方空活棋型 */            else k=m+129;                 /* 对方空冲棋型 */        }        break;        case SPA:            k=-1;            break;                         /* 空棋型 */        }    }    break;    }    return k;}void yiwei(int n,int *i,int *j)            /* 在n方向上对坐标 i j 移位 n为1-8方向 从右顺时针开始数 */{    switch(n)    {    case 1:        *i+=1;        break;    case 2:        *i+=1;        *j+=1;        break;    case 3:        *j+=1;        break;    case 4:        *i-=1;        *j+=1;        break;    case 5:        *i-=1;        break;    case 6:        *i-=1;        *j-=1;        break;    case 7:        *j-=1;        break;    case 8:        *i+=1;        *j-=1;        break;    }}