黑马程序员——螺旋方阵的打印

本文介绍了一个Java程序,该程序能够创建一个指定大小的方阵,并采用螺旋的方式填充从1开始的自然数。通过四个不同方向的状态标识实现数组的正确填充,并详细解释了实现原理。

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

import java.util.Scanner;

/*
 * 写一方法,打印等长的二维数组,要求从1开始的自然数由方阵的
 * 最外圈向内螺旋方式地顺序排列。 如: n = 4 则打印:
 * 	1	2	3	4
 12	13	14	5
 11	16	15	6
 10	9	8	7
 分析:
 用数组下标来表示上面的输出:
 [0][0] [0][1] [0][2] [0][3]
 [1][0] [1][1] [1][2] [1][3]
 [2][0] [2][1] [2][2] [2][3]
 [3][0] [3][1] [3][2] [3][3]
 从1开始给二维数组的赋值顺序是:
 从左向右:行下标不变,列下标递增
 从上向下:列下标不变,行下标递增
 从右向左:行下标不变,列下标递减
 从下向上:列下标不变,行下标递减
 由此可见:给数组赋值分为4个不同的状态,我们可以给每个状态定个标志来判断
 赋值的方向,当前状态赋值完毕后自动更改状态值进入下一状态。
 那么,怎么判断当前状态赋值完毕呢?
 可以发现该数组正好是一个方阵,一轮赋值完成以后正好是一个正方形。正方形的4个角可以当做4个拐点
 第一轮赋值		第二轮赋值
 拐点0:	00			11
 拐点1:	03			12
 拐点2:	33			22
 拐点3:	30			21
 发现拐点与数组长度和赋值轮数有关
 当第一轮赋值时拐点1为:数组长度-1-0
 当第二轮赋值时拐点1为:数组长度-1-1
 所以可以把第一轮赋值定义为第0轮,以此类推。。。
 直到了赋值规律,我们怎么用循环完成赋值呢:可以使用continue控制循环
 因为是从1开始赋值,所以最大值正好等于数组的长度:一直赋值,直到等于数组的长度,
 每完成一次赋值使用continue跳出本次循环,继续下次判断赋值
 */
public class Test7 {

	public static void main(String[] args) {
		// 键盘录入n值
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入你要打印的二维数组arr[n][n]方阵n的值:");
		int n = sc.nextInt();
		// 写一个方法创建数组并赋值
		int[][] arr = makeArr(n);
		//遍历数组
		for(int[] ar:arr){
			for(int i :ar){
				System.out.print(i+"\t");
			}
			System.out.println();
		}
	}

	private static int[][] makeArr(int n) {
		// 创建数组
		int[][] arr = new int[n][n];
		// 赋值
		// 首先定义几个变量
		int flag = 0; // 定义状态标识
		int t = 0; // 定义数组行下标
		int r = 0; // 定义数组列下标
		int c = 0;// 定义第几轮赋值
		int s = n * n;// 定义赋值的最大值
		int len = n;// 定义数组长度

		// 一直赋值直到最大值
		for (int x = 1; x <= s; x++) {

			// 当flag=0时,从左向右赋值,t不变,r++
			if (flag == 0) {
				// 如果r=len-1-c则另flag=1
				if (r == len - 1 - c) {
					flag = 1;
				} else {
					arr[t][r] = x;
					r++;
					// 每完成一次赋值使用continue跳出循环,使x++
					continue;
				}
			}

			// 如果以n=4来说,此时arr[0][3]还没有赋值,即从上向下的第一个元素还没有值
			// 当flag=1时,从上向下赋值,r不变,t++
			if (flag == 1) {
				// 如果t=len-1-c则令flag=2
				if (t == len - 1 - c) {
					flag = 2;
				} else {
					arr[t][r] = x;
					t++;
					continue;
				}
			}

			// 当flag=2时,从右向左赋值,t不变r--
			if (flag == 2) {
				// 如果r=c则令flag=3
				if (r == c) {
					flag = 3;
				} else {
					arr[t][r] = x;
					r--;
					continue;
				}
			}

			// 当flag=3时,从下向上赋值,r不变,t--
			if (flag == 3) {
				// 如果t=c+1时,说明一轮赋值完成,这时需要重置标识值,并c++,且列数也要自加
				if (t == c + 1) {
					// 由于此处的元素还没有赋值,先赋值
					arr[t][r] = x;
					flag = 0;// 重置标识值
					c++;// 轮数加1
					r++;// 列数加1
					continue;
				} else {
					arr[t][r] = x;
					t--;
					continue;
				}
			}
		}
		//至此,赋值完毕
		return arr;
	}
}


