問題1
Console.Write を用いて、自分の名前を画面に表示せよ。
using System;
class Sample
{
static void Main()
{
Console.Write("岩永信之");
}
}
問題2
Console.ReadLine を用いて文字列を1行読み込み、
Console.Write を用いて読んだ文字列をそのまま鸚鵡返しするプログラムを作成せよ。
おまけ: 1度読み込んだ文字列を2度ずつ鸚鵡返しするものを作成せよ。
using System;
class Sample
{
static void Main()
{
string line = Console.ReadLine();
Console.Write(line);
}
}
using System;
class Sample
{
static void Main()
{
string line = Console.ReadLine();
Console.Write(line);
Console.Write(line);
}
}
問題1
2つの整数を入力し、
その整数の四則演算(+, -, ×, ÷)結果を表示するプログラムを作成せよ。
using System;
class Exercise
{
static void Main()
{
Console.Write("input a: ");
int a = int.Parse(Console.ReadLine());
Console.Write("input b: ");
int b = int.Parse(Console.ReadLine());
Console.Write("{0} + {1} = {2}\n", a, b, a + b);
Console.Write("{0} - {1} = {2}\n", a, b, a - b);
Console.Write("{0} * {1} = {2}\n", a, b, a * b);
Console.Write("{0} / {1} = {2}\n", a, b, a / b);
}
}
問題2
前問の「整数の四則演算」の、 double, short 等の他の型を用いた物を作成せよ。
例として double 版を掲載。
using System;
class Exercise
{
static void Main()
{
Console.Write("input a: ");
double a = double.Parse(Console.ReadLine());
Console.Write("input b: ");
double b = double.Parse(Console.ReadLine());
Console.Write("{0} + {1} = {2}\n", a, b, a + b);
Console.Write("{0} - {1} = {2}\n", a, b, a - b);
Console.Write("{0} * {1} = {2}\n", a, b, a * b);
Console.Write("{0} / {1} = {2}\n", a, b, a / b);
}
}
問題3
複素数 x + iy の逆数を求めるプログラムを作成せよ。
using System;
class Exercise
{
static void Main()
{
Console.Write("実部を入力してください: ");
double x = double.Parse(Console.ReadLine());
Console.Write("虚部を入力してください: ");
double y = double.Parse(Console.ReadLine());
double norm = x * x + y * y;
Console.Write("{0} + i({1}) の逆数は {2} + i({3})\n)",
x, y,
x / norm, -y / norm);
}
}
問題4
半径を入力し、その半径の円の面積を求めるプログラムを作成せよ。
using System;
class Exercise
{
static void Main()
{
double r;
Console.Write("半径を入力してください: ");
r = double.Parse(Console.ReadLine());
double area = r * r * 3.1415926535897932;
Console.Write("面積 = {0}\n", area);
}
}
問題5
体重と身長を入力し、BMIを求めるプログラムを作成せよ。
BMIは、WHO(世界保健機関)が推奨しているもので、Body Mass Indexの略称で、肥満度指数とも呼ばれています。 BMIは肥満度の基準として、広く使用されている測定方法です。
計算式は、下記のとおりで比較的簡単に計算できることも特徴です。
BMI = 体重(kg)÷{身長(m)×身長(m)}
BMIの値が22のときに病気になる可能性が最も低く、BMIが26を超えると糖尿病など生活習慣病になるリスクが高まると言われています。
BMI 値
|
|
19.8未満
|
やせ型
|
19.8~24.2未満
|
普通
|
24.2~26.4未満
|
やや肥満(過体重)
|
26.4~35.0未満
|
肥満
|
35.0以上
|
高度肥満(要治療)
|
以下にプログラムの実行結果の例を示す。
身長[cm] = 175.5
体重[kg] = 52.4
BMI = 17.0128489216808
using System;
class Exercise
{
static void Main()
{
double height;
double weight;
Console.Write("身長[cm]: ");
height = double.Parse(Console.ReadLine());
height *= 0.01;
Console.Write("体重[kg]: ");
weight = double.Parse(Console.ReadLine());
double bmi = weight / (height * height);
Console.Write("BMI = {0}\n", bmi);
}
}
問題1
適当な文字を入力し、その文字コードを表示するプログラムを作成せよ。
(char 型の変数を int 型にキャストすると文字コードが得られます。)
using System;
class Exercise
{
static void Main()
{
char c;
Console.Write("文字を入力してください: ");
c = Console.ReadLine()[0];
Console.Write("文字 {0} の文字コードは {1}\n", c, (int)c);
}
}
問題2
整数型(int, short, long)同士の割り算では、結果も整数となり、あまりは切り捨てられます。
切り捨てられると困る場合、浮動小数点数(double, float)にキャストしてから計算する必要があります。
このことを確かめるため、
2つの整数を入力し、
整数のままで割り算した結果(あまり切り捨て)と、
浮動小数点数として割り算した結果を比較するプログラムを作成せよ。
using System;
class Exercise
{
static void Main()
{
Console.Write("input a: ");
int a = int.Parse(Console.ReadLine());
Console.Write("input b: ");
int b = int.Parse(Console.ReadLine());
Console.Write("整数: {0} / {1} = {2} … {3}\n", a, b, a / b, a % b);
Console.Write("実数: {0} / {1} = {2}\n", a, b, a / (double)b);
}
}
問題3
double → int にキャストすると、値が整数に切り詰められます。
このとき、どのようにして値が切り詰められるのか(切捨てなのか切り上げなのか等)を調べよ。
(正の数だけでなく、負の数も。)
using System;
class Exercise
{
static void Main()
{
Console.Write("{0} → {1}\n", 3.8, (int)3.8);
Console.Write("{0} → {1}\n", 3.1, (int)3.1);
Console.Write("{0} → {1}\n", 2.7, (int)2.7);
Console.Write("{0} → {1}\n", 2.4, (int)2.4);
Console.Write("{0} → {1}\n", 1.5, (int)1.5);
Console.Write("{0} → {1}\n", 0.5, (int)0.5);
Console.Write("{0} → {1}\n", -3.8, (int)-3.8);
Console.Write("{0} → {1}\n", -3.1, (int)-3.1);
Console.Write("{0} → {1}\n", -2.7, (int)-2.7);
Console.Write("{0} → {1}\n", -2.4, (int)-2.4);
Console.Write("{0} → {1}\n", -1.5, (int)-1.5);
Console.Write("{0} → {1}\n", -0.5, (int)-0.5);
}
}
3.8 → 3
3.1 → 3
2.7 → 2
2.4 → 2
1.5 → 1
0.5 → 0
-3.8 → -3
-3.1 → -3
-2.7 → -2
-2.4 → -2
-1.5 → -1
-0.5 → 0
結果を見ての通り、正の数は切り捨て、負の数は切り上げ(0 に向かって丸め)になります。
正負問わず値を切り捨てたい場合は Math.Floor
関数を、
切り上げたい場合は Math.Ceiling
関数を、
四捨五入したい場合は Math.Round
関数を使用します。
問題1
ユーザから入力された整数が奇数か偶数か判定するプログラムを作成せよ。
using System;
class Exercise
{
static void Main()
{
Console.Write("整数を入力してください: ");
int n = int.Parse(Console.ReadLine());
if (n % 2 == 0) Console.Write("{0} は偶数です\n", n);
else Console.Write("{0} は奇数です\n", n);
}
}
問題2
組込み演算子の問題 5のプログラムを修正し、
BMI 値から体型(やせ型、普通、やや肥満、肥満、高度肥満)を判定し、
表示するプログラムを作成せよ。
using System;
class Exercise
{
static void Main()
{
Console.Write("身長[cm]: ");
double height = double.Parse(Console.ReadLine()) * 0.01;
Console.Write("体重[kg]: ");
double weight = double.Parse(Console.ReadLine());
double bmi = weight / (height * height);
Console.Write("BMI = {0}\n", bmi);
if(bmi < 19.8) Console.Write("やせ型");
else if(bmi < 24.2) Console.Write("普通");
else if(bmi < 26.4) Console.Write("やや肥満(過体重)");
else if(bmi < 35.0) Console.Write("肥満");
else Console.Write("高度肥満(要治療)");
Console.Write("です\n");
}
}
問題3
switch 文を使って150以下の平方数(4=2×2、9=3×3、16=4×4というように、ある整数の二乗になっている数)を判別するプログラムを作成せよ。
ユーザに整数値を1つ入力してもらい、
判別結果を出力するものとする。
ヒント:
要するに、ユーザからの入力が 1, 4, 9, 16, ・・・になっているかどうかを switch 文で判別します。
using System;
class Exercise
{
static void Main()
{
Console.Write("整数を入力してください: ");
int n = int.Parse(Console.ReadLine());
switch (n)
{
case 1:
Console.Write("{0} は平方数です。\n", n);
break;
case 2 * 2: goto case 1;
case 3 * 3: goto case 1;
case 4 * 4: goto case 1;
case 5 * 5: goto case 1;
case 6 * 6: goto case 1;
case 7 * 7: goto case 1;
case 8 * 8: goto case 1;
case 9 * 9: goto case 1;
case 10 * 10: goto case 1;
case 11 * 11: goto case 1;
case 12 * 12: goto case 1;
default:
Console.Write("{0} は平方数ではないか、150以上です\n", n);
break;
}
}
}
問題4
数値を3つ入力してもらい、
その3つの値の中の最大値、最小値を求めるプログラムを作成せよ。
単純な条件分岐による方法。
using System;
class Exercise
{
static void Main()
{
Console.Write("値1: ");
double x = double.Parse(Console.ReadLine());
Console.Write("値2: ");
double y = double.Parse(Console.ReadLine());
Console.Write("値3: ");
double z = double.Parse(Console.ReadLine());
if (x > y)
{
if (x > z)
{
if (y > z) Console.Write("最大 {0}, 中間 {1}, 最小 {2}\n", x, y, z);
else Console.Write("最大 {0}, 中間 {1}, 最小 {2}\n", x, z, y);
}
else Console.Write("最大 {0}, 中間 {1}, 最小 {2}\n", z, x, y);
}
else
{
if (y > z)
{
if (x > z) Console.Write("最大 {0}, 中間 {1}, 最小 {2}\n", y, x, z);
else Console.Write("最大 {0}, 中間 {1}, 最小 {2}\n", y, z, x);
}
else Console.Write("最大 {0}, 中間 {1}, 最小 {2}\n", z, y, x);
}
}
}
3つの数値をあらかじめ整列してしまう方法。
using System;
class Exercise
{
static void Main()
{
Console.Write("値1: ");
double x = double.Parse(Console.ReadLine());
Console.Write("値2: ");
double y = double.Parse(Console.ReadLine());
Console.Write("値3: ");
double z = double.Parse(Console.ReadLine());
double tmp;
if (y < z) { tmp = y; y = z; z = tmp; }
if (x < y) { tmp = x; x = y; y = tmp; }
if (y < z) { tmp = y; y = z; z = tmp; }
Console.Write("最大 {0}, 中間{1}, 最小 {2}\n", x, y, z);
}
}
問題1
ユーザに整数 n を入力してもらい、
1 から n までの整数の和を求めるプログラムを作成せよ。
ただし、
ループを使って和を求めたものと、
和の公式
n (n + 1)
の結果を比較せよ。
using System;
class Exercise
{
static void Main()
{
Console.Write("n: ");
int n = int.Parse(Console.ReadLine());
int sum = 0;
for (int i = 1; i <= n; ++i)
{
sum += i;
}
Console.Write("loop {0}, formula {1}\n", sum, n * (n + 1) / 2);
}
}
問題2
平方数(4=2×2、9=3×3、16=4×4というように、ある整数の二乗になっている数)を判別するプログラムを作成せよ。
ユーザに整数値を1つ入力してもらい、
判別結果を出力するものとする。
条件分岐の問題 2と異なり、判別できる数値に上限は設けない。
ヒント:ループと条件分岐を組み合わせて作る。
using System;
class Exercise
{
static void Main()
{
Console.Write("整数を入力してください: ");
int n = int.Parse(Console.ReadLine());
int i;
for (i = 0; i <= n; ++i)
{
if (n == i * i) break;
}
if (i <= n) Console.Write("{0} = {1} × {1} は平方数です\n", n, i);
else Console.Write("{0} は平方数ではありません\n", n);
}
}
ちなみに、この for ループの継続条件の部分は、
i <= (int)Math.Sqrt(n)
でも OK。
(その下の if 文の条件も変更する必要あり。)
Sqrt は n の平方根を求める関数。
問題3
2重ループを使って掛け算の九九表を表示するプログラムを作成せよ。
using System;
class Exercise
{
static void Main()
{
for (int i = 1; i <= 9; ++i)
{
for (int j = 1; j <= 9; ++j)
{
Console.Write("{0,3}", i * j);
}
Console.Write('\n');
}
}
}
問題1
for 文を使って以下の漸化式の一般項
an
を20項目まで求めるプログラムを作成せよ。 (
an
を配列で表す。)
an + 2 = 2 an + 1 - 2 an
a0 = 3
a1 = 1
using System;
class Exercise
{
static void Main()
{
int[] a = new int[21];
a[0] = 3;
a[1] = 1;
for (int i = 2; i < a.Length; ++i)
{
a[i] = 2 * a[i - 1] - 2 * a[i - 2];
}
for (int i = 0; i < a.Length; ++i)
{
Console.Write("{0} ", a[i]);
}
Console.Write('\n');
}
}
問題2
int 型の配列に格納されている値の最大値、最小値および平均値を求めよ。
できれば、配列の長さ n および n 個の整数値をユーザに入力してもらうようにすること。
using System;
class Exercise
{
static void Main()
{
Console.Write("配列の長さ: ");
int n = int.Parse(Console.ReadLine());
int[] a = new int[n];
for (int i = 0; i < n; ++i)
{
Console.Write("{0}: ", i);
a[i] = int.Parse(Console.ReadLine());
}
int max = int.MinValue;
int min = int.MaxValue;
double average = 0;
for (int i = 0; i < n; ++i)
{
if (max < a[i]) max = a[i];
if (min > a[i]) min = a[i];
average += a[i];
}
average /= n;
Console.Write(
@"
最大値: {0}
最小値: {1}
平均値: {2}
"
, max, min, average);
}
}
問題3
double 型の2次元配列を行列に見立てて、行列の掛け算を行うプログラムを作成せよ。
行列の次元は任意だけども、例として2×2行列の場合を示す。
using System;
class Exercise
{
static void Main()
{
double[,] a = new double[,]
{
{1, 1},
{1, 0},
};
double[,] b = new double[,]
{
{1, 2},
{3, 4},
};
double[,] c = new double[a.GetLength(0), b.GetLength(1)];
for (int i = 0; i < a.GetLength(0); ++i)
for (int j = 0; j < b.GetLength(1); ++j)
for (int k = 0; k < a.GetLength(1); ++k)
c[i, j] += a[i, k] * b[k, j];
Console.Write("a =\n");
for (int i = 0; i < a.GetLength(0); ++i)
{
for (int j = 0; j < a.GetLength(1); ++j)
Console.Write("{0, 4} ", a[i, j]);
Console.Write('\n');
}
Console.Write("b =\n");
for (int i = 0; i < b.GetLength(0); ++i)
{
for (int j = 0; j < b.GetLength(1); ++j)
Console.Write("{0, 4} ", b[i, j]);
Console.Write('\n');
}
Console.Write("a×b =\n");
for (int i = 0; i < c.GetLength(0); ++i)
{
for (int j = 0; j < c.GetLength(1); ++j)
Console.Write("{0, 4} ", c[i, j]);
Console.Write('\n');
}
}
}
問題1
int 型の配列に格納されている値の最大値、最小値および平均値を求める関数をそれぞれ作成せよ。
static int Max(int[] a)
static int Min(int[] a)
static double Average(int[] a)
using System;
class Exercise
{
static void Main()
{
Console.Write("配列の長さ: ");
int n = int.Parse(Console.ReadLine());
int[] a = new int[n];
for (int i = 0; i < n; ++i)
{
Console.Write("{0}: ", i);
a[i] = int.Parse(Console.ReadLine());
}
Console.Write(
@"
最大値: {0}
最小値: {1}
平均値: {2}
"
, Max(a), Min(a), Average(a));
}
static int Max(int[] a)
{
int max = int.MinValue;
for (int i = 0; i < a.Length; ++i)
{
if (max < a[i]) max = a[i];
}
return max;
}
static int Min(int[] a)
{
int min = int.MaxValue;
for (int i = 0; i < a.Length; ++i)
{
if (min > a[i]) min = a[i];
}
return min;
}
static double Average(int[] a)
{
double average = 0;
for (int i = 0; i < a.Length; ++i)
{
average += a[i];
}
return average / a.Length;
}
}
問題2
double 型の値 x の整数冪を求める関数 Power を作成せよ。
static double Power(
double x,
int n)
using System;
class Exercise
{
static void Main()
{
const double x = 3;
Console.Write("{0}\n", Power(x, 4));
Console.Write("{0}\n", Power(x, -1));
Console.Write("{0}\n", Power(x, -2));
Console.Write("{0}\n", Power(x, 0));
}
static double Power(
double x,
int n)
{
if (n == 0)
return 1;
if (n < 0)
{
x = 1.0 / x;
n = -n;
}
double y = x;
while (--n > 0)
{
y *= x;
}
return y;
}
}
問題3
配列に格納されている値の最大値を求める関数を、
int[]
に対するものと
double[]
に対するものの2種類作成せよ。
using System;
class Exercise
{
static void Main()
{
int[] ai = new int[] { 1, 3, 9, 2, 5, 6, 4 };
double[] ad = new double[] { 1, 3, 9, 2, 5, 6, 4 };
Console.Write("{0}, {1}\n", Max(ai), Max(ad));
}
static int Max(int[] a)
{
int max = int.MinValue;
for (int i = 0; i < a.Length; ++i)
{
if (max < a[i]) max = a[i];
}
return max;
}
static double Max(double[] a)
{
double max = int.MinValue;
for (int i = 0; i < a.Length; ++i)
{
if (max < a[i]) max = a[i];
}
return max;
}
}
見ての通り、型が変わっただけで、処理自体は全く同じものになっています。
このように、型と無関係に同じ処理で実現できるものは、
「ジェネリック」を使うことで実装の手間を軽減できます。
問題1
サンプル中の Point 構造体を使って、三角形を表す構造体 Triangle
を作成せよ。
(3つの頂点を a, b, c 等のメンバー変数として持つ。)
また、作成した構造体に、三角形の面積を求めるメンバー関数 GetArea
を追加せよ。
public double GetArea()
using System;
struct Point
{
public double x;
public double y;
public override string ToString()
{
return "(" + x + ", " + y + ")";
}
}
struct Triangle
{
public Point a;
public Point b;
public Point c;
public double GetArea()
{
double abx, aby, acx, acy;
abx = b.x - a.x;
aby = b.y - a.y;
acx = c.x - a.x;
acy = c.y - a.y;
return 0.5 * Math.Abs(abx * acy - acx * aby);
}
}
class Test
{
static void Main()
{
Triangle t;
t.a.x = 0;
t.a.y = 0;
t.b.x = 3;
t.b.y = 4;
t.c.x = 4;
t.c.y = 3;
Console.Write("{0}\n", t.GetArea());
}
}
問題1
「データの構造化」のデータの構造化の問題 1で作成した Triangle
構造体をクラスで作り直せ。
(Point
構造体は構造体のままで OK。)
注1:現時点では、
単に struct が class に変わるだけで、特にメリットはありませんが、
今後、
「継承」」や「多態性」を通して、
クラスのメリットを徐々に加えていく予定です。
注2:
クラスにした場合、メンバー変数をきちんと初期化してやらないと正しく動作しません。
(構造体でもメンバー変数の初期化はきちんとする方がいいんですが。)
初期化に関しては、次節の「コンストラクターとデストラクター」で説明します。
問題1
前節クラスの問題 1の Point
構造体および Triangle
クラスに、
以下のようなコンストラクターを追加せよ。
public Point(double x, double y)
public Triangle(Point a, Point b, Point c)
using System;
struct Point
{
public double x;
public double y;
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
public override string ToString()
{
return "(" + x + ", " + y + ")";
}
}
class Triangle
{
public Point a;
public Point b;
public Point c;
public Triangle(Point a, Point b, Point c)
{
this.a = a;
this.b = b;
this.c = c;
}
public double GetArea()
{
double abx, aby, acx, acy;
abx = b.x - a.x;
aby = b.y - a.y;
acx = c.x - a.x;
acy = c.y - a.y;
return 0.5 * Math.Abs(abx * acy - acx * aby);
}
}
class Class1
{
static void Main()
{
Triangle t = new Triangle(
new Point(0, 0),
new Point(3, 4),
new Point(4, 3));
Console.Write("{0}\n", t.GetArea());
}
}
問題1
クラスの問題 1の Point
構造体および Triangle
クラスの各メンバー変数に対して、
プロパティを使って実装の隠蔽を行え。
using System;
struct Point
{
double x;
double y;
#region 初期化
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
#endregion
#region プロパティ
public double X
{
get { return this.x; }
set { this.x = value; }
}
public double Y
{
get { return this.y; }
set { this.y = value; }
}
#endregion
public override string ToString()
{
return "(" + x + ", " + y + ")";
}
}
class Triangle
{
Point a;
Point b;
Point c;
#region 初期化
public Triangle(Point a, Point b, Point c)
{
this.a = a;
this.b = b;
this.c = c;
}
#endregion
#region プロパティ
public Point A
{
get { return a; }
set { a = value; }
}
public Point B
{
get { return b; }
set { b = value; }
}
public Point C
{
get { return c; }
set { c = value; }
}
#endregion
public double GetArea()
{
double abx, aby, acx, acy;
abx = b.X - a.X;
aby = b.Y - a.Y;
acx = c.X - a.X;
acy = c.Y - a.Y;
return 0.5 * Math.Abs(abx * acy - acx * aby);
}
}
class Class1
{
static void Main()
{
Triangle t = new Triangle(
new Point(0, 0),
new Point(3, 4),
new Point(4, 3));
Console.Write("{0}\n", t.GetArea());
}
}
問題1
クラスの問題 1の Point
構造体に、
2点間の距離を求める static メソッド GetDistance
を追加せよ。
public static double GetDistance(Point a, Point b)
また、GetDistance
を用いて、
Triangle
クラスに三角形の周を求めるメソッド
GetPerimeter
を追加せよ。
public double GetPerimeter()
using System;
struct Point
{
double x;
double y;
#region 初期化
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
#endregion
#region プロパティ
public double X
{
get { return this.x; }
set { this.x = value; }
}
public double Y
{
get { return this.y; }
set { this.y = value; }
}
#endregion
public static double GetDistance(Point a, Point b)
{
double x = a.x - b.x;
double y = a.y - b.y;
return Math.Sqrt(x * x + y * y);
}
public override string ToString()
{
return "(" + x + ", " + y + ")";
}
}
class Triangle
{
Point a;
Point b;
Point c;
#region 初期化
public Triangle(Point a, Point b, Point c)
{
this.a = a;
this.b = b;
this.c = c;
}
#endregion
#region プロパティ
public Point A
{
get { return a; }
set { a = value; }
}
public Point B
{
get { return b; }
set { b = value; }
}
public Point C
{
get { return c; }
set { c = value; }
}
#endregion
public double GetArea()
{
double abx, aby, acx, acy;
abx = b.X - a.X;
aby = b.Y - a.Y;
acx = c.X - a.X;
acy = c.Y - a.Y;
return 0.5 * Math.Abs(abx * acy - acx * aby);
}
public double GetPerimeter()
{
double l = Point.GetDistance(this.a, this.b);
l += Point.GetDistance(this.a, this.c);
l += Point.GetDistance(this.b, this.c);
return l;
}
}
class Class1
{
static void Main()
{
Triangle t = new Triangle(
new Point(0, 0),
new Point(3, 4),
new Point(4, 3));
Console.Write("{0}\n", t.GetArea());
Console.Write("{0}\n", t.GetPerimeter());
}
}
問題1
クラスの問題 1の Point
構造体を2次元ベクトルとみなして、
ベクトルの和・差を計算する演算子 +
および -
を追加せよ。
public static Point operator +(Point a, Point b)
public static Point operator -(Point a, Point b)
using System;
struct Point
{
double x;
double y;
#region 初期化
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
#endregion
#region プロパティ
public double X
{
get { return this.x; }
set { this.x = value; }
}
public double Y
{
get { return this.y; }
set { this.y = value; }
}
#endregion
#region 演算子
public static Point operator +(Point a, Point b)
{
return new Point(a.x + b.x, a.y + b.y);
}
public static Point operator -(Point a, Point b)
{
return new Point(a.x - b.x, a.y - b.y);
}
#endregion
public static double GetDistance(Point a, Point b)
{
double x = a.x - b.x;
double y = a.y - b.y;
return Math.Sqrt(x * x + y * y);
}
public override string ToString()
{
return "(" + x + ", " + y + ")";
}
}
class Triangle
{
Point a;
Point b;
Point c;
#region 初期化
public Triangle(Point a, Point b, Point c)
{
this.a = a;
this.b = b;
this.c = c;
}
#endregion
#region プロパティ
public Point A
{
get { return a; }
set { a = value; }
}
public Point B
{
get { return b; }
set { b = value; }
}
public Point C
{
get { return c; }
set { c = value; }
}
#endregion
public double GetArea()
{
Point ab = b - a;
Point ac = c - a;
return 0.5 * Math.Abs(ab.X * ac.Y - ac.X * ab.Y);
}
public double GetPerimeter()
{
double l = Point.GetDistance(this.a, this.b);
l += Point.GetDistance(this.a, this.c);
l += Point.GetDistance(this.b, this.c);
return l;
}
}
class Class1
{
static void Main()
{
Triangle t = new Triangle(
new Point(0, 0),
new Point(3, 4),
new Point(4, 3));
Console.Write("{0}\n", t.GetArea());
Console.Write("{0}\n", t.GetPerimeter());
}
}
問題1
クラスの問題 1の Triangle
クラスを元に、
以下のような継承構造を持つクラスを作成せよ。
まず、三角形や円等の共通の基底クラスとなる Shape
クラスを以下のように作成。
class Shape
{
virtual public double GetArea() { return 0; }
virtual public double GetPerimeter() { return 0; }
}
そして、Shape
クラスを継承して、
三角形 Triangle
クラスと
円 Circle
クラスを作成。
class Triangle : Shape
class Circle : Shape
using System;
struct Point
{
double x;
double y;
#region 初期化
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
#endregion
#region プロパティ
public double X
{
get { return this.x; }
set { this.x = value; }
}
public double Y
{
get { return this.y; }
set { this.y = value; }
}
#endregion
#region 演算子
public static Point operator +(Point a, Point b)
{
return new Point(a.x + b.x, a.y + b.y);
}
public static Point operator -(Point a, Point b)
{
return new Point(a.x - b.x, a.y - b.y);
}
#endregion
public static double GetDistance(Point a, Point b)
{
double x = a.x - b.x;
double y = a.y - b.y;
return Math.Sqrt(x * x + y * y);
}
public override string ToString()
{
return "(" + x + ", " + y + ")";
}
}
class Shape
{
virtual public double GetArea() { return 0; }
virtual public double GetPerimeter() { return 0; }
}
class Circle : Shape
{
Point center;
double radius;
#region 初期化
public Circle(Point center, double r)
{
this.center = center;
this.radius = r;
}
#endregion
#region プロパティ
public Point Center
{
get { return this.center; }
set { this.center = value; }
}
public double Radius
{
get { return this.radius; }
set { this.radius = value; }
}
#endregion
#region 面積・周
public override double GetArea()
{
return Math.PI * this.radius * this.radius;
}
public override double GetPerimeter()
{
return 2 * Math.PI * this.radius;
}
#endregion
public override string ToString()
{
return string.Format(
"Circle (c = {0}, r = {1})",
this.center, this.radius);
}
}
class Triangle : Shape
{
Point a;
Point b;
Point c;
#region 初期化
public Triangle(Point a, Point b, Point c)
{
this.a = a;
this.b = b;
this.c = c;
}
#endregion
#region プロパティ
public Point A
{
get { return a; }
set { a = value; }
}
public Point B
{
get { return b; }
set { b = value; }
}
public Point C
{
get { return c; }
set { c = value; }
}
#endregion
#region 面積・周
public override double GetArea()
{
Point ab = b - a;
Point ac = c - a;
return 0.5 * Math.Abs(ab.X * ac.Y - ac.X * ab.Y);
}
public override double GetPerimeter()
{
double l = Point.GetDistance(this.a, this.b);
l += Point.GetDistance(this.a, this.c);
l += Point.GetDistance(this.b, this.c);
return l;
}
#endregion
public override string ToString()
{
return string.Format(
"Circle (a = {0}, b = {1}, c = {2})",
this.a, this.b, this.c);
}
}
class Class1
{
static void Main()
{
Triangle t = new Triangle(
new Point(0, 0),
new Point(3, 4),
new Point(4, 3));
Circle c = new Circle(
new Point(0, 0), 3);
Show(t);
Show(c);
}
static void Show(Shape f)
{
Console.Write("{0}\n", f);
Console.Write("{0}\n", f.GetArea());
Console.Write("{0}\n", f.GetPerimeter());
}
}
問題1
多態性の問題 1の Shape
クラスを抽象クラス化せよ。
必要な箇所(Shape クラスの部分)だけ抜粋。
abstract class Shape
{
public abstract double GetArea();
public abstract double GetPerimeter();
}
問題1
多態性の問題 1の Shape
クラスをインターフェース化せよ。
Triangle
や Shape
関係の例題は一応、これで完成形。
余力があれば、楕円、長方形、平行四辺形、(任意の頂点の)多角形等、さまざまな図形クラスを作成せよ。
また、これらの図形の面積と周の比を計算するプログラムを作成せよ。
三角形、円に加え、多角形を実装した物を示します。
using System;
struct Point
{
double x;
double y;
#region 初期化
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
#endregion
#region プロパティ
public double X
{
get { return this.x; }
set { this.x = value; }
}
public double Y
{
get { return this.y; }
set { this.y = value; }
}
#endregion
#region 演算子
public static Point operator +(Point a, Point b)
{
return new Point(a.x + b.x, a.y + b.y);
}
public static Point operator -(Point a, Point b)
{
return new Point(a.x - b.x, a.y - b.y);
}
#endregion
public static double GetDistance(Point a, Point b)
{
double x = a.x - b.x;
double y = a.y - b.y;
return Math.Sqrt(x * x + y * y);
}
public override string ToString()
{
return "(" + x + ", " + y + ")";
}
}
interface Shape
{
double GetArea();
double GetPerimeter();
}
class Circle : Shape
{
Point center;
double radius;
#region 初期化
public Circle(Point center, double r)
{
this.center = center;
this.radius = r;
}
#endregion
#region プロパティ
public Point Center
{
get { return this.center; }
set { this.center = value; }
}
public double Radius
{
get { return this.radius; }
set { this.radius = value; }
}
#endregion
#region 面積・周
public double GetArea()
{
return Math.PI * this.radius * this.radius;
}
public double GetPerimeter()
{
return 2 * Math.PI * this.radius;
}
#endregion
public override string ToString()
{
return string.Format(
"Circle (c = {0}, r = {1})",
this.center, this.radius);
}
}
class Triangle : Shape
{
Point a;
Point b;
Point c;
#region 初期化
public Triangle(Point a, Point b, Point c)
{
this.a = a;
this.b = b;
this.c = c;
}
#endregion
#region プロパティ
public Point A
{
get { return a; }
set { a = value; }
}
public Point B
{
get { return b; }
set { b = value; }
}
public Point C
{
get { return c; }
set { c = value; }
}
#endregion
#region 面積・周
public double GetArea()
{
Point ab = b - a;
Point ac = c - a;
return 0.5 * Math.Abs(ab.X * ac.Y - ac.X * ab.Y);
}
public double GetPerimeter()
{
double l = Point.GetDistance(this.a, this.b);
l += Point.GetDistance(this.a, this.c);
l += Point.GetDistance(this.b, this.c);
return l;
}
#endregion
public override string ToString()
{
return string.Format(
"Circle (a = {0}, b = {1}, c = {2})",
this.a, this.b, this.c);
}
}
class Polygon : Shape
{
Point[] verteces;
#region 初期化
public Polygon(params Point[] verteces)
{
this.verteces = verteces;
}
#endregion
#region プロパティ
public Point[] Verteces
{
get { return this.verteces; }
set { this.verteces = value; }
}
#endregion
#region 面積・周
public double GetArea()
{
double area = 0;
Point p = this.verteces[this.verteces.Length - 1];
for (int i = 0; i < this.verteces.Length; ++i)
{
Point q = this.verteces[i];
area += p.X * q.Y - q.X * p.Y;
p = q;
}
return 0.5 * Math.Abs(area);
}
public double GetPerimeter()
{
double perimeter = 0;
Point p = this.verteces[this.verteces.Length - 1];
for (int i = 0; i < this.verteces.Length; ++i)
{
Point q = this.verteces[i];
perimeter += Point.GetDistance(p, q);
p = q;
}
return perimeter;
}
#endregion
public override string ToString()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.AppendFormat("Polygon ({0}", this.verteces[0]);
for (int i = 1; i < this.verteces.Length; ++i)
{
sb.AppendFormat(", {0}", this.verteces[i]);
}
sb.Append(")");
return sb.ToString();
}
}
class Class1
{
static void Main()
{
Triangle t = new Triangle(
new Point(0, 0),
new Point(3, 4),
new Point(4, 3));
Circle c = new Circle(
new Point(0, 0), 3);
Polygon p1 = new Polygon(
new Point(0, 0),
new Point(3, 4),
new Point(4, 3));
Polygon p2 = new Polygon(
new Point(0, 0),
new Point(0, 2),
new Point(2, 2),
new Point(2, 0));
Show(t);
Show(c);
Show(p1);
Show(p2);
}
static void Show(Shape f)
{
Console.Write("図形 {0}\n", f);
Console.Write("面積/周 = {0}\n", f.GetArea() / f.GetPerimeter());
}
}