这是我参与「第七届青训营 」伴学笔记创作活动的第6天
今天的代码练习题目是:
五子棋获胜策略
问题描述
假设存在一个五子棋棋盘,大小未知。棋盘上已经摆放了一些白色棋子,现在你的手中还有一个白色棋子。你的任务是找出在棋盘的哪些位置摆放这个棋子,能够使棋盘上出现五颗棋子连成一线(不限于横向、纵向或斜向)。 备注:棋盘上当前不存在连成一条线的五个棋子,但至少存在一个点可以通过摆放使得形成五子连线。
测试样例
样例1:
输入:
n = 6, array = [[0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0]]
输出:[[1, 1], [6, 6]]
样例2:
输入:
n = 5, array = [[1, 0, 1, 0, 0], [0, 1, 0, 0, 0], [1, 0, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 0]]
输出:[[5, 5]]
样例3:
输入:
n = 5, array = [[1, 0, 1, 0, 0], [1, 1, 0, 0, 0], [1, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 0]]
输出:[]
题目解析
这个题目跟我之前做过的一个题目很像,那个是动态的,双方互相落子判断谁胜利,这个是给你一个棋局,没有黑白方,判断落子胜利有几种方式,原理就是落子时,判断上下左右左斜右斜,且在规定范围内,是否可以达到五子连珠。
代码如下:
import java.util.ArrayList; import java.util.List; public class Main { // 检查某个位置是否可以形成五子连线 public static boolean canFormLine(int x, int y, int[][] board, int n) { // 定义四个方向:右,下,右下,左下 int[][] directions = {{1, 0}, {0, 1}, {1, 1}, {1, -1}};
for (int[] dir : directions) {
int count = 1; // 当前位置记为1
int dx = dir[0], dy = dir[1];
// 检查正向
for (int step = 1; step < 5; ++step) {
int nx = x + dx * step;
int ny = y + dy * step;
if (nx >= 0 && nx < n && ny >= 0 && ny < n && board[nx][ny] == 1) {
count++;
} else {
break;
}
}
// 检查反向
for (int step = 1; step < 5; ++step) {
int nx = x - dx * step;
int ny = y - dy * step;
if (nx >= 0 && nx < n && ny >= 0 && ny < n && board[nx][ny] == 1) {
count++;
} else {
break;
}
}
// 如果形成五子连接,则返回 true
if (count >= 5) return true;
}
return false; // 没有符合条件的连线
}
// 主解决方案函数
public static int[][] solution(int n, int[][] board) {
List<int[]> results = new ArrayList<>();
// 检查每个位置是否能放置新棋子形成五子连线
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == 0) { // 只检查空位
if (canFormLine(i, j, board, n)) {
results.add(new int[]{i + 1, j + 1}); // 记录行列,+1因要求从1开始
}
}
}
}
// 将结果转换为二维数组
int[][] resultArray = new int[results.size()][2];
for (int i = 0; i < results.size(); i++) {
resultArray[i] = results.get(i);
}
return resultArray.length > 0 ? resultArray : new int[][]{}; // 如果没有结果,返回 {-1, -1}
}
public static void main(String[] args) {
// 测试用例
int[][] array = {
{0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0},
{0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0}
};
int[][] expectedOutput = {{1, 1}, {6, 6}};
System.out.println(java.util.Arrays.deepEquals(solution(6, array), expectedOutput)); // 验证测试结果
}
}
学习方法与心得
今天想和大家分享的是:AI刷题功能对我的学习影响
在学习编程的道路上,AI刷题功能的出现宛如一盏明灯,为我的学习之旅带来了前所未有的积极影响。
一、高效掌握编程思维
编程思维是编程学习的核心,而AI刷题功能大大加速了我对它的理解与掌握。传统的刷题方式往往是从书本或题库中随机挑选题目,做完后对照答案理解。但AI刷题功能有着独特的优势。它能根据我的知识水平和学习进度,精准推送具有针对性的题目。比如,当我在学习循环结构的初期,它会先给我一些简单的单层循环应用题目,像计算1到100的整数和。在解题过程中,我逐渐理解了循环变量的初始化、条件判断和迭代更新的重要性。
随着我对基础循环的掌握,AI又会推送涉及多层嵌套循环的题目,如打印九九乘法表。这不仅考验我对循环结构的运用,更让我体会到如何通过内层和外层循环的配合来解决复杂问题。而且,AI在每道题后都会提供详细的解题思路,包括从算法设计到代码实现的整个过程。这让我学会了如何将实际问题转化为编程问题,如何选择合适的数据结构和算法来解决问题,从而高效地培养了我的编程思维。
二、知识掌握程度的显著提升
在使用AI刷题功能之前,我对知识的掌握往往是碎片化的。学习一个新的知识点后,可能只是在理论上理解了,但在实际应用中却困难重重。然而,通过大量有针对性的刷题,这种情况得到了极大的改善。
以函数这一知识点为例,刚开始我只是记住了函数的定义、参数和返回值的概念。但在AI刷题过程中,我遇到了各种各样关于函数的题目,如函数的递归调用、函数作为参数传递给其他函数等。在不断地解题过程中,我真正理解了函数在编程中的灵活性和强大功能。以前对于递归函数的理解仅仅停留在书本上的定义,通过刷一道计算斐波那契数列的递归函数题目,我深刻理解了递归的调用过程和终止条件,并且能够熟练地写出类似的递归代码。
在数据结构方面,学习数组时,我从简单的数组元素访问和修改题目,到利用数组解决排序、查找等算法问题。这一系列的刷题过程让我对数组的存储方式、操作方法和应用场景有了全方位的认识。刷题后,我对知识的掌握不再是孤立的点,而是形成了相互关联的知识网络。我可以灵活地运用各种知识来解决综合性的编程问题,知识的深度和广度都得到了显著的拓展。
三、学习效率和动力的提升
AI刷题功能还极大地提高了我的学习效率和学习动力。它的智能提示和实时反馈功能让我能够迅速发现自己的错误并及时改正。当我在编写代码出现语法错误或者逻辑漏洞时,AI会准确地指出问题所在,并给出相应的修改建议。这避免了我在一个问题上花费过多的时间去猜测和调试,使学习过程更加顺畅。
同时,AI刷题系统中的排行榜和成就系统也激发了我的学习动力。看到自己在刷题过程中的进步和与其他学习者的排名对比,我会有一种竞争意识,想要不断地挑战自己,提高自己的刷题速度和正确率。而且,每当我完成一个阶段的刷题任务或者掌握了一个新的知识点,系统给予的成就奖励会让我产生强烈的满足感和成就感,进一步激发我继续学习的热情。
总之,AI刷题功能为我的编程学习带来了深刻的积极影响。它不仅帮助我更加高效地掌握编程思维,提升了知识的掌握程度,还极大地提高了我的学习效率和动力,让我在编程学习的道路上越走越稳,越走越远。