### TCP传输原理与实现 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层协议。其核心原理是通过建立端到端的连接,确保数据在可靠的网络中能够可靠地传输。TCP 使用确认机制、流量控制、拥塞控制等机制来保障数据的完整性和有序性。 在 Java 中,TCP 通信可以通过 `Socket` 和 `ServerSocket` 类实现。客户端使用 `Socket` 连接到服务器,服务器端使用 `ServerSocket` 监听连接请求。通信过程中,数据通过输入流和输出流进行传输。 #### 客户端实现 客户端的主要任务是与服务器建立连接,并通过输出流向服务器发送数据,同时可以通过输入流接收服务器的响应。例如: ```java Socket s = new Socket(InetAddress.getLocalHost(), 10004); OutputStream out = s.getOutputStream(); out.write("Hello TCPClient".getBytes()); InputStream is = s.getInputStream(); byte[] buffer = new byte[1024]; int len = is.read(buffer); System.out.println(new String(buffer, 0, len)); s.close(); ``` 该代码实现了客户端与服务器的连接,并发送了一条文本消息,同时接收服务器的响应[^1]。 #### 服务端实现 服务端通过 `ServerSocket` 监听指定端口,等待客户端连接。一旦连接建立,服务端通过输入流接收客户端发送的数据,并通过输出流向客户端发送响应。例如: ```java ServerSocket ss = new ServerSocket(10012); Socket s = ss.accept(); InputStream in = s.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println(new String(buffer, 0, len)); PrintWriter out = new PrintWriter(s.getOutputStream(), true); out.println("<font color='red' size=7>客户端s你好</font>"); s.close(); ss.close(); ``` 该代码展示了如何在服务端接收客户端发送的数据,并向客户端发送 HTML 格式的响应[^3]。 #### TCP连接的建立与释放 TCP 连接的建立采用三次握手(Three-way Handshake): 1. 客户端发送 SYN(同步)报文给服务器,表示请求建立连接。 2. 服务器收到 SYN 报文后,发送 SYN-ACK(同步-确认)报文作为响应。 3. 客户端收到 SYN-ACK 后,发送 ACK(确认)报文,连接建立。 连接的释放采用四次挥手(Four-way Handshake): 1. 客户端发送 FIN(结束)报文,表示数据发送完成。 2. 服务器发送 ACK 报文,确认收到 FIN。 3. 服务器发送 FIN 报文,表示数据发送完成。 4. 客户端发送 ACK 报文,连接关闭。 #### TCP的可靠性机制 TCP 通过以下机制确保数据的可靠传输: - **确认机制**:接收方收到数据后,向发送方发送确认信息。 - **重传机制**:如果发送方未收到确认信息,则重传数据。 - **流量控制**:通过滑动窗口机制,控制发送速率,避免接收方缓冲区溢出。 - **拥塞控制**:通过慢启动、拥塞避免等算法,防止网络拥塞。 #### TCP的编程模型 TCP 编程模型通常包括以下几个步骤: 1. **创建 Socket**:客户端创建 `Socket` 对象,连接服务器;服务端创建 `ServerSocket` 对象,监听端口。 2. **获取流对象**:获取 `Socket` 的输入流和输出流,用于数据传输。 3. **数据读写**:通过输入流读取数据,通过输出流写入数据。 4. **关闭连接**:通信结束后,关闭 `Socket` 和流对象。 ### 示例代码:完整的 TCP 通信 以下是一个完整的 TCP 通信示例,包含客户端和服务端的代码。 #### 客户端代码 ```java import java.io.*; import java.net.*; public class TcpClient { public static void main(String[] args) { try { Socket socket = new Socket("localhost", 8888); OutputStream out = socket.getOutputStream(); out.write("Hello Server!".getBytes()); InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println("Server response: " + new String(buffer, 0, len)); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` #### 服务端代码 ```java import java.io.*; import java.net.*; public class TcpServer { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Server is listening on port 8888..."); Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println("Client message: " + new String(buffer, 0, len)); OutputStream out = socket.getOutputStream(); out.write("Hello Client!".getBytes()); socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一夸克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值