Java實現(xiàn)的按照順時針或逆時針方向輸出一個數(shù)字矩陣功能示例
本文實例講述了Java實現(xiàn)的按照順時針或逆時針方向輸出一個數(shù)字矩陣功能。分享給大家供大家參考,具體如下:
題目:按照指定的長寬和輸出方向,從外向內打印一個從 1 開始的數(shù)字矩陣,矩陣的開始位置在左上角。如下圖

代碼及注釋如下:
public class NumberMatrix {
public static void main(String[] args) {
int width = 25;
int height = 12;
boolean clockwise = false;
System.out.println("腳本之家測試結果:");
outputMatrix(width, height, clockwise);
}
/**
* 按照指定的長寬和輸出方向,從外向內打印一個從 1 開始的數(shù)字矩陣,矩陣的開始位置在左上角。
*
* @param width 矩陣寬度
* @param height 矩陣高度
* @param clockwise 是否是順時針方向
*/
private static void outputMatrix(int width, int height, boolean clockwise) {
// 首先判斷最大數(shù)字的位數(shù),以決定輸出如何對齊
int numLength = (int) Math.log10(width * height) + 1;
// 決定輸出的格式(最大位數(shù) + 1個空格)
String format = "%" + (numLength + 1) + "d";
// 定義要輸出的二維數(shù)組,注意維度是從高到低的
// 此時 matrix 中所有元素的值都是 0
int[][] matrix = new int[height][width];
// 定義一個位置指針和一個計數(shù)器,位置指針進行移動,而計數(shù)器負責遞增,遞增后的數(shù)字
// 被填充進矩陣,當 width * height 個數(shù)字填充完畢,這個矩陣就完成了。
// 注意這里位置指針的第一個元素對應 matrix 的第一個維度 y,第二個元素對應第二個維度 x。
int[] pointer = {0, 0};
int counter = 1;
// 定義當前移動的方向:1、2、3、4 分別表示上、右、下、左。
// 順時針的起始方向為右,逆時針的起始方向為下。
int direction = clockwise ? 2 : 3;
// 開始循環(huán)填充,每個填充分為三步
for (int i = 1, max = width * height; i <= max; i++) {
// 1. 填充內容
int y = pointer[0];
int x = pointer[1];
matrix[y][x] = counter;
// 2. 計數(shù)器自增
counter += 1;
// 3. 移動到下一個位置,因為這地方比較復雜,所以開個方法實現(xiàn)
direction = move(matrix, width, height, pointer, direction, clockwise);
}
// 矩陣填充完畢,按照正常的方式循環(huán)輸出即可
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
System.out.printf(format, matrix[y][x]);
}
System.out.println(); // 完成一行后輸出換行
}
}
/**
* 在矩陣中移動
*
* @param matrix 矩陣,用于判斷前進方向的下一個位置是否已經(jīng)填充了數(shù)字,如果是則轉向
* @param width 矩陣的寬
* @param height 矩陣的高
* @param pointer 指針的當前位置。調用本方法后里面的值會改變,除非方法返回 0
* @param direction 指針當前移動的方向
* @param clockwise 是否是要按順時針方向轉向
*
* @return 移動后的新方向(與原來的方向可能相同也可能不同)。如果無法再繼續(xù)移動,則返回 0
*/
private static int move(int[][] matrix, int width, int height, int[] pointer, int direction, boolean clockwise) {
// 先嘗試按照原來的方向移動到 newPointer
int[] newPointer = moveDirectly(pointer, direction);
// 檢查 newPointer 是否合法,如果合法則將其賦值給 pointer 并保持原來的方向,方法完成
if (isValid(newPointer, matrix, width, height)) {
System.arraycopy(newPointer, 0, pointer, 0, 2);
return direction;
}
// 進行轉向,重新從 pointer 朝新的方向移動
direction = turn(direction, clockwise);
newPointer = moveDirectly(pointer, direction);
// 檢查 newPointer 是否合法(同前面一樣)
if (isValid(newPointer, matrix, width, height)) {
System.arraycopy(newPointer, 0, pointer, 0, 2);
return direction;
}
// 既無法前進也無法轉向,那么無法繼續(xù)移動。
return 0;
}
// 判斷矩陣中指定的位置是否可以填充
private static boolean isValid(int[] newPointer, int[][] matrix, int width, int height) {
// 位置不能超出矩陣范圍
if (newPointer[0] >= height
|| newPointer[0] < 0
|| newPointer[1] >= width
|| newPointer[1] < 0) {
return false;
}
// 位置的內容應該為空
if (matrix[newPointer[0]][newPointer[1]] != 0) {
return false;
}
return true;
}
// 轉向。根據(jù)我們對 direction 的定義,順時針就是 +1,逆時針就是 -1
private static int turn(int direction, boolean clockwise) {
int newDirection = clockwise ? direction + 1 : direction - 1;
if (newDirection > 4) {
newDirection = 1;
} else if (newDirection < 1) {
newDirection = 4;
}
return newDirection;
}
/**
* 朝指定的方向移動,并返回新的位置
*
* @param pointer 當前位置
* @param direction 方向
*
* @return 新的位置
*/
private static int[] moveDirectly(int[] pointer, int direction) {
int y = pointer[0];
int x = pointer[1];
switch (direction) {
case 1:
return new int[]{y - 1, x};
case 2:
return new int[]{y, x + 1};
case 3:
return new int[]{y + 1, x};
case 4:
return new int[]{y, x - 1};
}
throw new IllegalArgumentException("方向不正確: " + direction);
}
}
運行結果:

