本文共有三个问题,有助于初步学习java语言和理解面向对象编程
一. MagicSquare
A magic square of order n is an arrangement of n×n numbers, usually distinct integers, in a square, such that the n numbers in all rows, all columns, and both diagonals sum to the same constant (see Wikipedia: Magic Square).
You are to write a Java program (MagicSquare.java) for checking the row/column/diagonal values of a matrix and then judging whether it is a magic squares.
- We give you five text files: 1.txt, 2.txt, ..., 5.txt. Download them from https://github.com/rainywang/Spring2021_HITCS_SC_Lab1/tree/master/P1 and add them into your project directory \src\P1\txt\;
- 需要能够处理输入文件的各种特殊情况,例如:文件中的数据不符合Magic Square 的定义(行列数不相等、并非矩阵等)、矩阵中的某些数字并非正整数、数字之间并非使用\t 分割、等。若遇到这些情况,终止程序执行(isLegalMagicSquare 函数返回 false),并在控制台输出错误提示信息。
- 在 main()函数中调用五次 isLegalMagicSquare()函数,将 5 个文本文件名分别作为参数输入进去,看其是否得到正确的输出( true, false)。
- 函数规约:boolean isLegalMagicSquare(String fileName)
- Return a boolean result indicating whether the input is a magic square or not.
- Check that the columns and the diagonal also sum to the same constant.
- For each file: open the file, and check that all rows indeed sum to the same constant.
本题要求写一个函数判断txt文件中保存的矩阵是不是符合幻方要求的矩阵。输入参数为文件路径。返回布尔值,检验是否为符合条件的 Magic Square。
首先在于文件的读取,利用Bufferedreader,读入一行后进行分割。
每一行读取后每行按照 \t 进行分割。
随后尝试转化成数字。如果转化过程抛出异常,则可以认为数字不合法。
如果分割符问题,那么会造成数目不同,也比较好判断。因此分割完成后转换过程进行判断是否成功转换,转换失败可以认为数字非法,转换完成后以第一行作为标准,判断后面每行是否长度相等。之后比较列数等等如果没有问题,再判断横竖和对角线即可。
完整代码:
public static boolean isLegalMagicSquare(String fileName) throws Exception {
// open file
File file = new File("src/P1/txt/" + fileName);
FileReader fr = null;
fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
int firstLineCount = -1;
int totalLineCount = 0;
int thisLineCount = 0;
int[][] arr = new int[0][0];
// read file
while (true) {
// for the current line
String line = br.readLine();
if (line == null) {
break;
}
// split the line
String[] words = line.split("\t");
if (firstLineCount == -1) {
firstLineCount = words.length;
arr = new int[firstLineCount][firstLineCount];
}
// process lines with different numbers
thisLineCount = words.length;
if (thisLineCount != firstLineCount) {
System.out.print("line has different numbers");
return false;
}
// convert words to int, and check if they are integer
for (int i = 0; i < words.length; i++) {
int x;
try {
x = Integer.valueOf(words[i]);
} catch (NumberFormatException e) {
System.out.print("not a positive Int");
return false;
}
arr[totalLineCount][i] = x;
}
totalLineCount += 1;
}
int sum = 0;
int l2r = 0; // left to right
int r2l = 0; // right to left
// calc the sum of the diagonals, and the sum of the first line
for (int i = 0; i < firstLineCount; i++) {
sum += arr[0][i];
l2r += arr[i][i];
r2l += arr[firstLineCount - i - 1][i];
}
if (l2r != sum || r2l != sum) {
System.out.print("sum fail");
return false;
}
// calc the sum of the rows and cols
for (int i = 0; i < firstLineCount; i++) {
int col = 0;
int row = 0;
for (int j = 0; j < firstLineCount; j++) {
col += arr[i][j];
row += arr[j][i];
}
if (col != sum || row != sum) {
System.out.print("sum fail");
return false;
}
}
if (firstLineCount != totalLineCount) {
System.out.print("Not a matrix");
}
return true;
}
二. Turtle
java也有画图功能,与python的turtle相似。
请从https://github.com/rainywang/Spring2021_HITCS_SC_Lab1/tree/master/P2 获取代码。
下载的程序已经包括绘画相关的包,只需直接调用即可按自己意愿作图。
利用for循环逐层持续画出,利用整除关系获得层次和渐变色彩效果。代码如下:
结果如下:
三. Social Network
本作业来自于 CMU 17-214 软件构造课。
Implement and test a FriendshipGraph class that represents friendships in a social network and can compute the distance between two people in the graph. An auxiliary class Person is also required to be implemented.
You should model the social network as an undirected graph where each person is connected to zero or more people, but your underlying graph implementation should be directed. 注:本问题拟刻画的社交网络是无向图,但你的类设计要能够支持未来扩展到有向图。正因为此,如果要在两个 Person 对象 A 和 B 之间增加一条社交关系,那么需要同时调用 addEdge(A,B)和 addEdge(B,A)两条语句。
Your solution must work with the following client implementation.
|
Your solution should work with the client code above. The getDistance method should take two people (as Person) as arguments and return the shortest distance (an int) between the people, or -1 if the two people are not connected (or in other words, there are no any paths that could reach the second people from the first one).
Your graph implementation should be reasonably scalable. We will test your graph with several hundred or thousand vertices and edges.
Use proper access modifiers (public, private, etc.) for your fields and methods.
If a field/method can be private, it should be private.
Do not use static fields or methods except for the main method(s) and constant Follow the Java code conventions, especially for naming and commenting. Hint:
use Ctrl + Shift + F to auto-format your code!
Add short descriptive comments (/** ... */) to all public methods.
Additional hints/assumptions
For your implementation of getDistance, you may want to review breadth-first search.
You may use the standard Java libraries, including classes from java.util, but no third-party libraries.
You may assume that each person has a unique name.
You may handle incorrect inputs however you want (printing to standard out/error, silently failing, crashing, throwing a special exception, etc.)
You should write additional samples to test your graph, similar to our main method. To print something to standard out, use System.out.println. For example:
System.out.println("DON'T PANIC");
You should also write JUnit test code to test the methods addVertex(), addEdge(), and getDistance() of the class FriendshipGraph. All the test cases should be included in FriendshipGraphTest.java in the directory \test\P3. Test cases should be sufficient enough.
如果将上述代码的第 10 行注释掉(意即 rachel 和 ross 之间只存在单向的社交关系 ross->rachel),请人工判断第 14-17 行的代码应输出什么结果?让程序执行,看其实际输出结果是否与你的期望一致?
如果将第 3 行引号中的“Ross”替换为“Rachel”,你的程序会发生什么? 这其实违反了“ Each person has a unique name ”的约束条件。修改你的FriendshipGraph 类和 Person 类,使该约束能够始终被满足(意即:一旦该条件被违反,提示出错并结束程序运行)。
1、设计实现FriendshipGraph类
思路:在FriendshipGraph类中我们要完成的功能为:增加一个人的对象addVertex(若是增加的人为已存在的则输出“此名已存在,重复”并结束程序),增加一条有向边addEdge,得到两个人之间的最短距离getDistance。对此三个功能的实现,主要是功能三的实现相对复杂,我们决定采取广度优先搜索(BFS)的方式求最短路径。
过程:根据题目要求,有 addVertix, addEdge, getDistance 三个函数。对于存储数据,通过 HashMap 记录边, HashMap<Person, List<Preson>> 的方式存储某个人及其认识的人。而为了实现不重复,采用了 Set<String> 的方式,每次插入人员的时候。判断要插入的是否在这个集合内部。后面每次插入边的时候,首先判断两个人是否都已经记录了,如果都已经记录了,则再判断是否已经存在这条边。
对于获取距离,则是使用标准的 BFS 的方法,通过队列实现。
结果:
如果将上述代码的第10 行注释掉(意即rachel 和ross 之间只存在单向的
社交关系 ross->rachel):按预期正常输出
如果将第 3 行引号中的“Ross”替换为“Rachel”:抛出异常
2、设计实现Person类
对于一个人,其标识为姓名,通过构造函数的方式进行写入,单独提供了一个函数 getNanme() 进行读取。
public class Person {
private final String name;
public String getName(){
return this.name;
}
public Person(String name) {
this.name = name;
}
}
3、设计实现测试用例
思路:测试部分,参考 P2 测试的方式。
第一个测试点,判断测试是否可用
第二个测试点,testAll 是无向图(与 main() 实现相同)
第三个测试点,testAll2 为注释某条添加边的代码后的测试,即有向图
第四个测试点,插入两个名字相同的人,判断是否失败
第五个测试点,插入同一个人两次,判断是否失败
第六个测试点,插入一个未提含有未未AddVertix 的人的边,判断是否失败
第七个测试点,插入两次同一条边,判断是否失败