程设训练作业1.3——五子棋胜利者判断问题

【问题描述】

已知两人分别执白棋和黑棋在一个围棋棋盘上下五子棋,若同一颜色的棋子在同一条横行、纵行或斜线上连成5个棋子,则执该颜色棋子的人获胜。编写程序读入某一时刻下棋的状态,并判断是否有人获胜。
输入的棋盘大小是19×19,用数字0表示空位置(即没有棋子),用数字1表示该位置下了一白色棋子,用数字2表示该位置下了一黑色棋子。假设同一颜色的棋子在同一条横行、纵行或斜线上连成的棋子个数不会超过5个,并且最多有一人连成线的棋子个数为5。

【输入形式】

从控制台输入用来表示棋盘状态的数字0、1或2;每行输入19个数字,各数字之间以一个空格分隔,每行最后一个数字后没有空格;共输入19行表示棋盘状态的数字。

【输出形式】

若有人获胜,则先输出获胜人的棋子颜色(1表示白色棋子,2表示黑色棋子),然后输出英文冒号:,最后输出连成5个棋子连线的起始位置(棋盘横行自上往下、纵行自左往右从1开始计数,横行最小的棋子在棋盘上的横行数和纵行数作为连线的起始位置,两数字之间以一个英文逗号,作为分隔符)。
若没有人获胜,则输出英文字符串:No。
无论输出什么结果,最后都要有回车换行符。

【输入样例1】

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 2 0 1 1 2 0 0 0 0 0 0 0
0 0 0 0 0 2 1 1 1 1 2 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 1 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 2 2 0 0 0 0 0 0 0 0
0 0 0 0 0 2 0 1 0 0 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 1 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

【输出样例1】

1:9,8

【输入样例2】

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

【输出样例2】

No

【样例说明】

在输入的样例1中,执白棋(数字1表示)的人已经获胜,连成5个棋子的起始位置在第9行第8列,所以输出1:9,8。
在输入的样例2中,还没有同一颜色的棋子连成5个,所以无人获胜,直接输出No。

算法说明

此处的方法依然比较暴力。嘤嘤嘤。总的思想是挨个判断五子棋胜利的四种条件是否符合(横5/竖5/左斜5/右斜5)

  1. 读取键盘输入。存储为稀疏矩阵
  2. 根据黑白棋子个数选择需要判断的棋子颜色。
  3. 分别对棋子进行横5/竖5/左斜5/右斜5的判断
  4. 将胜利棋子的初始位置存放在全局变量中
  5. 根据返回值得到胜利方,并输出初始位置。

下图所示为判断左斜5时,将每一斜列重新整形为同一横排,判断横5是否成立。
在这里插入图片描述
代码如下:

#include <stdio.h>
#include <stdlib.h>
int end[1][2];

//判断横5是否成立
int judgex(int a[][2],int k){
    for(int i=0;i+4 <= k;i++){
        if(a[i+4][0] == a[i][0] && a[i+4][1] == a[i][1]+4){ //若横5成立则满足该条件
            end[0][0] = a[i][0]; //存储位置信息
            end[0][1] = a[i][1];
            return 1;
        }
    }
    return 0;
}
//判断竖5是否成立
int judgey(int a[][2],int k){
    int new_a[k][2];  //存储整形之后的矩阵,即将原矩阵的每一竖列整形为同一横排
    int i,j,m;
    int tem=0,max=a[0][1];

    for(m=0;m<k;m++)
        if(a[m][1]>max){
            max=a[m][1];  //获得棋子所在位置列最大值
        }

    for(i=0;i<max;i++)  //每一列循环一次
        for(j=0;j<k;j++){ //遍历所有棋子
            if(a[j][1] == i){ //当为第i列时,为所寻棋子
                new_a[tem][0] = i;  //行列坐标交换
                new_a[tem++][1] = a[j][0];
            }
        }
    int change;
    if(judgex(new_a,k)){ //若存在5连,则将位置复原为整形前
        change = end[0][0]; 
        end[0][0] = end[0][1];
        end[0][1] = change;
        return 1;
    }
    else
        return 0;
}

//判断左斜5是否成立
int judgezuoxie(int a[][2],int k){
    int new_a[k][2];
    int tem=0;
    int i,j;

    for(i=-14;tem<k && i<15;i++) //对原始矩阵整形,使得每一左斜的棋子在同一行上
        for(j=0;j<k;j++)
            if(a[j][0]-a[j][1]==i){
                new_a[tem][0] = i+14;
                new_a[tem++][1] = a[j][1];
            }
    if(judgex(new_a,k)){ //坐标复原
        end[0][0]=end[0][0]-14+end[0][1];
        return 1;
    }
    else
        return 0;
}
//判断右斜5是否成立
int judgeyouxie(int a[][2],int k){
    int new_a[k][2];
    int i,j;
    int tem =0;

    for(i=4;tem<k && i<33;i++)//整形
        for(j=0;j<k;j++){
            if(a[j][0]+a[j][1]==i){
                new_a[tem][0] = i-4;
                new_a[tem++][1] = 18-a[j][1];
            }
        }
    if(judgex(new_a,k)){//复原
        end[0][1] = 18-end[0][1];
        end[0][0] = end[0][0]+4-end[0][1];
        return 1;
    }
    else
        return 0;
}


