| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3305 人关注过本帖
标题:原创 人机对战---------五子棋
只看楼主 加入收藏
qq349004853
Rank: 1
等 级:新手上路
帖 子:31
专家分:0
注 册:2008-3-27
收藏
 问题点数:0 回复次数:14 
原创 人机对战---------五子棋
这几天用c编了一个人机对战的五子棋,感觉还不错,尤其是编五子棋AI部分,让我学到了不少东西,体会到亲自创造一个大脑的乐趣。至于棋力如何,还是看者自己去体会吧,我粗略测试了一下,和现今网上流传的应该不相上下吧。本人不敢藏拙,特地拿出来和大家分享一下,由于本人是第一次编写如此浩大的工程(呵呵,相对于以前只是写个几十行数学计算代码而言),并且是第一次涉及到人工智能,所以代码部分难免有不足之处,希望各位不吝赐教,由于代码部分并不晦涩难懂,所以没有进行详细注释,如果有人实在看不懂要求详细注释的话,我会抽出时间进行详细的注释。本程序在win-tc上编译通过。
/************************************************************/
/*          五子棋之人机对战               */
/*          2008.12.2  版本:1.0             */
/*            作者:博士金刚                                */
/************************************************************/
/************************************************************/
/********           头文件部分        ********/
#include "graphics.h"            /*图形系统头文件*/
#include <conio.h>
#define closegr closegraph
#define LEFT 0x4b00           /*光标左键值*/
#define RIGHT 0x4d00          /*光标右键值*/
#define DOWN 0x5000           /*光标下键值*/
#define UP 0x4800             /*光标上键值*/
#define ESC 0x011b            /* ESC键值*/
#define ENTER 0x1c0d          /* 回车键值*/
/*************************************************************/
void drawqp();                    /*画棋盘*/
void downzi(int x,int y,int p);   /*下棋子*/
int panying();                    /*判断输赢*/
void play();                      /*人机对战*/
void cpuai();                     /*五子棋AI*/
int qp[15][15]={0};               /*标志棋局棋子的全局数组*/
int x=399,y=239,flag=0;           /*光标坐标以及输赢标志*/

void main()
{
    int gd = DETECT, gm = 0;
    registerbgidriver(EGAVGA_driver);
    initgraph(&gd,&gm,"");         /*图形模式初始化*/
    settextstyle(0,0,2);
    outtextxy(160,200,"Welcome to the game");
    outtextxy(160,250,"Press any key to play");
    getch();
    cleardevice();
    setbkcolor(0);
    drawqp();
    play();
    getch();
    closegraph();
}

void drawqp()
{
    int i;
    setcolor(1);
    setlinestyle(SOLID_LINE,0,3);
    setfillstyle(SOLID_FILL,6);
    bar(163,4,635,475);
    rectangle(163,3,635,475);
    setlinestyle(SOLID_LINE,0,1);
    for(i=0;i<15;i++)
        {line(189+30*i,3,189+30*i,475);
         line(163,29+30*i,635,29+30*i);
        }
   printf("\n");
   printf("Wlcome to the game!\n");
   printf("smart wuzi qi!\n\n\n");
   printf("ver: 1.0\n");
   printf("author:\n");
   printf("boshijingang\n\n");
   printf("control key:\n");
   printf("up--up\n");
   printf("down--down\n");
   printf("left--left\n");
   printf("right--right\n");
   printf("Yes--Enter\n");
   printf("EXIT--ESC\n\n\n");
   printf("contact me:\n");
   printf("QQ:\n");
   printf("349004853\n");
   printf("EMAIL:\n");
   printf("349004853qq@.com \n");
}

