# 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;
}
}
}
```