五子棋(Version.2 函数模拟迭代解法)

文章介绍了通过编程模拟五子棋盲棋比赛的过程,关注落子策略和判断胜负的算法实现。
摘要由CSDN通过智能技术生成

题面:

张学长和孙学长最近迷上了五子棋,但是看着棋局下棋总感觉差点什么东西——高手的风范,于是两人就开始下盲棋,但是两人的脑阔都不是太灵光,没办法记下所有的落子,所以就先写下落子的坐标后再去棋盘落子,最后才知道是那个获胜,这里将棋盘看成是一个N*N (N=20) 的二维矩阵,刚开始时通过摇骰子的方式决定那个先手(点数大的先手,不存在点数相等的情况),每一次落子都是(i ,j)1<=i,j<=20 表示落子的坐标,问经过M(9<=M<=60)次落子后是未分输赢还是有赢方,由于两人刚开始下盲棋,所以不知道到底有没有人获胜,所以哪怕有一方已经获胜了也还会继续下棋,当两人都感觉到有一方获胜后才会停止下棋(也可能会感觉错^_^)。

输入格式:

第一行输入A,B分别表示张学长的点数和孙学长的点数
第二行输入M。接下来M行每行输入一个落子的坐标。

输出格式:

如果未分输赢只需要输出Draw即可,否则就先输出赢家的编号(张学长编号为A,孙学长编号为B)空格后输出赢家落了多少棋子就赢了。

输入样例:

1 6
12
6,10
5,11
7,11
6,12
5,9
7,13
8,12
8,14
4,8
9,13
4,10
9,15

输出样例:

B 5

样例棋局:

image.png

题解思路:

本质上是模拟题,在代码深度方面的难度是基本等同于语法题的,但是确实相对冗余繁杂了一些,个人认为,在写这道题的代码前要真正的理解题面在讲述什么,很可能你没有AC的原因只是因为理解错了题意......

说几个比较容易忽略的点:

1.可能很多人和我一样拿到这题的第一时间是想到直接当图论,二维数组模拟直接做的,这里就先要注意:五子棋是一个博弈型游戏,双方的落子必须要区分开,要打上不同的标记。

2.对于五子棋的规则要有基本的了解,获胜的条件就是一条线上(纵向、横向、斜向)连通了大于等于5个棋子(注意是存在大于5的情况的)。

3.可以适当分析简化题目中的操作,因为有没有人获胜是由我们设计的代码系统实时判断的,那么一定是由于某一次的落子之后才会首次产生胜利者,在落下这颗关键的棋子之前,不可能提前产生胜利者。

明确上述各点之后,做这题会顺畅很多。由于本质上就是模拟题,做法是非常之多的,首先就不一定是使用图论的思想(笑),之所以提出这种迭代模拟的解法,主要是考虑到不是所有人都能在赛时反应过来用更简化的递归、回溯等算法,或者用得不熟练,而这题是不那么复杂的固定层数问题, 完全可以用比较容易想到的正向思维迭代算法直接模拟出来,于是谨在这里提出个人的思路。

题解代码:

代码看起来确实比较长,但是我这里是为了方便写题解,把所有步骤(包括相似重复的部分)的底层实现都放出来写的。实际做题过程中,完全可以把判断的步骤封装在一个方法函数中,大大节省代码量(初步估计可以节约大概一半,所以最终也就60~70行可以解决)。

OS:所以这题比起考编程能力,个人认为更侧重于对应用型思维和封装能力的考察,思路转得过来和转不过来的两种做题过程会有比较大的差异。

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

using namespace std;
const int N=25;
int G[N][N];            //用二维矩阵形式存储棋盘的状态
int dt[]={1, 2, 3, 4};    //用一维数组存储下标的偏移量,因为是五子棋,只用偏移4次即可

bool Check(int, int, int);

