# OOP midtern ## shape3D ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using _106_Classwork8; namespace _106_Quiz7 { public static class ShapeType //靜態類別, 不能被實體化 (new) { public enum Geo //使用 enum 增加程式的可讀性 { UNKNOWN = -1, BALL = 0, CUBE, CYLINDER, PYRAMID }; public enum Material //使用 enum 增加程式的可讀性 { UNKNOWN = -1, Al = 0, Fe, Pb }; } abstract class Shape3D //抽象類別, 不能被實體化 (new) { protected static int _amount; //被繼承的欄位 (資料成員)需宣告為 protected //protected double _density; //被繼承的欄位 (資料成員)需宣告為 protected, _material 與 _density 有相關性 故取消 protected ShapeType.Geo _geoType; protected ShapeType.Material _materialType; //_material 與 _density 有相關性 public Shape3D() { _materialType = ShapeType.Material.UNKNOWN; _amount++; } public Shape3D(ShapeType.Material mType) { _materialType = mType; _amount++; } public static int Amount //要給其他類別取用, 故宣告為 public { get { return _amount; } } public ShapeType.Material MaterialType //要給其他類別取用, 故宣告為 public { get { return _materialType; } } public ShapeType.Geo GeoType //要給其他類別取用, 故宣告為 public { get { return _geoType; } } public abstract double Volume(); //抽象函式, 子類別需進行 override public double Weight() //開放給其他類別使用, 故宣告成 public { return Density() * Volume(); } public double Density() //根據 Material Type 計算 density { return MaterialTable.Density(_materialType); } public abstract string ShapeProperty(); //抽象函式, 子類別需進行 override protected string Property() //只讓子類別呼叫, 故宣告 protected, 抽出子類別重複的程式碼進行重構 { string str=""; str += string.Format("{0,8:F2}", Density()); str += '\t'; str += string.Format("{0,8:F2}", Volume()); str += '\t'; str += string.Format("{0,8:F2}", Weight()); return str; } } } ``` ## MaterialTable ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using _106_Quiz7; namespace _106_Classwork8 { public class Element { public ShapeType.Material MaterialType { get; set; } public string Name { get; set; } public double Density { get; set; } public Element() { } public Element(ShapeType.Material mType, string name, double density) { MaterialType = mType; Name = name; Density = density; } } public static class MaterialTable // 宣告 static 類別, 不用 new Obj 即可使用 { public static Element[] elements= { new Element(ShapeType.Material.Al, "鋁", 2.7), new Element(ShapeType.Material.Fe, "鐵", 7.87), new Element(ShapeType.Material.Pb, "鉛", 11.3) }; public static ShapeType.Material Type(string name) { foreach (var e in elements) { if (e.Name == name) return e.MaterialType; } return ShapeType.Material.UNKNOWN; } public static double Density(string name) { foreach(var e in elements) { if (e.Name == name) return e.Density; } return 0; } public static double Density(ShapeType.Material mType) { foreach (var e in elements) { if (e.MaterialType == mType) return e.Density; } return 0; } } } ``` ## h2 IRollable ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _106_Classwork8 { interface IRollable { double Distance(); string RollShapeProperty(); } } ``` ## Cylinder ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using _106_Quiz7; using _106_Classwork8; namespace _106_Quiz6 { class Cylinder:Shape3D,IRollable { new private static int _amount; //隱藏繼承 private double _radius; private double _height; private static double _pi = 3.1415926; public Cylinder():base() { _geoType = ShapeType.Geo.CYLINDER; _radius = 0; _height = 0; _amount++; } public Cylinder(double radius, double height, ShapeType.Material mType):base(mType) { _geoType = ShapeType.Geo.CYLINDER; Radius = radius; Height = height; _amount++; } new public static int Amount //隱藏繼承 { get { return _amount; } } public double Radius { get { return _radius; } set { if (value < 0) _radius = 0; else _radius = value; } } public double Height { get { return _height; } set { if (value < 0) _height = 0; else _height = value; } } public override double Volume() //改寫父類別的方法, 給其他類別使用故宣告為 public { return _pi * _radius * _radius * _height; } public override string ShapeProperty() //改寫父類別的方法, 給其他類別使用故宣告為 public { string str = string.Format("{0,8}", "Cylinder"); str += '\t'; str += string.Format("{0,8:F2}", _radius); str += '\t'; str += string.Format("{0,8:F2}", _height); str += '\t'; str += Property(); //重構, 降低重複的程式碼 return str; } //實作介面函數 public double Distance() { return Radius * Height; } public string RollShapeProperty() { return ShapeProperty() + string.Format("{0,8:F2}", Distance()); } } } ``` ## h2 Form1.cs ```csharp= using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using _106_Quiz6; using _106_Quiz7; using _106_Classwork8; using System.Collections; namespace _106_Quiz6 { public partial class Form1 : Form { private List<Shape3D> shapeArr = new List<Shape3D>(); // 使用 ArrayList 來儲存產生的形狀物件 private List<IRollable> _mRollShapeList = new List<IRollable>(); private delegate bool CompareFunc(Shape3D a, Shape3D b); //利用委託來傳函式給另一個函式使用 private ShapeType.Material _mType; //紀錄材料類別的欄位, 被兩個事件用到, 故需宣告為類別變數 public Form1() { InitializeComponent(); cboxShape.SelectedIndex = 0; //初始化 comboBox 避免出問題 cBoxMaterial.SelectedIndex = 0; //初始化 comboBox 避免出問題 cboxSortType.SelectedIndex = 0; //初始化 comboBox 避免出問題 txtDensity.Enabled = false; //取消自行輸入密度的選項 } private void btnAddShape_Click(object sender, EventArgs e) { string shape = cboxShape.SelectedItem.ToString(); switch (shape) { case "球": shapeArr.Add(new Ball(Double.Parse(txtPara1.Text), _mType)); // new 出 Ball 物件, 並將其加入 shapeArr中 break; case "立方體": shapeArr.Add(new Cube(Double.Parse(txtPara1.Text), _mType)); break; case "圓柱體": shapeArr.Add(new Cylinder(Double.Parse(txtPara1.Text), Double.Parse(txtPara2.Text), _mType)); break; case "金字塔": shapeArr.Add(new Pyramid(Double.Parse(txtPara1.Text), Double.Parse(txtPara2.Text), _mType)); break; default: break; } txtAmountOfShape.Text = Shape3D.Amount.ToString(); txtBallAmount.Text = Ball.Amount.ToString(); txtCubeAmount.Text = Cube.Amount.ToString(); txtCylinderAmount.Text = Cylinder.Amount.ToString(); txtPyramidAmount.Text = Pyramid.Amount.ToString(); ShowAllShapeInfo(txtMessage); } private void ShowAllShapeInfo(TextBox msg) { string info=""; foreach(var shape in shapeArr) { info += (shape.ShapeProperty() + "\r\n"); } msg.Text = info; } private void cboxShape_SelectedIndexChanged(object sender, EventArgs e) { string shape = cboxShape.SelectedItem.ToString(); switch (shape) { case "球": lblPara1.Text = "半徑"; lblPara2.Visible= false; txtPara2.Visible = false; break; case "立方體": lblPara1.Text = "邊長"; lblPara2.Visible = false; txtPara2.Visible = false; break; case "圓柱體": lblPara1.Text = "半徑"; lblPara2.Visible = true; lblPara2.Text = "高"; txtPara2.Visible = true; break; case "金字塔": lblPara1.Text = "邊長"; lblPara2.Visible = true; lblPara2.Text = "高"; txtPara2.Visible = true; break; default: break; } } private void cBoxMaterial_SelectedIndexChanged(object sender, EventArgs e) { string material = cBoxMaterial.SelectedItem.ToString(); _mType = MaterialTable.Type(material); txtDensity.Text = MaterialTable.Density(material).ToString(); } //以下為排序功能所需的函數 private bool CompareByShapeTypeAscent(Shape3D a, Shape3D b) //Ascent =true 時遞增 =false 時遞減 { if (a.GeoType > b.GeoType) return true; else return false; } private bool CompareByShapeTypeDescent(Shape3D a, Shape3D b) //Ascent =true 時遞增 =false 時遞減 { if (a.GeoType < b.GeoType) return true; else return false; } private bool CompareByMaterialAscent(Shape3D a, Shape3D b) //Ascent =true 時遞增 =false 時遞減 { if (a.MaterialType > b.MaterialType) return true; else return false; } private bool CompareByMaterialDescent(Shape3D a, Shape3D b) //Ascent =true 時遞增 =false 時遞減 { if (a.MaterialType < b.MaterialType) return true; else return false; } private bool CompareByVolumnAscent(Shape3D a, Shape3D b) //Ascent =true 時遞增 =false 時遞減 { if (a.Volume() > b.Volume()) return true; else return false; } private bool CompareByVolumnDescent(Shape3D a, Shape3D b) //Ascent =true 時遞增 =false 時遞減 { if (a.Volume() < b.Volume()) return true; else return false; } private bool CompareByWeightAscent(Shape3D a, Shape3D b) //Ascent =true 時遞增 =false 時遞減 { if (a.Weight() > b.Weight()) return true; else return false; } private bool CompareByWeightDescent(Shape3D a, Shape3D b) //Ascent =true 時遞增 =false 時遞減 { if (a.Weight() < b.Weight()) return true; else return false; } private void BubbleSort(CompareFunc cmp) //利用委託的方式將 比較函式 傳進 排序函式中, 可以精簡程式碼 { Shape3D temp; for (int pass = 0; pass < shapeArr.Count; pass++) { for (int i = 0; i < shapeArr.Count - 1; i++) { if (cmp(shapeArr[i],shapeArr[i + 1])) { temp = shapeArr[i]; shapeArr[i] = shapeArr[i + 1]; shapeArr[i + 1] = temp; } } } } private void btnCofirmSort_Click(object sender, EventArgs e) { switch (cboxSortType.SelectedItem.ToString()) { case "形狀": if (rBtnAscent.Checked) BubbleSort(CompareByShapeTypeAscent); else BubbleSort(CompareByShapeTypeDescent); break; case "材料": if (rBtnAscent.Checked) BubbleSort(CompareByMaterialAscent); else BubbleSort(CompareByMaterialDescent); break; case "體積": if (rBtnAscent.Checked) BubbleSort(CompareByVolumnAscent); else BubbleSort(CompareByVolumnDescent); break; case "重量": if (rBtnAscent.Checked) BubbleSort(CompareByWeightAscent); else BubbleSort(CompareByWeightDescent); break; default: break; } ShowAllShapeInfo(txtSortMessage); } //以下為滾球大賽的程式碼 private void btn_RollContest_Click(object sender, EventArgs e) { IRollable rollShape = null; _mRollShapeList.Clear(); //從 shapeArr 中尋找屬於 IRollable 的物件並加入 _mRollShapeList foreach (var shape in shapeArr) { rollShape = shape as IRollable; if (null != rollShape) _mRollShapeList.Add(rollShape); } _mRollShapeList.Sort(CompareByDistance); //使用 List 的內建Sort函式 ShowRollShapeInfo(txt_RollContest); } private int CompareByDistance(IRollable a, IRollable b) //使用List 內定的 Sort時, 回傳型態是整數 { if (a.Distance() > b.Distance()) return -1; else return 1; } private void ShowRollShapeInfo(TextBox msg) { string info = ""; foreach (var rollShape in _mRollShapeList) { info += (rollShape.RollShapeProperty() + "\r\n"); } msg.Text = info; } } } ```