---
# System prepended metadata

title: QUIZ 8

---

# QUIZ 8

###### tags: OOP

## Form1.cs
```
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 System.Collections;

namespace _106_Quiz6
{
    public partial class Form1 : Form
    {
        private ArrayList shapeArr = new ArrayList();      // 使用 ArrayList 來儲存產生的形狀物件
        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 避免出問題
        }

        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(Shape3D 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();
            double density;
            bool canModified = false;
            switch (material)
            {
                case "鋁":
                    _mType = ShapeType.Material.Al;
                    density = 2.7; 
                    break;
                case "鐵":
                    _mType = ShapeType.Material.Fe;
                    density = 7.87;
                    break;
                case "鉛":
                    _mType = ShapeType.Material.Pb;
                    density = 11.3;
                    break;
               
                default:
                    density = 0;
                    canModified = true;
                    break;
            }
            txtDensity.Text = density.ToString();
            if (!canModified)
                txtDensity.Enabled = false;
        }

        private void btn_FindHeaviestShape_Click(object sender, EventArgs e)
        {
            string info = "";
            double maxWeight = 0;
            foreach (Shape3D shape in shapeArr)
            {
                if(shape.Weight() > maxWeight)
                {
                    maxWeight = shape.Weight();
                    info = shape.ShapeProperty();
                }
            }
            txt_ShowHeaviestShape.Text = info;
        }
        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)   //利用委託的方式將 比較函式 傳進 排序函式中, 可以精簡程式碼
        {
            Object temp;  // shapeArr 屬於 ArrayList 類別, 每一個元素都是 Object 類別, Object 是所有類別的父類別 
            for (int pass = 0; pass < shapeArr.Count; pass++)
            {
                for (int i = 0; i < shapeArr.Count - 1; i++)
                {
                    if (cmp((Shape3D)shapeArr[i],(Shape3D)shapeArr[i + 1]))      //呼叫不同的 compare function, shapeArr 的元素是 Object 類別, 因此需強制轉型為 Shape3D
                    {
                        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);
        }
    }
}

```
## Shape3D.cs
```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _106_Quiz7
{
    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
        {
            double density = 0;
            switch(_materialType)
            {
                case ShapeType.Material.Al:
                    density = 2.7;
                    break;
                case ShapeType.Material.Fe:
                    density = 7.87;
                    break;
                case ShapeType.Material.Pb:
                    density = 11.3;
                    break;
                default:
                    break; 
            }
            return density;
        }
        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;
        }

    }
}

```