int main(void){
    int pa, pb;        //pa,pb分别代表张、孙的点数
    char op;
      cin>>pa>>pb;

    int m;
      cin>>m;

    for(int i=1;i<=m;i++){
        int x, y;
          cin>>x>>op>>y;
        //输入下标,存在G数组内部,形成棋盘的格局

        if(i%2==1){
            if(pa>pb) G[x][y]=1;        //这里通过奇偶判断+点数大小对比,固定代表张的落子都为“1”,孙的落子都为“2”
            else G[x][y]=2;
        }else{
            if(pa>pb) G[x][y]=2;
            else G[x][y]=1;
        }

        if(Check(x, y, G[x][y])){    //判断是否有人胜出
            if(pa>pb){            //这里的处理与上文类似,判断胜利者的编号及落子数
                if(G[x][y]==1) cout<<"A "<<(i+1)/2<<'\n';
                        //可以推出,对于先手的人来说,他当前总共的落子数是((i+1)/2)
                                //对于后手的人来说,他当前落子数量是i/2
                else cout<<"B "<<i/2<<'\n';
            }else{
                if(G[x][y]==2) cout<<"B "<<(i+1)/2<<'\n';
                else cout<<"A "<<i/2<<'\n';
            }

            return 0;        //当有人提前胜出,程序也提前结束
        }
    }

      cout<<"Draw\n";
    //经过上述判断之后程序没有提前结束,即说明是不分胜负的情况
    return 0;
}


bool Check(int x, int y, int w){
    //判断是否有人胜出,x与y代表棋盘的坐标{x,y},w代表当前下的是谁的棋子
    //因为之前代码的处理,已经明确1是张的落子,2是孙的落子,这里就只需要判断w是1还是2

    int res=1;
    //res保存当前能够连在一起的棋子数量,初始是1(这次落下的1个)

    //下列8个循环,两两作为一组,方便用来判断当前棋子
    //1.纵向有没有连出大于等于5个的棋子
    //2.横向有没有连出大于等于5个的棋子
    //3.自右上向左下的方向有没有连出大于等于5个的棋子
    //4.自左上向右下的方向有没有连出大于等于5个的棋子

    //这里是为了便于读者理解内部底层实现所以写出8个相似的循环,
    //实际上如果理解了,完全可以把这8个循环封装在一个执行函数里面,至少可以节省一半代码量

    for(int i=0;i<4;i++){    //判断纵向
        int nx=x+dt[i];    //相当于是把x坐标进行四次操作,分别是x=x+1, x=x+2, x=x+3, x=x+4,迭代5次,判断有没有连出五个相同棋子
        if(nx<=20&&G[nx][y]==w) res++;    //没有越出棋盘边界,且是相同的棋子,相连棋子的数量res就可以+1

        //在对下标进行移动时,严格注意最大范围要求,在这种做法中,本题棋盘的上界是20,下界是1
        //所以在增加下标时要保证增加之后<=20,减少时保证减少之后>=1

        else break;
        //判断出已经抵达棋盘边界或存在另一种棋子,及时结束循环,进入之后的判断
    }
    for(int i=0;i<4;i++){
        int nx=x-dt[i];    //相当于是把x坐标进行四次操作,分别是x=x-1, x=x-2, x=x-3, x=x-4,迭代5次,判断有没有连出五个相同棋子
        if(nx>=1&&G[nx][y]==w) res++;
        else break;
    }
    if(res>=5) return true;    //判断出已经存在大于等于5个棋子相连了,代表有人已经胜出,返回true

    //以下就是代码、判断与上面完全相同,仅仅作用不同的部分,是完全可以封装起来的
    res=1;    //注意对每一种方向进行判断时,对res进行初始化,因为横向纵向斜向的棋子是不能连在一起讨论的
    for(int i=0;i<4;i++){
        int ny=y+dt[i];
        if(ny<=20&&G[x][ny]==w) res++;
        else break;
    }
    for(int i=0;i<4;i++){
        int ny=y-dt[i];
        if(ny>=1&&G[x][ny]==w) res++;
        else break;
    }
    if(res>=5) return true;

    res=1;
    for(int i=0;i<4;i++){
        int nx=x-dt[i], ny=y+dt[i];        //等同于对x-1~4, y+1~4
        if(nx>=1&&ny<=20&&G[nx][ny]==w) res++;
        else break;
    }
    for(int i=0;i<4;i++){
        int nx=x+dt[i], ny=y-dt[i];
        if(nx<=20&&ny>=1&&G[nx][ny]==w) res++;
        else break;
    }
    if(res>=5) return true;

    res=1;
    for(int i=0;i<4;i++){
        int nx=x-dt[i], ny=y-dt[i];
        if(nx>=1&&ny>=1&&G[nx][ny]==w) res++;
        else break;
    }
    for(int i=0;i<4;i++){
        int nx=x+dt[i], ny=y+dt[i];
        if(nx<=20&&ny<=20&&G[nx][ny]==w) res++;
        else break;
    }
    if(res>=5) return true;

    return false;
    //当最终都没有发现大于等于5个棋子相连的情况,说明没有人提前胜出,返回false
}