void play()
{
   
    int key=0,p=0;
    int *mapbuf1,*mapbuf2;
    int size;
  /********** 画光标*********/
    setcolor(10);
    line(387,237,397,237);
    line(397,227,397,237);
    line(401,227,401,237);
    line(401,237,411,237);
    line(387,241,397,241);
    line(397,241,397,251);
    line(401,241,401,251);
    line(401,241,411,241);
    size=imagesize(387,227,411,251);
    mapbuf1=malloc(size);
    mapbuf2=malloc(size);
    getimage(387,227,411,251,mapbuf1);
    getimage(207,47,231,71,mapbuf2);
 /*************循环控制双方轮流下子***************/
    while(key!=ESC)
    {
        key=bioskey(0);
        if(key==LEFT&&x>189)
        {
            if(qp[(y-29)/30][(x-189)/30]==0)
            putimage(x-12,y-12,mapbuf2,COPY_PUT);
            x-=30;key=0;
            if(qp[(y-29)/30][(x-189)/30]==0)
            putimage(x-12,y-12,mapbuf1,COPY_PUT);
        }
        if(key==RIGHT&&x<609)
        {
            if(qp[(y-29)/30][(x-189)/30]==0)
            putimage(x-12,y-12,mapbuf2,COPY_PUT);
            x+=30;key=0;
            if(qp[(y-29)/30][(x-189)/30]==0)
            putimage(x-12,y-12,mapbuf1,COPY_PUT);
        }
        if(key==DOWN&&y<449)
        {
            if(qp[(y-29)/30][(x-189)/30]==0)
            putimage(x-12,y-12,mapbuf2,COPY_PUT);
            y+=30;key=0;
            if(qp[(y-29)/30][(x-189)/30]==0)
            putimage(x-12,y-12,mapbuf1,COPY_PUT);
        }
        if(key==UP&&y>29)
        {
            if(qp[(y-29)/30][(x-189)/30]==0)
            putimage(x-12,y-12,mapbuf2,COPY_PUT);
            y-=30; key=0;
            if(qp[(y-29)/30][(x-189)/30]==0)
            putimage(x-12,y-12,mapbuf1,COPY_PUT);
        }

        if(key==ENTER&&qp[(y-29)/30][(x-189)/30]==0)
        {
            if(p%2==0)
            { downzi(x,y,p);
             qp[(y-29)/30][(x-189)/30]=1;

            p++;
            flag=panying();
            key=0;
            }
             if(p%2==1)
            {cpuai();
             downzi(x,y,p);
             qp[(y-29)/30][(x-189)/30]=2;
             flag=panying();
             p++;
            }
        }

        if(1==flag)
        {
            settextstyle(0,0,4);
            outtextxy(190,240,"The white win");
            return;
        }
        if(2==flag)
        {
            settextstyle(0,0,4);
            outtextxy(190,240,"The black win");
            return;
        }

    }
}

void downzi(x,y,p)
{
    if(p%2==0)
        setfillstyle(SOLID_FILL,WHITE);
    else
        setfillstyle(SOLID_FILL,BLACK);
    fillellipse(x,y,15,15);
}

int panying()
{
    int p1=0,p2=0,i,j,k;
/****************判行**********************/
    for(i=0;i<15;i++)
        for(j=0;j<10;j++)
        {
            for(k=0;k<5;k++)
            {
                if(qp[i][j+k]==1)
                    p1++;
                if(qp[i][j+k]==2)
                    p2++;
            }
            if(p1==5) return 1;
            if(p2==5) return 2;
            p1=p2=0;
        }
/**************判列*******************/
          for(j=0;j<15;j++)
            for(i=0;i<10;i++)
            {
                for(k=0;k<5;k++)
                {
                    if(qp[i+k][j]==1)
                        p1++;
                    if(qp[i+k][j]==2)
                        p2++;
                }
                if(p1==5) return 1;
                if(p2==5) return 2;
                p1=p2=0;
            }
/**************右斜******************/
            for(i=0;i<10;i++)
                for(j=0;j<10;j++)
                {
                    for(k=0;k<5;k++)
                    {
                        if(qp[i+k][j+k]==1)
                            p1++;
                        if(qp[i+k][j+k]==2)
                            p2++;
                    }
                    if(p1==5) return 1;
                    if(p2==5) return 2;
                    p1=p2=0;
                }
/***************左斜*****************/
                for(i=0;i<10;i++)
                    for(j=4;j<15;j++)
                    {
                        for(k=0;k<5;k++)
                        {
                            if(qp[i+k][j-k]==1)
                                p1++;
                            if(qp[i+k][j-k]==2)
                                p2++;
                        }
                        if(p1==5) return 1;
                        if(p2==5) return 2;
                        p1=p2=0;
                    }
}

