BUPT Summer Journey #test10 A

 

A. 五子棋AI格式 2014新生暑假个人排位赛10

时间限制 1000 ms     内存限制 65536 KB    

题目描述

设计五子棋AI是一个很简单但是也很考验编程设计功底的事,今天的排位赛就让大家来设计一个五子棋AI。

相信现场的每个人都玩过五子棋,没有玩过的可以现在去玩:http://www.4399.com/special/159.htm

不同的人玩五子棋可能有不同规则,我们统一这一次的比赛规则如下。

1. 棋盘大小为15×15。
2. 白方和黑方轮流下子,棋子不可以下到其他棋子上,黑方先走,对战双方锤子剪刀布决定谁为黑方。
3. 无禁手规则。

4. 谁先让自己的棋子连成五颗或者五颗以上获胜,没有平局,若棋盘下满了还没有获胜则更换先后手再下一盘,程序异常直接判输。

5. 比赛赛制:

    淘汰赛制度,第一轮按照ID和姓名的排序分为8个小组,小组内进行循环赛,每个小组决出两名胜者。

    每一个小组内与其他2-3名选手都要打一盘,积分较高的2名选手进第二轮,同组出现同分的进入晋级池,直到只剩下16个选手。

    第二三轮依然为小组赛,规则同上,每一轮人数减半,最后一轮决出[冠军1个][亚军1个][季军2个]排位赛记分为7,6,5。其余的选手根据轮数分别记为4,3,2,通过oj上的题目的数据,记分分别为1。

 

输入格式

我们的AI测试系统是这样的,给你一个15*15的放了棋子的棋盘,可以看成一个包含012三种字符的矩阵
1表示黑子,2表示白子,0表示没有棋子。
请你设计一个AI程序,输出下一个棋子下哪,如果局面的黑白子相等,你走黑棋,否则走白棋子。
本题目的棋局都是下一步就必赢的棋局,你的AI如果能赢就能得AC。

单组数据。

输出格式

输出两个数字,你所下的棋子的位置。横纵坐标均为1-15的整数。

输入样例

000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000000011210000
000000011120000
000000022221000
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000
000000000000000

输出样例

8 7

 

思路:即判断水平方向,垂直方向,主对角线以及副对角线有没有4个相同的子即可。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
//#define LOCAL
int a[20][20];
int ansx,ansy;
bool ok(int x,int y)
{
    if(x>=1&&x<=15&&y>=1&&y<=15)return true;
    return false;
}
void deal(char turn)
{
    //printf("%c\n",turn);
    //统计横的四子
    for(int i=1;i<=15;i++)
        for(int j=1;j+3<=15;j++)
        {
            if(ok(i,j+3))if(a[i][j]==turn&&a[i][j+1]==turn&&a[i][j+2]==turn&&a[i][j+3]==turn)
            {
                //printf("yes\n");
                int cx1=i,cy1=j-1,cx2=i,cy2=j+4;
                if(ok(cx1,cy1)&&a[cx1][cy1]=='0'){ansx=cx1;ansy=cy1;break;}
                if(ok(cx2,cy2)&&a[cx2][cy2]=='0'){ansx=cx2;ansy=cy2;break;}
            }
        }
 
    //统计竖的四子
    for(int j=1;j<=15;j++)
        for(int i=1;i+3<=15;i++)
            if(ok(i+3,j))if(a[i][j]==turn&&a[i+1][j]==turn&&a[i+2][j]==turn&&a[i+3][j]==turn)
            {
                int cx1=i-1,cy1=j,cx2=i+4,cy2=j;
                //printf("%d %d %d %d\n",cx1,cy1,cx2,cy2);
                //printf("%c %c\n",a[cx1][cy1],a[cx2][cy2]);
                if(ok(cx1,cy1)&&a[cx1][cy1]=='0'){ansx=cx1;ansy=cy1;break;}
                if(ok(cx2,cy2)&&a[cx2][cy2]=='0'){ansx=cx2;ansy=cy2;break;}
            }
    //统计主对角线的四子
    for(int p=2;p<=30;p++)
    {
        int i=p;
        while(i--)
        {
            int j=p-i;
            if(!ok(i,j))continue;
            //printf("%d %d\n",i,j);
            if(ok(i-3,j+3))if(a[i][j]==turn&&a[i-1][j+1]==turn&&a[i-2][j+2]==turn&&a[i-3][j+3]==turn)
            {
                int cx1=i+1,cy1=j-1,cx2=i-4,cy2=j+4;
                if(ok(cx1,cy1)&&a[cx1][cy1]=='0'){ansx=cx1;ansy=cy1;break;}
                if(ok(cx2,cy2)&&a[cx2][cy2]=='0'){ansx=cx2;ansy=cy2;break;}
            }
        }
    }
    //统计副对角线的四子
    for(int p=-14;p<=14;p++)
    {
        int i=1;
        while(i<=15)
        {
            int j=i-p;
            if(!ok(i,j)){i++;continue;}
            if(ok(i+3,j+3))if(a[i][j]==turn&&a[i+1][j+1]==turn&&a[i+2][j+2]==turn&&a[i+3][j+3]==turn)
            {
                int cx1=i-1,cy1=j-1,cx2=i+4,cy2=j+4;
                if(ok(cx1,cy1)&&a[cx1][cy1]=='0'){ansx=cx1;ansy=cy1;break;}
                if(ok(cx2,cy2)&&a[cx2][cy2]=='0'){ansx=cx2;ansy=cy2;break;}
            }
            i++;
        }
    }
}
int main()
{
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    #endif // LOCAL
    int num1=0,num2=0;
    for(int i=1;i<=15;i++)
    {
        for(int j=1;j<=15;j++)
        {
            scanf("%c",&a[i][j]);
            if(a[i][j]=='1')num1++;
            if(a[i][j]=='2')num2++;
        }
        getchar();
    }
    //for(int i=1;i<=15;i++){for(int j=1;j<=15;j++)printf("%c",a[i][j]);printf("\n");}
    char turn;
    if(num1==num2)turn='1';
    else turn='2';
    //printf("turn=%c\n",turn);
    deal(turn);
    printf("%d %d\n",ansx,ansy);
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值