### 回答1: 支持人机对战的五子棋软件.zip是一个帮助玩家提高五子棋水平的电脑程序。这个软件结合了人工智能技术和五子棋的规则,可以提供给玩家一个有趣而充满挑战的游戏环境。 首先,这个软件具有人机对战的功能,玩家可以选择与电脑进行对弈。电脑的AI(人工智能)算法经过精心设计,可以根据对手的动作给出最佳的应对策略。这样一来,玩家可以通过与电脑对战来提高自己的棋艺水平。 其次,这个软件还提供了不同难度级别的选项。对于初学者来说,可以选择较低级别的电脑对手,以便逐步熟悉游戏规则和基本策略。而对于资深玩家来说,可以选择更高级别的电脑对手,挑战更高水平的对手,提升自己的技术。 此外,这个软件还有一些其他的功能,比如悔棋、暂停和计时器等。这些功能可以增强玩家的游戏体验和操作便捷性。当玩家犯错误或者需要暂停游戏时,可以随时使用悔棋和暂停功能。而计时器则可以帮助玩家更好地掌握时间,增加游戏的紧张感。 综上所述,支持人机对战的五子棋软件.zip是一个很有用的工具,可以同时提供娱乐和训练功能。它不仅可以帮助玩家提高五子棋水平,还提供了丰富的功能和游戏体验。无论是初学者还是资深玩家,都能从中受益。 ### 回答2: 人机对战的五子棋软件.zip是一款支持玩家与计算机进行对战的五子棋游戏程序。该软件具有以下几个特点和优势。 首先,该软件提供了真实的五子棋对战体验。虽然五子棋是一种简单的游戏规则,但由于计算机可以进行高级的算法和思考,因此与计算机对战可以提供一种更具挑战性和令人满足的游戏体验。 其次,该软件具有不同难度级别的设定。用户可以选择不同的难度等级与计算机进行对战,从简单到困难等级设定,满足不同玩家的需求。对于新手玩家,可以选择较低的难度进行练习和熟悉游戏规则。而对于有经验的玩家,可以选择较高的难度与计算机进行挑战,提升自己的棋力。 第三,该软件提供了多种功能和设置选项。用户可以根据自己的喜好和需求,对游戏界面、音效、游戏难度等进行调整和设定,以达到最佳的游戏体验。 最后,该软件界面简洁、操作便捷,易于上手。无论是新手还是有经验的玩家,都可以轻松上手,享受游戏的乐趣。 总之,支持人机对战的五子棋软件.zip提供了真实、挑战性强的五子棋对战体验,具有不同难度级别的设定,提供了多种功能和设置选项,并具备简洁、便捷的操作界面。相信这款软件能够满足五子棋爱好者的需求,带来愉快的游戏体验。 ### 回答3: 支持人机对战的五子棋软件.zip 是一个可以在电脑上进行五子棋对战的程序文件。这个软件具有以下几个特点和优势。 首先,支持人机对战意味着无论是新手还是高手都能够享受到游戏的乐趣。对于初学者来说,软件提供了强大的人工智能对手,可以提供简单的难度供他们在游戏中慢慢成长。而对于高手来说,软件也提供了更高级别的难度,可以为他们提供有挑战性的对手。 其次,这个软件操作简单方便。用户只需要下载并解压文件,即可开始游戏。软件界面友好,有清晰的棋盘和明亮的棋子颜色,使得游戏过程更加舒适和易于操作。 除此之外,软件还提供了多种游戏模式。玩家可以选择与人工智能对战,也可以选择与其他玩家在线对战,这样能够更好地锻炼自己的棋艺并与其他玩家交流互动。 此外,软件还具备一些辅助功能。比如,它会给出一些提示和建议,帮助玩家更好地形成对策。同时,软件还具备保存和读取游戏记录以及回放功能,便于玩家进行复盘和分析,提高自己的下棋水平。 综上所述,支持人机对战的五子棋软件.zip 具备了简便操作、多种游戏模式和辅助功能等特点和优势,能够满足不同玩家的需求,并为他们带来愉快的游戏体验。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值