int main()
{
    int i,j,k1,k2,tem;
    k1=0;k2=0;
    int a1[19*19][2];//存储白棋子位置信息
    int a2[19*19][2];//存储黑棋子位置信息

    for(i=0;i<19;i++){
        for(j=0;j<19;j++){
            scanf("%d",&tem);
            if(tem == 1){   //判断棋子种类
                a1[k1][0]=i;  //写入棋子位置
                a1[k1++][1]=j;
            }
            else if(tem == 2){
                a2[k2][0]=i;
                a2[k2++][1]=j;
            }
        }
    }
    
    
    
    if(k1 < 5 && k2 < 5)  //若两种棋子个数均小于5,则不可能存在胜者
        printf("No\n");
    else if(k1 >= 5 && k2 >= 5){  //对两种棋子均进行判断
        if(judgex(a1,k1) || judgey(a1,k1) || judgezuoxie(a1,k1)||judgeyouxie(a1,k1)){
            printf("1:%d,%d\n",end[0][0]+1,end[0][1]+1);  //由于代码中棋子位置从0计数,输出要求从1计数
        }
        else if(judgex(a2,k2) || judgey(a2,k2) || judgezuoxie(a2,k2)||judgeyouxie(a2,k2)){
            printf("2:%d,%d\n",end[0][0]+1,end[0][1]+1);
        }
        else
            printf("No\n");
    }
    else if(k1 >= 5 && k2<5){  
        if(judgex(a1,k1) || judgey(a1,k1) || judgezuoxie(a1,k1)||judgeyouxie(a1,k1)){
            printf("1:%d,%d\n",end[0][0]+1,end[0][1]+1);
        }
        else
            printf("No\n");
    }
    else if(k1 < 5 && k2>=5){
        if(judgex(a2,k2) || judgey(a2,k2) || judgezuoxie(a2,k2)||judgeyouxie(a2,k2)){
            printf("2:%d,%d\n",end[0][0]+1,end[0][1]+1);
        }
        else
            printf("No\n");

    }
    return 0;
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构习题:已知两人分别执白棋和黑棋在一个围棋棋盘上下五子棋,若同一颜色的棋子在同一条横行、纵行或斜线上连成5个棋子,则执该颜色棋子的人获胜。编写程序读入某一时刻下棋的状态,并判断是否有人即将获胜,即:同一颜色的棋子在同一条横行、纵列或斜线上连成4个棋子,且该4个棋子的两端至少有一端为空位置。 输入的棋盘大小是19×19,用数字0表示空位置(即没有棋子),用数字1表示该位置下了一白色棋子,用数字2表示该位置下了一黑色棋子。假设同一颜色的棋子在同一条横行、纵列或斜线上连成的棋子个数不会超过4个,并且最多有一人连成线的棋子个数为4。 【输入形式】 从控制台输入用来表示棋盘状态的数字0、1或2;每行输入19个数字,各数字之间以一个空格分隔,每行最后一个数字后没有空格;共输入19行表示棋盘状态的数字。 【输出形式】 若有人即将获胜,则先输出即将获胜人的棋子颜色(1表示白色棋子,2表示黑色棋子),然后输出英文冒号:,最后输出连成4个棋子连线的起始位置(棋盘横行自上往下、纵列自左往右从1开始计数,横行最小的棋子在棋盘上的横行数和纵列数作为连线的起始位置,若在同一行上,则纵列数最小的棋子位置作为起始位置,两数字之间以一个英文逗号,作为分隔符)。 若没有人获胜,则输出英文字符串:No。 无论输出什么结果,最后都要有回车换行符。
下面是一个简单的五子棋胜利判断代码,假设棋盘大小为15x15,1代表黑棋,2代表白棋。 ```C++ int check_win(int board[15][15], int player) { // 判断横向是否有五子连珠 for (int i = 0; i < 15; i++) { for (int j = 0; j <= 10; j++) { if (board[i][j] == player && board[i][j+1] == player && board[i][j+2] == player && board[i][j+3] == player && board[i][j+4] == player) { return player; } } } // 判断纵向是否有五子连珠 for (int i = 0; i <= 10; i++) { for (int j = 0; j < 15; j++) { if (board[i][j] == player && board[i+1][j] == player && board[i+2][j] == player && board[i+3][j] == player && board[i+4][j] == player) { return player; } } } // 判断左上到右下是否有五子连珠 for (int i = 0; i <= 10; i++) { for (int j = 0; j <= 10; j++) { if (board[i][j] == player && board[i+1][j+1] == player && board[i+2][j+2] == player && board[i+3][j+3] == player && board[i+4][j+4] == player) { return player; } } } // 判断左下到右上是否有五子连珠 for (int i = 4; i < 15; i++) { for (int j = 0; j <= 10; j++) { if (board[i][j] == player && board[i-1][j+1] == player && board[i-2][j+2] == player && board[i-3][j+3] == player && board[i-4][j+4] == player) { return player; } } } // 没有五子连珠 return 0; } ``` 这个函数的返回值为0表示没有五子连珠,1表示黑棋胜利,2表示白棋胜利。函数的实现比较简单,就是对于每个位置,分别判断横向、纵向、左上到右下、左下到右上四个方向是否有五子连珠。如果有,就返回相应的胜利方。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值