void cpuai()
{
 int qiju[2][15][15][8][2]={0};     /* 棋型数组*/
 int k,i,j,q,b=0,a=1,d,y1=0,y2=0,x1=0,x2=0;
 int a1[15][15]={0},a2[15][15]={0};
/****************为双方填写棋型表************/
 for(k=0;k<2;k++)
 for(i=0;i<15;i++)
 for(j=0;j<15;j++)
 {
  if(qp[i][j]==0)
  {
   for(q=0;q<8;q++)
   {
    if(k==0) d=1;
    else d=2;
    if(q==0&&j>0)
    {
     for(;;)
     {
      if(qp[i][j-a]==d){b++;a++;continue;}
      else break;
     }
     qiju[k][i][j][q][0]=b;b=0;
     if(qp[i][j-a]==0){qiju[k][i][j][q][1]=1;a=1;}
     else {qiju[k][i][j][q][1]=0;a=1;}
    }
    if(q==1&&i>0&&j>0)
    {
     for(;;)
     {
      if(qp[i-a][j-a]==d){b++;a++;continue;}
      else break;
     }
     qiju[k][i][j][q][0]=b;b=0;
     if(qp[i-a][j-a]==0){qiju[k][i][j][q][1]=1;a=1;}
     else {qiju[k][i][j][q][1]=0;a=1;}
    }
    if(q==2&&i>0)
    {
     for(;;)
     {
      if(qp[i-a][j]==d){b++;a++;continue;}
      else break;
     }
     qiju[k][i][j][q][0]=b;b=0;
     if(qp[i-a][j]==0){qiju[k][i][j][q][1]=1;a=1;}
     else {qiju[k][i][j][q][1]=0;a=1;}
    }
    if(q==3&&i>0&&j<14)
    {
     for(;;)
     {
      if(qp[i-a][j+a]==d){b++;a++;continue;}
      else break;
     }
     qiju[k][i][j][q][0]=b;b=0;
     if(qp[i-a][j+a]==0){qiju[k][i][j][q][1]=1;a=1;}
     else {qiju[k][i][j][q][1]=0;a=1;}
    }
     if(q==4&&j<14)
    {
     for(;;)
     {
      if(qp[i][j+a]==d){b++;a++;continue;}
      else break;
     }
     qiju[k][i][j][q][0]=b;b=0;
     if(qp[i][j+a]==0){qiju[k][i][j][q][1]=1;a=1;}
     else {qiju[k][i][j][q][1]=0;a=1;}
    }
    if(q==5&&i<14&&j<14)
    {
     for(;;)
     {
      if(qp[i+a][j+a]==d){b++;a++;continue;}
      else break;
     }
     qiju[k][i][j][q][0]=b;b=0;
     if(qp[i+a][j+a]==0){qiju[k][i][j][q][1]=1;a=1;}
     else {qiju[k][i][j][q][1]=0;a=1;}
    }
    if(q==6&&i<14)
    {
     for(;;)
     {
      if(qp[i+a][j]==d){b++;a++;continue;}
      else break;
     }
     qiju[k][i][j][q][0]=b;b=0;
     if(qp[i+a][j]==0){qiju[k][i][j][q][1]=1;a=1;}
     else {qiju[k][i][j][q][1]=0;a=1;}
    }
    if(q==7&&j>0&&i<14)
    {
     for(;;)
     {
      if(qp[i+a][j-a]==d){b++;a++;continue;}
      else break;
     }
     qiju[k][i][j][q][0]=b;b=0;
     if(qp[i+a][j-a]==0){qiju[k][i][j][q][1]=1;a=1;}
     else {qiju[k][i][j][q][1]=0;a=1;}
    }
   }
  }
 }
/******************根据评分规则对每一个空格评分***************/
 for(k=0;k<2;k++)
 for(i=0;i<15;i++)
 for(j=0;j<15;j++)
 {
  if(k==0) /*为白棋评分*/
  {
   for(q=0;q<4;q++)
   {
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==4
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=7000;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==3
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=301;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==2
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=43;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==1
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=11;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==4
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][i][j][q+4][1]==1)))
    b+=7000;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==3
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][i][j][q+4][1]==1)))
    b+=63;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==2
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][i][j][q+4][1]==1)))
    b+=6;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==1
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][i][j][q+4][1]==1)))
    b+=1;

   }
    if(b==126||b==189||b==252) b=1500;
    if(b==106) b=1000;

   a1[i][j]=b;b=0;
  }
  if(k==1)  /*为黑棋评分*/
  {
   for(q=0;q<4;q++)
   {
   
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==4
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=30000;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==3
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=1500;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==2
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=51;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==1
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=16;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==4
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][i][j][q+4][1]==1)))
    b+=30000;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==3
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][i][j][q+4][1]==1)))
    b+=71;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==2
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][i][j][q+4][1]==1)))
    b+=7;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==1
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][i][j][q+4][1]==1)))
    b+=2;
   }
   if(b==142||b==213||b==284) b=1500;
   if(b==122) b=1300;

   a2[i][j]=b;b=0;
  }
 }
/****************算出分数最高的空位,填写坐标*********************/
 for(i=0;i<15;i++)
 for(j=0;j<15;j++)
 {
  if(a1[y1][x1]<a1[i][j]) {y1=i;x1=j;}
 }
 for(i=0;i<15;i++)
 for(j=0;j<15;j++)
 {
  if(a2[y2][x2]<a2[i][j]) {y2=i;x2=j;}
 }
 if(a2[y2][x2]>=a1[y1][x1]){x=189+30*x2;y=29+30*y2;}
 else {x=189+30*x1;y=29+30*y1;}
}

