---
# System prepended metadata

title: OOP midtern

---

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

```