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

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

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

