简单的控制台绘图程序(Java)
在这项作业中,你将编写一个简单的控制台绘图程序,以实现一个流行图形应用程序(如Microsoft Paint)的一些简化功能。具体来说,给定一些参数(例如边长、对齐设置),该程序在绘图画布上绘制等腰直角三角形和正方形。该程序还具有一定的能力来实现一些简单的转换,如旋转和缩放,并执行简单的错误检查。这个作业的设计是这样的,我们可以评估你对以下主题的知识:1)基本类的设计和实现,2)控制流结构(例如,if-then-else,循环),和3)基本I/O(例如,扫描仪类,格式化打印)。
- 程序必须接受三个参数,它们将用于设置初始绘图画布。
例如,下面的命令用一个10x6绘图画布启动程序,背景字符是负号。
java consoleddrawing 10 6 -
注意,这是一个控制台绘图应用程序,所以我们使用一个字符作为测量单位,而不是使用一个像素。一个10x6绘图画布就像一个有6行10列的表格,其中每个单元格有足够的空间容纳一个可打印的字符。下面是一个10x6画布的例子,上面画了一个5x5的“正方形”。
- 程序将首先显示一条欢迎信息。然后,它将显示程序参数中给出的初始绘图画布设置。
3.然后,程序将显示主菜单和一个选项列表:1)绘制等腰直角三角形,2)绘制正方形,3)更新绘图画布,以及4)退出程序。
4.如果提供了一个无效的选项,假设用户输入“5”并按Enter,将显示一条错误消息,并再次列出主菜单。
5.如果选择了第一个选项(“绘制三角形”),输入“1”,然后按回车键,程序应该调用三角形类的相应方法来接受更多的用户输入,并相应地绘制三角形。具体地说,它应该首先询问等腰直角三角形的边长、打印字符(将在画布上的三角形中绘制)以及它的对齐方式。关于错误处理,您需要检查画布是否足够大,以容纳三角形。在对齐选项的情况下,如果选择了一个无效的选项,比如“a”或“b”,默认的选择应该是左对齐。然后,如果所有设置都有效,程序将在画布上绘制一个三角形。
如果选择了中间或右对齐,请参阅下面的程序输出。你可以看到这些三角形看起来是一样的,但是它们在画布上的位置是不同的。如果我们使用一个元组(行索引,列索引),其中索引从1开始,来指定图形在绘图画布上的左上角位置,对于所有对齐设置,行索引等于1。这意味着所有的形状都应该从第一行开始绘制。下面的公式展示了应该如何计算列索引。注意,同样的规则也适用于正方形。
6.然后,您的程序将询问用户是否想进行旋转,输入R(代表90度顺时针旋转)或L(代表90度逆时针旋转),然后按Enter键。注意,选择是不区分大小写的(即接受R/ R和L/ L)。
下图显示了左对齐三角形的初始位置,以及分别旋转90度、180度、270度和360度后的新位置。同样的变换规则适用于中间对齐和右对齐的三角形。注意,所有的转换都不应该改变当前的对齐设置,例如,如果一个三角形或一个正方形是左对齐的,旋转后的三角形或缩放后的正方形也必须是左对齐的。
7.当用户停止旋转三角形,通过输入除R和L之外的任何字符,然后按回车键,你的程序将询问他们是否想要绘制另一个三角形。
如果选择了Y,程序应该接受用户输入并绘制另一个三角形。如果选择了N,它应该返回到主菜单。否则,将显示一条错误消息。注意,选择也是不区分大小写的。
8.在主菜单中,如果选择第二个选项(绘制正方形),程序将遵循与选择第一个选项(绘制三角形)类似的工作流程,只是支持缩放(缩放),而不是旋转。注意,每当一个正方形被放大/缩小时,它的边长将增加/减少一个字符。一旦正方形达到其极限,即其边长等于min(画布宽度,画布高度)或1,用户就不能分别使其变大或变小。如果他们尝试这样做,什么也不会改变。
9.主菜单中的第三个选项用于更改当前画布设置。一旦设置被更改,你的程序将打印出一个确认消息和最新的设置。
10.要退出程序,用户可以在主菜单中选择第四个选项。程序会显示一条再见信息。
通过编译、运行和比较几个测试用例的输出与生成的预期输出,将对程序进行自动测试。如果输出与预期的输出不匹配,自动测试将认为输出是错误的,即使不同之处只是多了一个空格或缺少一个冒号。因此,至关重要的是,输出必须完全遵循上面示例中显示的格式。
另外,在整个程序中只使用一个Scanner对象。否则,自动测试可能会导致程序生成异常并终止。原因是在自动测试中,多行测试输入都被发送到程序中。当程序接收到输入时,它将把它们全部传递给当前活动的扫描器对象,而不让其他扫描器对象读取任何内容,从而导致运行时异常。因此,程序只有一个Scanner对象是很重要的。诸如“在执行手动测试时它运行正确,但在自动测试时失败”之类的参数将不会被接受。
代码思路:设计四个类Main主类,画布类,三角形类,正方形类,我们用画布类的方法去画正方形和三角形,主类调用画布类。
Square类:
package beans;
/**
* 正方形类
*
* @author 夕阳下的孤影
*
*/
public class Square {
private Integer length; // 正方形边长
private char Scharacter; // 正方形组成字符
public static final int LEFT = 1; // 对齐方式常量 左
public static final int MIDDLE = 2; // 对齐方式常量 中
public static final int RIGHT = 3; // 对齐方式常量 右
private int alignment; // 对齐方式变量
// 成员变量的get,set方法
public Integer getLength() {
return length;
}
public void setLength(Integer length) {
this.length = length;
}
public char getScharacter() {
return Scharacter;
}
public void setScharacter(char scharacter) {
Scharacter = scharacter;
}
public int getAlignment() {
return alignment;
}
public void setAlignment(int alignment) {
this.alignment = alignment;
}
}
Triangle类:
package beans;
/**
* 三角形类
* @author 夕阳下的孤影
*
*/
public class Triangle {
private int angle=0; //记录三角形当前的角度
private Integer Length; //等腰直角三角形的边长
private char character; //等腰三角形由什么字符构成
public static final int LEFT=1; //对齐方式常量 左
public static final int MIDDLE=2; //对齐方式常量 中
public static final int RIGHT=3; //对齐方式常量 右
public int alignment; //对齐方式变量
//变量的get,set方法
public Integer getLength() {
return Length;
}
public void setLength(Integer length) {
Length = length;
}
public char getCharacter() {
return character;
}
public void setCharacter(char character) {
this.character = character;
}
public int getAlignment() {
return alignment;
}
public void setAlignment(int alignment) {
this.alignment = alignment;
}
public int getAngle() {
return angle;
}
public void setAngle(int angle) {
this.angle = angle;
}
}
Canvas类:
package beans;
/**
* 画布类
* @author 夕阳下的孤影
*
*/
public class Canvas {
private static Integer Width; //画布的宽
private static Integer Height; //画布的高
private char BackgroundChar; //画布的背景符号
public static final int LEFT=1; //对齐方式常量 左
public static final int MIDDLE=2; //对齐方式常量 中
public static final int RIGHT=3; //对齐方式常量 右
/**
* 通过有参构造函数对画布进行一个初始化
* @param width 初始化宽度
* @param height 初始化高度
* @param bgchar 初始化背景符号
*/
public Canvas(int width,int height,char bgchar) {
this.Width=width;
this.Height=height;
this.BackgroundChar=bgchar;
}
//对三角形进行打印,打印角度为0时的三角形
public void printTriangle(Triangle triangle) {
int col_index=0; //不同的对齐方式,开始打印的初始点不同
if(triangle.getAlignment()==LEFT) {
col_index=1;
}else if(triangle.getAlignment()==MIDDLE) {
col_index=((this.getWidth()-triangle.getLength())/2+1);
}else if(triangle.getAlignment()==RIGHT) {
col_index=this.getWidth()-triangle.getLength()+1;
}
int side_length=triangle.getLength();
for(int i=1;i<=this.getHeight();i++) {
for(int j=1;j<=this.getWidth();j++) {
if(j>=col_index&&j<(col_index+side_length)) {
System.out.print(triangle.getCharacter());
}
else {
System.out.print(this.getBackgroundChar());
}
}
side_length-=1;
System.out.println();
}
}
//打印旋转角度为90的三角形
public void print90_Triangle(Triangle triangle) {
int col_index=0; //不同的对齐方式,开始打印的初始点不同
if(triangle.getAlignment()==LEFT) {
col_index=1;
}else if(triangle.getAlignment()==MIDDLE) {
col_index=((this.getWidth()-triangle.getLength())/2+1);
}else if(triangle.getAlignment()==RIGHT) {
col_index=this.getWidth()-triangle.getLength()+1;
}
int side_length=triangle.getLength();
int right=col_index+side_length;
for(int i=1;i<=this.getHeight();i++) {
for(int j=1;j<=this.getWidth();j++) {
if(j>=col_index&&j<right) {
System.out.print(triangle.getCharacter());
}
else {
System.out.print(this.getBackgroundChar());
}
}
col_index+=1;
System.out.println();
}
}
//打印旋转角度为180的三角形
public void print180_Triangle(Triangle triangle) {
int col_index=0; //不同的对齐方式,开始打印的初始点不同
if(triangle.getAlignment()==LEFT) {
col_index=1;
}else if(triangle.getAlignment()==MIDDLE) {
col_index=((this.getWidth()-triangle.getLength())/2+1);
}else if(triangle.getAlignment()==RIGHT) {
col_index=this.getWidth()-triangle.getLength()+1;
}
int side_length=triangle.getLength();
int right=col_index+side_length;
int index=right-1;
for(int i=1;i<=this.getHeight();i++) {
for(int j=1;j<=this.getWidth();j++) {
if(j>=index&&j<right&&(right-index)<=side_length) {
System.out.print(triangle.getCharacter());
}
else {
System.out.print(this.getBackgroundChar());
}
}
index--;
System.out.println();
}
}
//打印旋转角度为270的三角形
public void print270_Triangle(Triangle triangle) {
int col_index=0; //不同的对齐方式,开始打印的初始点不同
if(triangle.getAlignment()==LEFT) {
col_index=1;
}else if(triangle.getAlignment()==MIDDLE) {
col_index=((this.getWidth()-triangle.getLength())/2+1);
}else if(triangle.getAlignment()==RIGHT) {
col_index=this.getWidth()-triangle.getLength()+1;
}
int side_length=triangle.getLength();
int right=col_index+1;
for(int i=1;i<=this.getHeight();i++) {
for(int j=1;j<=this.getWidth();j++) {
if(j>=col_index&&j<right&&right<=(col_index+side_length)) {
System.out.print(triangle.getCharacter());
}
else {
System.out.print(this.getBackgroundChar());
}
}
right++;
System.out.println();
}
}
//
//对三角形进行顺时针旋转90度
public void rotateR(Triangle triangle) {
int angle=triangle.getAngle();
angle=(angle+90)%360;
triangle.setAngle(angle);
if(triangle.getAngle()==0) {
printTriangle(triangle);
}else if(triangle.getAngle()==90||triangle.getAngle()==-270) {
print90_Triangle(triangle);
}else if(triangle.getAngle()==180||triangle.getAngle()==-180) {
print180_Triangle(triangle);
}else if(triangle.getAngle()==270||triangle.getAngle()==-90) {
print270_Triangle(triangle);
}
}
//对三角形进行逆时针旋转90度
public void rotateL(Triangle triangle) {
int angle=triangle.getAngle();
angle=(angle-90)%360;
triangle.setAngle(angle);
if(triangle.getAngle()==0) {
printTriangle(triangle);
}else if(triangle.getAngle()==90||triangle.getAngle()==-270) {
print90_Triangle(triangle);
}else if(triangle.getAngle()==180||triangle.getAngle()==-180) {
print180_Triangle(triangle);
}else if(triangle.getAngle()==270||triangle.getAngle()==-90) {
print270_Triangle(triangle);
}
}
//对正方形进行打印
public void printSquare(Square square) {
int col_index=0; //不同的对齐方式,开始打印的初始点不同
if(square.getAlignment()==LEFT) {
col_index=1;
}else if(square.getAlignment()==MIDDLE) {
col_index=((this.getWidth()-square.getLength())/2+1);
}else if(square.getAlignment()==RIGHT) {
col_index=this.getWidth()-square.getLength()+1;
}
int side_length=square.getLength();
for(int i=1;i<=this.getHeight();i++) {
for(int j=1;j<=this.getWidth();j++) {
if(j>=col_index&&j<(col_index+side_length)&&i<=square.getLength()) {
System.out.print(square.getScharacter());
}
else {
System.out.print(this.getBackgroundChar());
}
}
System.out.println();
}
}
//对正方形进行缩小
public void narrow(Square square) {
int square_length=square.getLength();
if(square_length>1) { //如果正方形边长没到1,可以缩小
square_length--;
square.setLength(square_length);
}
}
//对正方形进行放大
public void enlarge(Square square) {
int square_length=square.getLength();
if(square_length<this.getHeight()&&square_length<this.getWidth()) { //如果正方形的长没有达到画布的高或宽,则可以放大加一,否则不做任何操作
square_length++;
square.setLength(square_length);
}
}
public char getBackgroundChar() {
return BackgroundChar;
}
public void setBackgroundChar(char backgroundChar) {
BackgroundChar = backgroundChar;
}
public Integer getWidth() {
return Width;
}
public void setWidth(Integer width) {
Width = width;
}
public Integer getHeight() {
return Height;
}
public void setHeight(Integer height) {
Height = height;
}
}
Main类:
package beans;
import java.util.Scanner;
/**
* 主程序类
* @author 夕阳下的孤影
*
*/
public class Main {
//对一些会用到的类对象进行一个定义
public static Canvas canvas=null;
public static Square square=null;
public static Triangle triangle=null;
static Scanner in=null;
//主方法入口
public static void main(String[] args) {
in=new Scanner(System.in);
initCanvas();//初始化画布
printInit();//打印欢迎信息,显示画布设置
displayMenu();//显示主菜单和一个选项列表
}
//1、初始化画布,启动程序
public static void initCanvas() {
System.out.print("java consoleddrawing ");
String s=in.nextLine();
String[] s1=s.split(" ");
int width=Integer.parseInt(s1[0]);
int height=Integer.parseInt(s1[1]);
char bgchar=s1[2].charAt(0);
canvas=new Canvas(width,height,bgchar); //初始化画布
}
//2、打印欢迎信息,显示初始画布设置,参数为画布实例
public static void printInit() {
System.out.println("----WELCOME TO MY CONSOLE DRAWING APP----");
System.out.println("Current drawing canvas settings:");
System.out.println("- Width: "+canvas.getWidth());
System.out.println("- Height: "+canvas.getHeight());
System.out.println("- Background character: "+canvas.getBackgroundChar());
System.out.println();
}
//3、显示主菜单和选项列表1)绘制等腰三角形2)绘制正方形3)更新绘图画布4)退出程序
public static void displayMenu() {
System.out.println("Please select an option. Type 4 to exit.");
System.out.println("1. Draw triangles");
System.out.println("2. Draw squares");
System.out.println("3. Update drawing canvas settings");
System.out.println("4. Exit");
String option=in.next();
verifyOption(option);//调用verify方法,对输入的选择进行判断
}
//4、如果是无效选择,将显示一条错误信息,并再次列出主菜单
public static void verifyOption(String option) {
//进行对option的判断,等于1则调用画布对三角形
if("1".equals(option)) {
initTriangle();//初始化三角形
canvas.printTriangle(triangle);//调用画布的方法画出三角形
rotateItOrNot();//旋转画布
iSprintAgain();//是否再画一个三角形
}else if("2".equals(option)) {
//等于2则调用画布对正方形进行操作
initSquare();//初始化正方形
canvas.printSquare(square); //调用画布的方法画出正方形
zoomItOrNot(); //缩放正方形
iSprintAgainSquare();//是否再画一个正方形
}else if("3".equals(option)) {
//等于3则调用画布方法对画布进行再次设置
updateCanvasSettings();
}else if("4".equals(option)) {
//等于4打印goodbye并退出
System.out.println("Goodbye!");
}else {
System.out.println("Unsupported option. Please try again!");
displayMenu(); //回调displayMenu()方法
}
}
//初始化三角形属性
public static void initTriangle() {
triangle=new Triangle();//创建三角形对象实例
System.out.println("Side length:");
int length=in.nextInt(); //接收三角形的长
while(length>canvas.getHeight()||length>canvas.getWidth()) {
System.out.println("Error! The side length is too long (Current canvas size is "+canvas.getHeight()+"x"+canvas.getWidth()+")");
// initTriangle();//再调用一次自身
System.out.println("Side length:");
length=in.nextInt();
}
triangle.setLength(length);
System.out.println("Printing character:"); //接收三角形的字符
char character=in.next().charAt(0);//确保输入的始终是一个字符
triangle.setCharacter(character);
System.out.println("Alignment(left,middle,right):");
String alignment=in.next(); //接收对齐方式
if("left".equals(alignment)) {
triangle.setAlignment(Triangle.LEFT);
}
else if("middle".equals(alignment)) {
triangle.setAlignment(Triangle.MIDDLE);
}
else if("right".equals(alignment)) {
triangle.setAlignment(Triangle.RIGHT);
}else {
triangle.setAlignment(Triangle.LEFT);
}
}
//是否进行旋转三角形
public static void rotateItOrNot() {
System.out.println("Type R/L to rotate clockwise/anti-clockwise.Use other keys to continue");
String ch=in.next().toLowerCase();//转成小写字母
while("r".equals(ch)||"l".equals(ch)) {
if("r".equals(ch)) {
canvas.rotateR(triangle);//调用画布方法顺时针旋转三角形
}
if("l".equals(ch)) {
canvas.rotateL(triangle);//调用画布方法逆时针旋转三角形
}
//旋转以后再次询问是否要旋转,如果输入字符不满足r,l,则跳出循环,方法结束
System.out.println("Type R/L to rotate clockwise/anti-clockwise.Use other keys to continue");
ch=in.next().toLowerCase();
}
}
//是否画另一个三角形
public static void iSprintAgain() {
System.out.println("Draw another triangle (Y/N)?");
String ch=in.next().toLowerCase();
while(!("y".equals(ch)||"n".equals(ch))) {
System.out.println("Unsupported option. Please try again!");
ch=in.next().toLowerCase();
}
if("y".equals(ch)) { //接收绘制另一个三角形
initTriangle();//初始化
canvas.printTriangle(triangle);//调用画布的方法画出三角形
rotateItOrNot();//旋转画布
iSprintAgain();
}
if("n".equals(ch)) { //拒绝,并返回主菜单
displayMenu();//返回主菜单
}
}
//初始化正方形
public static void initSquare() {
square=new Square();//创建正方形对象实例
System.out.println("Side length:");
int length=in.nextInt(); //接收正方形的长
while(length>canvas.getHeight()||length>canvas.getWidth()) {
System.out.println("Error! The side length is too long (Current canvas size is "+canvas.getHeight()+"x"+canvas.getWidth()+")");
System.out.println("Side length:");
length=in.nextInt();
}
square.setLength(length);
System.out.println("Printing character:"); //接收正方形的字符
char character=in.next().charAt(0);//确保输入的始终是一个字符
square.setScharacter(character);
System.out.println("Alignment(left,middle,right):");
String alignment=in.next(); //接收对齐方式
if("left".equals(alignment)) {
square.setAlignment(Square.LEFT);
}
else if("middle".equals(alignment)) {
square.setAlignment(Square.MIDDLE);
}
else if("right".equals(alignment)) {
square.setAlignment(Square.RIGHT);
}else {
square.setAlignment(Square.LEFT);
}
}
//是否缩放正方形
public static void zoomItOrNot() {
System.out.println("Type I/O to zoom in/out. Use other keys to continue.");
String ch=in.next().toLowerCase();//转成小写字母
while("i".equals(ch)||"o".equals(ch)) {
if("i".equals(ch)) {
canvas.enlarge(square);//放大一次
canvas.printSquare(square);//画出放大后的正方形
}
if("o".equals(ch)) {
canvas.narrow(square);//缩小一次
canvas.printSquare(square);//画出缩小后的正方形
}
//缩放以后再次询问是否要缩放,如果输入字符不满足I/O,则跳出循环,方法结束
System.out.println("Type I/O to zoom in/out. Use other keys to continue.");
ch=in.next().toLowerCase();
}
}
//是否画另一个正方形
public static void iSprintAgainSquare() {
System.out.println("Draw another square (Y/N)?");
String ch=in.next().toLowerCase();
while(!("y".equals(ch)||"n".equals(ch))) {
System.out.println("Unsupported option. Please try again!");
ch=in.next().toLowerCase();
}
if("y".equals(ch)) { //接收绘制另一个正方形
initSquare();
canvas.printSquare(square); //调用画布的方法画出正方形
zoomItOrNot();
iSprintAgainSquare();
}
if("n".equals(ch)) { //拒绝,并返回主菜单
displayMenu();//返回主菜单
}
}
//更新画布设置
public static void updateCanvasSettings() {
System.out.println("Canvas width: ");
int width=in.nextInt();
System.out.println("Canvas height: ");
int height=in.nextInt();
System.out.println("Background character: ");
char ch=in.next().charAt(0);
//对画布进行设置
canvas.setWidth(width);
canvas.setHeight(height);
canvas.setBackgroundChar(ch);
System.out.println("Drawing canvas has been updated!");
System.out.println();
System.out.println();
//显示当前画布设置
System.out.println("Current drawing canvas settings:");
System.out.println("- Width: "+canvas.getWidth());
System.out.println("- Height: "+canvas.getHeight());
System.out.println("- Background character: "+canvas.getBackgroundChar());
System.out.println();
System.out.println();
//设置成功后跳转到主菜单
displayMenu();//显示主菜单和一个选项列表
}
}
ystem.out.println("Background character: ");
char ch=in.next().charAt(0);
//对画布进行设置
canvas.setWidth(width);
canvas.setHeight(height);
canvas.setBackgroundChar(ch);
System.out.println("Drawing canvas has been updated!");
System.out.println();
System.out.println();
//显示当前画布设置
System.out.println("Current drawing canvas settings:");
System.out.println("- Width: "+canvas.getWidth());
System.out.println("- Height: "+canvas.getHeight());
System.out.println("- Background character: "+canvas.getBackgroundChar());
System.out.println();
System.out.println();
//设置成功后跳转到主菜单
displayMenu();//显示主菜单和一个选项列表
}
}