更多關于java算法相關內容感興趣的讀者可查看本站專題:《Java數(shù)據(jù)結構與算法教程》、《Java操作DOM節(jié)點技巧總結》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設計有所幫助。
相關文章
Kafka中的producer攔截器與consumer攔截器詳解
這篇文章主要介紹了Kafka中的producer攔截器與consumer攔截器詳解,Producer 的Interceptor使得用戶在消息發(fā)送前以及Producer回調邏輯前有機會對消息做 一些定制化需求,比如修改消息等,需要的朋友可以參考下2023-12-12
教你開發(fā)腳手架集成Spring?Boot?Actuator監(jiān)控的詳細過程
這篇文章主要介紹了開發(fā)腳手架集成Spring?Boot?Actuator監(jiān)控的詳細過程,集成包括引入依賴配置文件及訪問驗證的相關知識,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05
java調用openoffice將office系列文檔轉換為PDF的示例方法
本篇文章主要介紹了java使用openoffice將office系列文檔轉換為PDF的示例方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-11-11
SpringBoot注解篇之@Resource與@Autowired的使用區(qū)別
@Resource 注解和 @Autowired 注解都是在 Spring Framework 中進行依賴注入的注解,那么你知道他們有什么區(qū)別嗎,本文就來介紹一下2023-12-12
Java如何接收前端easyui?datagrid傳遞的數(shù)組參數(shù)
這篇文章分享一下怎么在easyui的datagrid刷新表格時,在后端java代碼中接收datagrid傳遞的數(shù)組參數(shù),本文通過實例代碼給大家介紹的非常詳細,需要的朋友參考下吧2023-11-11
SpringBoot使用MyBatis實現(xiàn)數(shù)據(jù)的CRUD
MyBatis是一個輕量級的對象關系映射(Object-Relational Mapping,ORM)框架,它允許開發(fā)者通過編寫SQL動態(tài)查詢數(shù)據(jù)庫,而無需顯式地操作JDBC,對于增刪改查操作,MyBatis提供了一種基于XML或注解的方式來進行,本文介紹了SpringBoot使用MyBatis實現(xiàn)數(shù)據(jù)的CRUD2024-11-11