[ 本帖最后由 qq349004853 于 2013-1-6 14:32 编辑 ]
搜索更多相关主题的帖子: 如何 对战 人工智能 五子棋 
2008-12-03 19:36
yd30000
Rank: 1
等 级:新手上路
帖 子:37
专家分:0
注 册:2008-12-3
收藏
得分:0 
tc 2.0 通过了吗?
2008-12-03 20:55
qq349004853
Rank: 1
等 级:新手上路
帖 子:31
专家分:0
注 册:2008-3-27
收藏
得分:0 
win-tc上通过,不过win-tc是基于tc 2.0内核的,我想应该能通过吧。
2008-12-03 21:02
ying8501
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:6
帖 子:1092
专家分:1446
注 册:2008-11-24
收藏
得分:0 
谢谢了。
2008-12-03 22:00
zqy110007
Rank: 3Rank: 3
来 自:外太空
等 级:论坛游民
威 望:6
帖 子:1493
专家分:82
注 册:2008-11-19
收藏
得分:0 
你使用的是什么系统??
我的通过了,不过打不开。
我这系统不知道怎么搞的,C语言的图形模式一打开就黑掉,然后就关掉了。。
高手帮个忙啊

每个人都是蛤蟆,只是井的大小不同罢了.
沙石下的泉水,挖得越深,泉水越清.
2008-12-03 22:02
qq349004853
Rank: 1
等 级:新手上路
帖 子:31
专家分:0
注 册:2008-3-27
收藏
得分:0 
回复 第5楼 zqy110007 的帖子
你装的是什么操作系统啊,用的是什么c环境,我的操作系统是windows xp,这个程序的编译环境是win-tc。
2008-12-03 22:11
lz654347621
Rank: 1
等 级:新手上路
帖 子:40
专家分:0
注 册:2008-10-23
收藏
得分:0 
玩了一下被我打败了哈哈  支持源代码的开放 谢谢。!虽然现在还bu怎么看得懂
 以后会看懂的。 。!
2008-12-04 10:11
卧龙孔明
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:59
帖 子:3872
专家分:684
注 册:2006-10-13
收藏
得分:0 
一定程度上给与鼓励与支持,但是希望你抛弃掉tc,否则你的程序只能时候64K内存,无法支持新系统(vista),编译后的代码执行效率低下(貌似比gcc低几十倍)

还有要注意一定的编程技巧性
类似以下这段代码,其实5行内就可以解决了。
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==4
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=7000;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==3
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=301;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==2
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=43;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==1
    &&qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==1)
    b+=11;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==4
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][i][j][q+4][1]==1)))
    b+=7000;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==3
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][i][j][q+4][1]==1)))
    b+=63;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==2
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][i][j][q+4][1]==1)))
    b+=6;
    if((qiju[k][i][j][q][0]+qiju[k][i][j][q+4][0])==1
    &&((qiju[k][i][j][q][1]==1&&qiju[k][i][j][q+4][1]==0)
    ||(qiju[k][i][j][q][1]==0&&qiju[k][j][q+4][1]==1)))
    b+=1;

My Blog: www.aiexp.info
虽然我的路是从这里开始的,但是这里不再是乐土.感谢曾经影响过,引导过,帮助过我的董凯,飞燕,leeco,starwing,Rockcarry,soft_wind等等等等.别了,BCCN.
2008-12-04 12:27
qq349004853
Rank: 1
等 级:新手上路
帖 子:31
专家分:0
注 册:2008-3-27
收藏
得分:0 
回复 第8楼 卧龙孔明 的帖子
呵呵,说得很对,现在tc除了用于学习之外已经没有多大用途了,我现在正在学vc++呢,只是还没有完全掌握,过段时间我会用mfc重做一个。还有代码的问题,有些地方确实存在冗长的问题,可以进一步精简,但由于只是一个学习之作,所以第一次写出来了之后就发表出来了,多谢你的鼓励啊,我会努力的。
2008-12-04 12:40
zqy110007
Rank: 3Rank: 3
来 自:外太空
等 级:论坛游民
威 望:6
帖 子:1493
专家分:82
注 册:2008-11-19
收藏
得分:0 
你们的机子都可以进入图形模式啊??
告诉我怎么进入啊~~

每个人都是蛤蟆,只是井的大小不同罢了.
沙石下的泉水,挖得越深,泉水越清.
2008-12-04 12:41
快速回复:原创 人机对战---------五子棋
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.024927 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved