拓展三字棋

题目描述

在 3×3 的棋盘玩三子棋太无聊了,小 A 拉了很多同学一起来玩三子棋,同时棋盘变成了 n×n 的正方形棋盘。

三子棋的规则是每位玩家轮流写下一个字母,同一名玩家的字母相同。当有一名玩家在行、列或者斜线上连续组成了 3 个自己的字母时,即为获胜。

给定棋盘的当前状态,请找出获胜的玩家。

输入格式

输入第一行为一个整数 n。

接下来的 n 行,每行 n 个字符,可能为大写字母或 .(表示没人在这下棋)。

输出格式

输出一行一个大小字母,表示获胜的玩家所写的那种字母。

如果没有人获胜,则输出 ongoing

数据保证最多只有一个人获胜。

输入输出样例

输入 #1

复制代码
3
XOC
XOC
X..

输出 #1

复制代码
X

输入 #2

复制代码
4
....
..A.
AAB.
.B.B

输出 #2

复制代码
ongoing

输入 #3

复制代码
3
ABB
AAA
BBA

输出 #3

复制代码
A

说明/提示

对于 100% 的数据,保证 1≤n≤30。

分析题目

这道题的关键在于检查棋盘上是否存在连续三个相同的非空字符(X 或 O)。

检查所有可能的行、列、对角线是否存在连续三个相同的字符

具体要怎么实现呢?

  • 遍历棋盘 :对每个位置(i, j)检查是否为有效字符
  • 检查四个方向
    • 水平方向 :检查(i, j)右侧两个位置
    • 垂直方向 :检查(i, j)下方两个位置
    • 主对角线方向:检查右下方向两个位置
    • 副对角线方向:检查左下方向两个位置
  • 边界条件(很重要!!):确保遍历的位置不越界

这个思路的关键在于通过双重循环遍历棋盘的每个位置,并在每个位置上检查四个方向的连续性,确保能够覆盖所有的获胜情况。

那根据这个思路,可以写出初步代码

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
char win(char a[][35],int n)
{
    for(int i=0;i<n;i++)
	{
        if(a[i][0]!='.' && a[i][0]==a[i][1] && a[i][1]==a[i][2])
		{
            return a[i][0];
        }
    }
    for(int j=0;j<n;j++)
	{
        if(a[0][j]!='.' && a[0][j]==a[1][j] && a[1][j]==a[2][j])
		{
            return a[0][j];
        }
    }
    if(a[0][0]!='.' && a[0][0]==a[1][1] && a[1][1]==a[2][2])
	{
        return a[0][0];
    }
    if(a[0][2]!='.' && a[0][2]==a[1][1] && a[1][1]==a[2][0])
	{
        return a[0][2];
    }
    return ' ';
}
int main()
{
    int n;
    cin>>n;
    char a[35][35];
    for(int i=0;i<n;i++)
	{
        string row;
        cin>>row;
        for(int j=0;j<n;j++)
		{
            a[i][j]=row[j];
        }
    }
    char w=win(a,n);
    if(w!=' ')
	{
        cout<<w;
    }
	else
	{
        cout<<"ongoing";
    }
    return 0;
}

但是提交之后就会发现,这个代码只得了30分

这是为什么呢?

错误代码分析

仔细观察可以发现,这个代码没有符合题目给出的数据范围条件

win 函数里,仅仅对 n = 3 的情况进行了判断,也就是只检查了固定的行(每一行的第 0、1、2 列)、列(每一列的第 0、1、2 行 )以及两条斜线(主对角线 a[0][0]a[1][1]a[2][2] 和副对角线 a[0][2]a[1][1]a[2][0] )是否有连续三个相同且非 . 的字符。

但题目中 n 是可以变化的(范围 1 ≤ n ≤ 30 ),当 n > 3 时,这个代码便无法判断其他存在连续三个相同字符的行、列、斜线情况。

正确代码

通过遍历每个位置,并在每个位置上动态地检查行、列、斜线方向是否有连续三个相同字符的方式

以下是实现的步骤

首先最重要的是遍历棋盘的每一个位置,当遇到非 . 的字符时,从该位置出发,去检查其所在的行、列、两条斜线方向上,是否存在连续三个相同的字符。

接下来是关于行,列,对角线的判断:

对于行方向,要检查当前位置向右连续两个位置(即 j + 2 < n 时,判断 a[i][j]a[i][j + 1]a[i][j + 2] 是否相同且非 . )。

对于列方向,要检查当前位置向下连续两个位置(即 i + 2 < n 时,判断 a[i][j]a[i + 1][j]a[i + 2][j] 是否相同且非 . )。

对于主对角线方向(从左上到右下 ),要检查当前位置向右下连续两个位置(即 i + 2 < nj + 2 < n 时,判断 a[i][j]a[i + 1][j + 1]a[i + 2][j + 2] 是否相同且非 . )。

对于副对角线方向(从右上到左下 ),要检查当前位置向左下连续两个位置(即 i + 2 < nj - 2 >= 0 时,判断 a[i][j]a[i + 1][j - 1]a[i + 2][j - 2] 是否相同且非 . )。

最后是胜负判断。如果在任何一种检查中发现了连续三个相同且非 . 的字符,就返回对应的字符,表示该玩家获胜;

如果遍历完整个棋盘都没有找到这样的情况,就返回 ' '

主函数中再根据返回值判断输出获胜字符还是 ongoing

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

char win(char a[][35], int n) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (a[i][j] == '.') {
                continue; 
            }
            if (j + 2 < n && a[i][j] == a[i][j + 1] && a[i][j + 1] == a[i][j + 2]) {
                return a[i][j];
            }
            if (i + 2 < n && a[i][j] == a[i + 1][j] && a[i + 1][j] == a[i + 2][j]) {
                return a[i][j];
            }
            if (i + 2 < n && j + 2 < n && a[i][j] == a[i + 1][j + 1] && a[i + 1][j + 1] == a[i + 2][j + 2]) {
                return a[i][j];
            }
            if (i + 2 < n && j - 2 >= 0 && a[i][j] == a[i + 1][j - 1] && a[i + 1][j - 1] == a[i + 2][j - 2]) {
                return a[i][j];
            }
        }
    }
    return ' ';
}

int main() {
    int n;
    cin >> n;
    char a[35][35];
    for (int i = 0; i < n; i++) {
        string row;
        cin >> row;
        for (int j = 0; j < n; j++) {
            a[i][j] = row[j];
        }
    }
    char w = win(a, n);
    if (w != ' ') {
        cout << w;
    } else {
        cout << "ongoing";
    }
    return 0;
}
相关推荐
Gappsong87412 分钟前
Rufus:Ubuntu U盘启动盘制作工具详解
linux·c++·web安全·网络安全
এ᭄画画的北北1 小时前
力扣-198.打家劫舍
算法·leetcode
橙小花1 小时前
C语言:break、continue、猜拳游戏
c语言·算法·游戏
Kira Skyler1 小时前
c++,从汇编角度看lambda
汇编·c++
Algebraaaaa2 小时前
C++ 多线程中成员函数如何传参?拷贝、引用还是指针?
开发语言·c++
程序员编程指南2 小时前
Qt开发环境搭建全攻略(Windows+Linux+macOS)
linux·c语言·c++·windows·qt
Mr_Swilder2 小时前
一种可扩展且可用于生产环境的天空与大气渲染技术
前端·javascript·算法
Himon2 小时前
LLM参数有效性学习综述
人工智能·算法·nlp
এ᭄画画的北北2 小时前
力扣-300.最长递增子序列
算法·leetcode
晨曦学习日记2 小时前
Leetcode题解:209长度最小的子数组,掌握滑动窗口从此开始!!!
数据结构·算法·leetcode