Const.cs
namespace HW7___多邊體計算視窗程式2
{
static class GeoConst
{
public static readonly double Pi = 3.14159;
}
static class MetrialConst
{
public static readonly double Density_Al = 2.7;
public static readonly double Density_Fe = 7.87;
public static readonly double Density_Pb = 11.3;
public static readonly double Density_Ice = 0.9;
public static readonly double Density_Wood = 0.8;
}
}
IRollable.cs namespace HW7___多邊體計算視窗程式2
{
interface IRollable
{
double RollDistance();
}
}
Shape.cs namespace HW7___多邊體計算視窗程式2
{
abstract class Shape
{//此為抽象類別,不可以實體化,因為形狀不是任何一種形狀
private static int _count = 0;
public static int Count { get { return _count; } }
protected double density=0;
public double Density { get { return density; } }
//建構子
public Shape()
{
_count++;
}
//解構子
~Shape()
{
_count--;
}
public double Weight()
{//重量=體積*密度, 不須另外宣告變數存放
return Bulk() * density;
}
public abstract double Bulk();//體積演算法每種形狀都不同, 留給衍生類實作
}
}
Ball.cs namespace HW7___多邊體計算視窗程式2
{
class Ball : Shape, IRollable
{
private static int _count = 0;
new public static int Count { get { return _count; } }
//長度參數
private double _radius = 0;
//建構子
public Ball(double radius, double density)
{
this.density = density;
this._radius = radius;
_count++;
}
//解構子
~Ball()
{
_count--;
}
public override double Bulk()
{
return (4.0 / 3.0) * GeoConst.Pi * _radius * _radius * _radius;
}
public double RollDistance()
{//prototype at Interface
return _radius * _radius;
}
}
}
Cube.cs namespace HW7___多邊體計算視窗程式2
{
class Cube : Shape
{
private static int _count = 0;
new public static int Count { get { return _count; } }
//長度參數
private double _side = 0;
//建構子
public Cube(double side, double density)
{
this.density = density;
this._side = side;
_count++;
}
//解構子
~Cube()
{
_count--;
}
public override double Bulk()
{
return _side*_side*_side;
}
}
}
Cylinder.cs namespace HW7___多邊體計算視窗程式2
{
class Cylinder : Shape,IRollable
{
private static int _count = 0;
new public static int Count { get { return _count; } }
//長度參數
private double _radius = 0;
private double _height = 0;
//建構子
public Cylinder(double radius, double height, double density)
{
this.density = density;
this._radius = radius;
this._height = height;
_count++;
}
//解構子
~Cylinder()
{
_count--;
}
public override double Bulk()
{
return GeoConst.Pi * _radius * _radius * _height;
}
public double RollDistance()
{//prototype at Interface
return _radius * 5;
}
}
}
Pyramid.cs namespace HW7___多邊體計算視窗程式2
{
class Pyramid : Shape
{
private static int _count = 0;
new public static int Count { get { return _count; } }
//長度參數
private double _side = 0;
private double _height = 0;
//建構子
public Pyramid(double side, double height, double density)
{
this.density = density;
this._side = side;
this._height = height;
_count++;
}
//解構子
~Pyramid()
{
_count--;
}
public override double Bulk()
{
double _dSide = _side/1000;
double _dHeight = _height/1000;
double _tempBulk=0;
for (int i=0; i<1000 ; i++ )
{//從最底下的那片體積往上加,邊長一直縮小
double _currentSide = _side - (i * _dSide * 0.5); //0.5 使 side 修正到斜邊中點
_tempBulk += _currentSide * _currentSide * _dHeight;
}
return _tempBulk;
}
}
}
Form1.cs namespace HW7___多邊體計算視窗程式2
{
public partial class Form1 : Form
{
private List ListShape = new List();
public Form1()
{
InitializeComponent();
}
private double DensityTable(string material)
{
if (material == "鐵") return MetrialConst.Density_Fe;
if (material == "冰") return MetrialConst.Density_Ice;
if (material == "木材") return MetrialConst.Density_Wood;
return -9999;
}
private void btnAddNewShape_Click(object sender, EventArgs e)
{
///================ 使用者輸入檢查 開始 ================
bool CheckPass = false; //標記使用者是否通過防呆檢查
string Forget = ""; //存放使用者忘記輸入的項目
int DummyInt; //供int.TryParse()檢查用
double DummyDouble; //供double.TryParse()檢查用
//逐條審查,不可用switch case
if (null == cbBox_Material.SelectedItem)Forget += " 材質";
if (null == cbBox_Shape.SelectedItem) Forget += " 形狀";
if (!int.TryParse(txtBox_AddNewShapeNum.Text, out DummyInt)) Forget += " 數量";
if (!double.TryParse(txtBox_ShapeParameter1.Text, out DummyDouble)) Forget += " 第1個形狀參數";
if ((cbBox_Shape.SelectedItem.ToString() == "圓柱體") || (cbBox_Shape.SelectedItem.ToString() == "金字塔"))
{
if ("" == txtBox_ShapeParameter2.Text) Forget += " 第2個形狀參數";
}
//拋出檢查結果. 若無錯誤就Pass
if ("" != Forget)
MessageBox.Show("你忘記輸入" + Forget + " !\a");
else
CheckPass = true;//無錯誤
///================ 使用者輸入檢查 結束 ================
//若是沒有通過防呆檢查,以下這個迴圈會被by pass
for(int i=0;CheckPass && i<(Convert.ToInt16(txtBox_AddNewShapeNum.Text));i++)
{
double _localDensity = DensityTable(cbBox_Material.Text);//取得選單所選之密度數值
switch (cbBox_Shape.SelectedItem.ToString())
{
case "球":
{
double _tempRadius = Convert.ToDouble(txtBox_ShapeParameter1.Text);
ListShape.Add(new Ball(_tempRadius, _localDensity));
txtBox_ShapeList1.AppendText("Ball \t"
+ "半徑=" + Convert.ToString(_tempRadius) + " "
+ "\n");
}
break;
case "正方體":
{
double _tempSide = Convert.ToDouble(txtBox_ShapeParameter1.Text);
ListShape.Add(new Cube(Convert.ToDouble(txtBox_ShapeParameter1.Text), _localDensity));
txtBox_ShapeList1.AppendText("Cube \t"
+ "邊長=" + Convert.ToString(_tempSide) + " "
+ "\n");
}
break;
case "圓柱體":
{
double _tempRadius = Convert.ToDouble(txtBox_ShapeParameter1.Text);
double _tempHeight = Convert.ToDouble(txtBox_ShapeParameter2.Text);
ListShape.Add(new Cylinder(_tempRadius, _tempHeight, _localDensity));
txtBox_ShapeList1.AppendText("Cylinder \t"
+ "半徑=" + Convert.ToString(_tempRadius) + " "
+ "高度=" + Convert.ToString(_tempHeight) + " "
+ "\n");
}
break;
case "金字塔":
{
double _tempSide = Convert.ToDouble(txtBox_ShapeParameter1.Text);
double _tempHeight = Convert.ToDouble(txtBox_ShapeParameter2.Text);
ListShape.Add(new Pyramid(_tempSide, _tempHeight, _localDensity));
txtBox_ShapeList1.AppendText("Pyramid \t"
+ "邊長=" + Convert.ToString(_tempSide) + " "
+ "高度=" + Convert.ToString(_tempHeight) + " "
+ "\n");
}
break;
}
}
}
private void cbBox_Shape_SelectedIndexChanged(object sender, EventArgs e)
{//顯示介面控制, 當使用者改變 形狀 時, 動態更動UI
switch (cbBox_Shape.SelectedItem.ToString())
{
case "球":
{
labelParameter1.Text = "直徑"; txtBox_ShapeParameter1.Visible = true;
labelParameter2.Text = ""; txtBox_ShapeParameter2.Visible = false;
}
break;
case "正方體":
{
labelParameter1.Text = "邊長"; txtBox_ShapeParameter1.Visible = true;
labelParameter2.Text = ""; txtBox_ShapeParameter2.Visible = false;
}
break;
case "圓柱體":
{
labelParameter1.Text = "直徑"; txtBox_ShapeParameter1.Visible = true;
labelParameter2.Text = "高"; txtBox_ShapeParameter2.Visible = true;
}
break;
case "金字塔":
{
labelParameter1.Text = "邊長"; txtBox_ShapeParameter1.Visible = true;
labelParameter2.Text = "高"; txtBox_ShapeParameter2.Visible = true;
}
break;
}
}
private void btnCalcShapeParameter_Click(object sender, EventArgs e)
{
txtBox_ShapeList2.Clear();
for (int i = 0; i < ListShape.Count ; i++)
{
txtBox_ShapeList2.AppendText( ListShape[i].GetType().Name + "\t "
+ "密度:" + ListShape[i].Density.ToString("f2") + "\t "
+ "體積:" + ListShape[i].Bulk().ToString("f2") + "\t "
+ "重量:" + ListShape[i].Weight().ToString("f2") + "\t "
+ "\n");
}
}
private void btnCalcRollDistance_Click(object sender, EventArgs e)
{
txtBox_ShapeListForRollDistance.Clear();//清除畫面
List RollableList = new List();//宣告管理可滾動物件的陣列,每次重新配置
for (int i = 0; i < ListShape.Count; i++)//檢查每一個由Shape refenece 管理的物件
{
//取得 ListShape[i] 的類別資訊
Ball DummyBall = new Ball(0,0);
Cylinder DummyCylinder = new Cylinder(0,0,0);
bool _isBallObj = (ListShape[i].GetType() == DummyBall.GetType());
bool _isCylinderObj = (ListShape[i].GetType() == DummyCylinder.GetType());
if (_isBallObj || _isCylinderObj)
{//如果是可以滾動的Shape衍生類,就進來
RollableList.Add((IRollable)ListShape[i]); //加入可滾動的List之中
txtBox_ShapeListForRollDistance.AppendText(
((Shape)RollableList[RollableList.Count-1]).GetType().Name + "\t " +
"滾動距離:" + RollableList[RollableList.Count-1].RollDistance().ToString("f2") + "\t " +
"\n");
}
}//迴圈結束
}
}
}
提醒一下, namespace最好使用英文.
回覆刪除這個問題出於你們一開始建立專案時,命名就用"W7___多邊體計算視窗程式2". 雖然用visual studio編譯不會出錯,但是難保之後其他程式用這支專案檔內的類別時會出錯. 所以最好養成以英文命名的習慣.
其他內容還沒看過,所以就先講到這.
林高遠:
刪除namespace 的名稱是我在建專案時打的專案名稱,IDE就自動當作namespace了,謝謝提醒以後我會注意,不過沒特別狀況的話,應該就不會去改
Form1.cs 中第157, 158行的兩個實體化應該可以丟到迴圈外
回覆刪除應該不需要每個迴圈都做一次
林高遠:這個地方是為了最小權限原則&模組化,只有該scope內用到的東西,不宜在scope外宣告;另外程式碼移植時也可以整塊移動,所以這樣做是有必要的,為了以上好處,我寧願讓他每個迴圈都多做一次。
刪除那這樣子我可以理解了,但是我還是覺得這做法不是很好。
刪除bool _isBallObj = ListShape[i] is Ball ;
應該是更好的做法,只是現在還沒教到就是了。
我不知道還有這種語法,太好了
刪除