黑马程序员技术交流社区
标题:
螺旋方阵打印方法分享(感觉代码有点多)
[打印本页]
作者:
郑飞
时间:
2014-9-5 03:04
标题:
螺旋方阵打印方法分享(感觉代码有点多)
本帖最后由 郑飞 于 2014-9-5 04:05 编辑
分享入学测试题 , 不知道代码还能不能再优化,或者有没其他简单方法 :
/*
1、 写一方法,打印等长的二维数组,要求从1开始的自然数由方阵的最外圈向内螺旋方式地顺序排列。 如: n = 4 则打印:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
思路和步骤:
1:利用二维数组 列为里面的一维数组
2:给元素赋值 依题意可知方阵开始走动,必然有一边是被堵住 而且纵横交替因此 定义两个方法 一个横向一个纵向
横向:左右都走一遍 而后转入纵向 如此循环 利用最大元素值n的平方来控制跳出循环
3:跳出循环时必然赋值完毕,打印二维数组.
*/
class Exam1
{
private static String insert = "";
public static void main(String[] args)
{
test(4);
}
//横向赋值的时候 必然有一边是被堵的
public static void setX(int[][] arr,int x,int y,int count)
{
if(arr[x][y]==arr.length*arr.length)//如果走到头了就退出
return;
if((x+1)<arr.length)//向右边走
{
while(arr[x+1][y]==0)
{
arr[x+1][y] = count++;
x++;
if((x+1)>=arr.length)
break;
}
}
if((x-1)>=0)//向左走
{
while(arr[x-1][y]==0)
{
arr[x-1][y] = count++;
x--;
if((x-1)<0)
break;
}
}
setY(arr,x,y,count);//调用纵向方法
}
public static void setY(int[][] arr,int x,int y,int count)
{
if((y+1)<arr[x].length)//直接向下走
{
while(arr[x][y+1]==0)
{
arr[x][y+1] = count++;
y++;
if((y+1)>=arr[x].length)
break;
}
}
if((y-1)>=0)//向上走
{
while(arr[x][y-1]==0)
{
arr[x][y-1] = count++;
y--;
if((y-1)<0)
break;
}
}
setX(arr,x,y,count);//调用横向方法
}
public static void test(int n)
{
int[][] arr = new int[n][n];//初始化二维数组
arr[0][0] = 1;//给第一个元素赋值(因为set方法中是从第二个元素开始赋值)
setX(arr,0,0,2);//从x=0,y=0位置开始,第二个元素开始赋值,所以count传入2.
printArr(arr);//打印数组
}
public static void printArr(int[][] arr)
{
for (int x=0;x<arr[0].length ;x++ )//遍历打印二维数组
{
for (int y=0;y<arr.length ;y++ )
{
System.out.print(blank(arr,arr[y][x])+arr[y][x]+" ");//打印插入空格后的元素
insert = "";
}
System.out.println("");//打印所有第二维某一行后,换行.
}
}
public static String blank(int[][] arr,int value)//传入当前数组和当前元素值,返回该插入的空格.
{
int len = (arr.length*arr.length+"").length();//得到该数组最大值该有的长度
len = len - (value+"").length();//得到该插入的空格数
while (len>=0)//添加空格
{
insert = insert+" ";
len--;
}
return insert;
}
}
复制代码
作者:
huanglyhf
时间:
2014-9-5 08:45
import java.util.Scanner;
public class Test9 {
public static void main(String[] args) {
System.out.println("请输入一个数,来作为您的二位数组维度:");//从键盘接收一个数,动态确定数组大小
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
printArray(num);
}
public static void printArray(int num){
int[][] arr = new int[num][num];//根据输入的值,初始化一个num阶的数组,数组里的元素都初始化为0
for(int i=0;i<num;i++){
for(int j=0;j<num;j++)
arr[i][j] = 0;
}
int cycles = num/2+num%2;//循环的总圈数
int count = 1;//圈数计数器
int step = 1;//初始化数字
while(count<=cycles){
int min = count-1;//最小坐标
int max = num-count;//最大坐标
if(min==max){
arr[cycles-1][cycles-1]=step;//数组阶数是奇数时,最后一圈不是圈,只有一个点。这里直接对这个点赋值。
}
else{
//第一条边
for(int a=min;a<=max;a++){
arr[min][a]=step++;
}
//第二条边
for(int b=min+1;b<=max;b++){
arr[b][max]=step++;
}
//第三条边
for(int c=max-1;c>=min;c--){
arr[max][c]=step++;
}
//第四条边
for(int d=max-1;d>=min+1;d--){
arr[d][min]=step++;
}
}
count++;
}
//输出数组
for(int m=0;m<num;m++){
for(int n=0;n<num;n++){
System.out.print(arr[m][n]+"\t");
}
System.out.println("");
}
}
}
复制代码
作者:
huanglyhf
时间:
2014-9-5 08:53
加空格的程序用制表符就可以搞定了!
作者:
郑飞
时间:
2014-9-5 09:06
huanglyhf 发表于 2014-9-5 08:53
加空格的程序用制表符就可以搞定了!
嗯 谢谢 之前也想过每条边的做 感觉有点难 就放弃了 现在正好看看
作者:
左脑想你
时间:
2014-9-5 10:17
public class Test9 {
public static void main(String[] args) {
// 根据n创建一个二维数组
int n = 8;
int[][] arr = new int[n][n];
// 调用数组赋值的方法
method(arr);
// 将数组遍历出来
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
System.out.print(arr[i][j] + "\t");
}
System.out.println("\n");
}
}
// 二维数组赋值方法
public static void method(int[][] arr) {
// 创建数组的两个索引变量
int i = 0;
int j = 0;
// 通过 max 和min控制索引i,j的变化
int max = arr.length - 1;
int min = 0;
// 所需要赋的值
int num = 1;
while (min <= max) {
// 1、i不变j++ 向右
while (j < max) {
arr[i][j++] = num++;
}
// 2、j不变i++ 向下
while (i < max) {
arr[i++][j] = num++;
}
// 3、i不变j-- 向左
while (j > min) {
arr[i][j--] = num++;
}
// 4、j不变i-- 向上
while (i > min) {
arr[i--][j] = num++;
}
// 由于可能在n为奇数的时候无法为中心那个数赋值所以要补上这个数的赋值
if (min == max) {
arr[i][j] = num;
}
max--;
min++;
// 循环一圈又开始想有赋值j++
j++;
// 由于向上的时候最后一次赋值i多减了一次所以每次外循环都要将i补回来
i++;
}
}
}
复制代码
作者:
fantacyleo
时间:
2014-9-5 11:04
直接从1循环到N^2,i,j代表二维数组下标,初始值为0,二维数组也全部初始化为0。每次输出一个值:如果i=0或a[i-1][j]>0,则往右走;如果j=N-1或a[i][j+1]>0,则往下走;如果i=N-1或a[i+1][j]>0,则往左走;如果j=0或a[i][j-1]>0,则往上走。这样代码看起来会清楚很多
作者:
毛富强
时间:
2014-9-5 12:32
学习了。。。。。
作者:
郑飞
时间:
2014-9-5 14:27
左脑想你 发表于 2014-9-5 10:17
谢谢 分享 思路和代码都很简练 用while看起来很清爽啊 哈哈 :handshake
作者:
我只适合被遗忘
时间:
2015-3-11 18:10
好难啊,还没学到数组怎么破
作者:
wk843620202
时间:
2015-4-28 00:59
不错啊!
作者:
忘言
时间:
2015-5-9 15:46
我也发个我写的~
package pack;
public class LuoXuan {
/**
* @param args
*/
public static void main(String[] args) {
func(5);
}
public static void func(int n)
{
int i=0,j=0,value=0;
int arr[][]=new int[n][n];
if(n%2==0)
arr[n/2][n/2-1]=n*n;
else
arr[n/2][n/2]=n*n;
for(j=0;j<n-1;j++)
arr[0][j]=++value;
while(n>1)
{
for(int x=0;x<n-1;x++)
arr[i++][j]=++value;
for(int x=0;x<n-1;x++)
arr[i][j--]=++value;
n--;
for(int x=0;x<n-1;x++)
arr[i--][j]=++value;
for(int x=0;x<n-1;x++)
arr[i][j++]=++value;
n--;
}
for(int ii=0;ii<arr.length;ii++)
{
for(int jj=0;jj<arr[i].length;jj++)
{
System.out.print(arr[ii][jj]+"\t");
}
System.out.println();
}
}
}
作者:
文森
时间:
2015-5-10 20:43
方法好多
作者:
zl074081027_hm
时间:
2015-5-12 16:02
package com.itheima;
/**
*第9题:写一方法,打印等长的二维数组,要求从1开始的自然数由方阵的最外圈向内螺旋方式地顺序排列。
* 如: n = 4 则打印:
* 1 2 3 4
* 12 13 14 5
* 11 16 15 6
* 10 9 8 7
* @author zl
*思路:给二维数组赋值的方法,一圈一圈地从外到内赋值,一圈即一个循环。
*详细:设为n维、h圈
*一,nxn维数组有h((n+1)/2)圈,循环从外到内圈依次赋值;
*二,每圈由上、下行和左、右列共四个臂组成,按照上、右、下、左臂的先后顺序依次循环赋值;
*三,每个臂有元素n-h-(h-1)个,每臂以一个四角元素为起始元素依次赋值;
*四,四角元素索引分别为[h-1][h-1]、[h-1][n-h]、[n-h][n-h]、[n-h][h-1]。
*
*以n=4为例进行具体说明,此时h=2
*一共2圈;
*第1圈每臂有元素3个;第2圈每臂有元素2个;
*第1圈四角元素(每臂起始)分别为[0][0]、[0[3]、[3][3]、[3][0];
*第1圈赋值顺序依次为:
*上臂元素为[0][0]、[0[1]、[0][2];右臂元素为[0][3]、[1[3]、[2][3];
*下臂元素为[3][3]、[3[2]、[3][1];左臂元素为[3][0]、[2[0]、[1][0];
*第2圈赋值顺序依次为
*上臂元素为[1][1];右臂元素为[1][2];
*下臂元素为[2][2];左臂元素为[2][1];
*
*注意一个特例:即最后一圈为一个元素时,需要做点例外处理。
*/
public class Test09_2DArray {
public static void main(String[] args) {
// 定义螺旋形二维数组并打印
int[][] arr = helixArray(6);
printArr(arr);
}
//定义静态方法,返回n行n列的螺旋形二维数组;
static int[][] helixArray(int n) {
//定义二维数组、圈数和第一个元素的值
int[][] helArr = new int[n][n];
int helLen = (n+1)/2 ;
helArr[0][0] = 1;
//初始化; 从外圈到内圈依次赋值
for(int h=1; h<=helLen; h++) {
// 给第h圈的上臂[h-1]行的元素赋值;从第一列[h-1]到倒数最后一列[n-h-1];第一圈与其他圈稍有不同,分开处理;
//考虑到最后一圈的元素可能只有一个,即每行或列的第一个元素与最后一个元素重合,因此有必要遍历到上行的最后一个元素[n-h];
//如果不遍历到最后一个元素,则n为奇数即最后一圈为一个元素时,最后一个元素将得不到赋值。
for(int j=h-1; j<=n-h; j++) {
if(h==1) {
// 公式中helArr[h-1][h-1]是第1圈上臂行左边第一个元素,第一圈其余元素值根据第一个元素值依次获得
helArr[h-1][j] = helArr[h-1][h-1] + j - (h - 1);
} else {
// helArr[h-1][h-2]是第h-1圈左臂列上面第一个元素,即非第一圈元素值根据第一圈最后一个元素值获得
helArr[h-1][j] = helArr[h-1][h-2] + 1 + j - (h-1) ;
}
}
//给第h圈的右臂[n-h]列元素赋值;从第一行[h-1]到倒数最后一行[n-h-1]
for(int i=h-1; i<=n-h-1; i++) {
// helArr[h-1][n-h-1]是第h圈上臂最后一个元素
helArr[i][n-h] = helArr[h-1][n-h-1]+1 + i - (h - 1);
}
//给第h圈的下臂[n-h]行元素赋值;从右边第一列[n-h]向左到倒数第二列[h]
for(int j=n-h; j>=h; j--) {
// helArr[n-h-1][n-h]是第h圈右右臂的最后一个元素
helArr[n-h][j] = helArr[n-h-1][n-h]+ 1 + n-h- j;
}
//给第h圈的左侧列[h-1]元素赋值,从左侧列倒数第一行[n-h]向上到第二行[h]
for(int i=n-h; i>=h; i--) {
// helArr[n-h][h]是第h圈下臂最后一个元素
helArr[i][h-1] = helArr[n-h][h] + 1 + n - h - i;
}
}
return helArr;
}
//定义静态方法,打印二维数组; 添加制表符,对齐数组
static void printArr(int[][] arr) {
for(int i=0; i<arr.length; i++) {
for(int j=0; j<arr[i].length; j++) {
System.out.print(arr[i][j]+"\t");
}
//一行打印完,执行转行
System.out.println();
}
}
}
复制代码
作者:
guyulei
时间:
2016-3-29 20:36
左脑想你 发表于 2014-9-5 10:17
和你思想 一样
作者:
freshnboy
时间:
2016-3-31 16:06
左脑想你 发表于 2014-9-5 10:17
这个代码是最简单的,顶了。
作者:
freshnboy
时间:
2016-3-31 16:11
本帖最后由 freshnboy 于 2016-3-31 16:13 编辑
我也写了一个,不过思路麻烦了一些。把二维数组看做地图上的点,然后把这个当做路径问题。
每一个地图点都有三个属性:坐标(x,y)、通行性(true/false)、位移矢量(dx,dy)。
规则是从(0,0)出发之后,一直直行(下一点坐标=本坐标+位移矢量),遇到无法通行的情况就向右拐(下一点坐标=本坐标+右转位移矢量)。
然后遍历到计数器=n*n为止。没有什么需要特殊处理的点。
这种方法缺点是代码量明显增加,看起来也不容易一眼看清。
优点是可以处理任意规则的转法,你喜欢S形也能给你走出来
作者:
热火程序猿
时间:
2016-6-29 08:52
左脑想你 发表于 2014-9-5 10:17
这个是我认为最好理解又最方便的方法 怒赞
作者:
lx610
时间:
2016-7-8 10:00
左脑想你 发表于 2014-9-5 10:17
数组的方法厉害。
作者:
袁志娜
时间:
2016-9-2 23:08
66666,好赞
作者:
yuzt
时间:
2016-10-4 16:26
还没想明白,仔细研究下
作者:
缥缈hugh
时间:
2017-8-30 11:25
嗯125875698
作者:
缥缈hugh
时间:
2017-8-30 11:26
是的没错很好还好需要
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2