0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【C#】ロト購入でインターフェースを体感してみた

Last updated at Posted at 2024-09-06

1.はじめに

色々あったというか転職先で必要になったため、C#の勉強を開始した。
時々見かける、メソッドのみが羅列されている謎のクラス、インターフェース。
今回の目的は、インターフェースとは何かを体感することにしている。

2.インターフェースって何?

インターフェースについてC#入門の本で調べてみた。

  • 親クラスからのメソッドは宣言のみで、フィールドを生成することはできない。
  • 抽象クラスと同じように、インスタンスを生成できない
  • 抽象クラスの概念をさらに推し進めたもの
  • 呼び出すときは、親クラスをインターフェースでキャストして使うことができる

箇条書きの3つ目が気になる。
抽象クラスを誇張したもの?ザコシショウか?⇒結論、そういう意味ではなかった。

下記のような感じで作るらしい。
interface インターフェース名
{
親クラスのメソッド1(引数)
親クラスのメソッド2(引数)
}

わかんない。イマイチわからないのだ。
例を見てもよくわからない。
何で、わざわざ親クラスの一部のメソッドだけ宣言しているのか。

親クラスの一部の機能だけしか、使わない場合ってあるのか?
色々かんがえたところ、

日頃からお世話になっている (当たらないので課金を続けている) Lotoの購入で使えそうかも
と気が付いた。

3.ロトの購入について

3-1.ロトの購入処理手順

ここでロトを購入するときの処理内容を考える。
1.購入するとき、ロト6やロト7という銘柄を決める。
2.購入の仕方も「自分で番号を決めて購入」か「クイックピック」がある。
(厳密にいえば、半分ランダム、半分自己選択という混合型もあるが(クラス名:キューピーハーフ)、
今回は、全番号自己選択 or クイックピックで考える)
※キューピーハーフクラスは、某会社の商品名ともかぶるし今回は作成しない。
全番号クイックピックを指定した時、自分で番号を選択することができない。
番号選択の時は、全番号クイックピックを使うことができない。

(a)クイックピック
ロト6の場合は、1~43までの数字6つがランダムに選ばれる方式
ロト7の場合は1~37までの数字7つがランダムに選ばれる方式。

(b)自分で数字選択
自分で数字を決めて入力する方式。
数字の入力回数は、ロト6では購入本数6、ロト7では購入本数7とする。

3.購入本数分の金額を払う。
(ロト6は一本200円、ロト7は一本300円)

3-2.ロト関連クラスについて

(1)ロトクラス

ロトクラス:自己番号選択インターフェース,クイックピックインターフェース
{
銘柄(ロト6かロト7か)
表示名
購入方法(クリックピックか自己選択か)
最大数値
購入本数
価格
自己選択関連メソッド
クイックピック関連メソッド
購入金額計算メソッド
}

(2)自己番号選択インターフェース

自己番号選択インターフェース
{
自己選択関連メソッド
購入金額計算メソッド
}

(3)クイックピックインターフェース

クイックピックインターフェース
{
クイックピック関連メソッド
購入金額計算メソッド
}

実行環境:Windows 10 home
visual studio 2022

4.実行画面

4-1.ロト6をクイックピックで購入

image.png

4-2.ロト7を数字を選択して購入

image.png

5.ソース

5-1.購入の選択

(1)loto6かloto7か
loto6を購入する場合は0を、loto7を購入したい場合は1を入力

(2)購入方式
クイックピック:0
自己選択:1
自己選択式の場合、以下の制限が必要になる。
1)ロト6では1~43までの数字
ロト7では1~37までの数字までしか購入できない。
2)1組の購入数字内に、同じ数字は選択できない。

(3)購入本数
自己選択なら、3本まで購入可能

Program0.cs
using ConsoleApp_loto;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp_loto
{
 class Program0
 {

  //入力文字列のチェック
  public static Boolean Check_input(string s0, int nmax = 0)
  {
   int type0;
   //入力文字列が数字以外の時
   if (int.TryParse(s0, out type0) == false)
   {
    return true;
   }
   type0 = int.Parse(s0);
   //自己選択型での入力数字
   if (nmax > 2)
   {
    return (type0<1 || type0>nmax) ? true : false;
   }
   //自己選択型の購入本数
   if (nmax == 2)
   {
    return (type0>3 || type0<0) ? true : false;
   }
   //購入タイプ選択
   if (nmax==0)
   {
    return (type0>1 || type0<0) ? true : false;
   }
   //購入タイプQPの整数での本数入力
   return false;
  }

  public static void Main(string[] args)
  {
   int i, j;
   int rettype = 0;
   string retname = "";
   int nmax = 0;
   string s, s1, s2, s3;
   int type0 = 0;
   int type2 = 0;
   int n = 0;
   int price0 = 0;
   string tmpstr0 = "";

   Console.WriteLine("クイックピックの場合は0を、自分で選択する場合は1を入力してください。");
   s1 = Console.ReadLine();

   Console.WriteLine("ロト6は0,ロト7は1を入力してください");
   s2 = Console.ReadLine();

   if (Check_input(s1) == true || Check_input(s2) == true)
   {
    Console.WriteLine("不正な値です");
    return;
   }
   Console.WriteLine("購入本数(自分で選択の場合は3本まで)");
   s3 = Console.ReadLine();

   type0 = int.Parse(s1);
   type2 = int.Parse(s2);
   //ロトの銘柄
   rettype = (type2 == 0) ? 6 : 7;
   //一本当たりの金額
   price0 = (type2 == 0) ? 200 : 300;
   //くじ番号の最大値
   nmax = (type2 == 0) ? 43 : 37;

   //クイックピック
   if (type0 == 0)
   {
    if (Check_input(s3,1) == true)
    {
     Console.WriteLine("不正な値です");
     return;
    }
    n = int.Parse(s3); 

    retname=(type2==0)? "ロト6(QP)": "ロト7(QP)";
    Loto kuji = new Loto();
    kuji.Name = retname;
    kuji.Type1 = rettype;
    kuji.Num1 = n;
    kuji.Price = price0;
    kuji.Loto_max = nmax;

    Iquick_pick ltqp = (Iquick_pick)kuji;
    ltqp.Buyqp();
    ltqp.PrintTotalAmount();
   }
   //自分で選択した場合
   if (type0 == 1)
   {
    if (Check_input(s3, 2) == true)
    {
     Console.WriteLine("不正な値です");
     return;
    }
    n = int.Parse(s3);
    string[] tmpstr1 = new string[n];
    int n2;

    retname = (type2 == 0) ? "ロト6(自己選択)" : "ロト7(自己選択)";
    //n本分の数字を入力
    for (i = 0; i < n; i++)
    {
     List<int> retint_list = new List<int>();
     for (j = 0; j < rettype; j++)
     {
      Console.Write((i + 1) + "回目:" + (j + 1) + "番目(1~" + nmax + ")までを指定 ");
      s = Console.ReadLine();
      if (Check_input(s, nmax) == true)
      {
       Console.WriteLine("不正な値です");
       return;
      }
      n2 = int.Parse(s);
      if (retint_list.Contains(n2) == true)
      {
       Console.WriteLine("同じ値が入力されています");
       return;
      }
      retint_list.Add(n2);
     }
     Console.WriteLine();
     tmpstr1[i] = string.Join(",", retint_list);
     retint_list.Clear();
    }
    tmpstr0 = string.Join(" ", tmpstr1);
    Loto kuji = new Loto();
    kuji.Name = retname;
    kuji.Type1 = rettype;
    kuji.Num1 = n;
    kuji.Mynumbers = tmpstr0;
    kuji.Price = price0;
    kuji.Loto_max = nmax;
    Inumber_select mylt = (Inumber_select)kuji;
    mylt.Buymynum();
    mylt.PrintTotalAmount();
   }
  }
 }
}

ロトクラス

loto.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp_loto
{
 internal class Loto : Inumber_select, Iquick_pick
 {
  private string _name;
  private int _num1;
  private int _type1;
  private string _mynumbers;
  private int _loto_max;
  private int _price;

  public string Name
  {
   set { _name = value; }
   get { return _name; }
  }
  //ロト6やロト7など銘柄を表す数字
  public int Type1
  {
   set { _type1 = value; }
   get { return _type1; }
  }
  //購入本数
  public int Num1
  {
   set { _num1 = value; }
   get { return _num1; }
  }
  //自分で選択した数字を連結した文字列
  public string Mynumbers
  {
   set { _mynumbers = value; }
   get { return _mynumbers; }
  }

  //選択する最大値
  public int Loto_max
  {
   set { _loto_max = value; }
   get { return _loto_max; }
  }

  //一本当たりの価格
  public int Price
  {
   set { _price = value; }
   get { return _price; }
  }

  //クイックピックで購入
  public void Buyqp()
  {
   Random rand = new Random();
   int nn;
   //可変配列
   List<string> ret_list = new List<string>();

   for (int i = 0; i < _num1; i++)
   {
    List<int> lotoqp_list = new List<int>();
    for (int j = 1; j <= _loto_max; j++)
    {
     lotoqp_list.Add(j);
    }
    int[] tmparr = new int[_type1];

    for (int j = 0; j < _type1; j++)
    {
     nn = rand.Next(_loto_max - j);
     tmparr[j] = lotoqp_list[nn];
     lotoqp_list.RemoveAt(nn);
    }
    ret_list.Add(string.Join(",", tmparr));
    lotoqp_list.Clear();
   }

   for (int i = 0; i < _num1; i++)
    Console.WriteLine(_name + ": " + (i + 1) + "回目:" + ret_list[i]);
  }


  //合計金額表示
  public void PrintTotalAmount()
  {

   int total = 0;
   total = _price * _num1;
   Console.WriteLine("購入金額は" + total + "です");
  }

  public void Buymynum()
  {
   string[] tmpstr3 = new string[_num1];
   tmpstr3 = _mynumbers.Split(" ");
   int i, j;

   for (i = 0; i < _num1; i++)
    Console.WriteLine(_name + ":" + (i + 1) + "回目:" + tmpstr3[i]);
  }
 }
}


自己選択式

  • 購入数分の選択した数字を表示
  • 購入金額を表示
Inumber_select.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp_loto
{
 internal interface Inumber_select
 {
  void Buymynum();
  void PrintTotalAmount();
 }
}

クイックピッククラス

  • クイックピック方式の数字を表示
  • 購入金額を表示
Iquick_pick.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp_loto
{
 internal interface Iquick_pick
 {
  void Buyqp();
  void PrintTotalAmount();
 }
}

6.気になったこと

インターフェースについては体感できた。
それよりも地味に大変なことがあった。
入力文字列のチェックだ。
if,elseという判定文だ。
簡単なif文で4行書くことになる ⇒これ!!!
{カッコだけで1行使うのだ。
しかも、対になるカッコも必要なのだ。)
行数削減のため、3項演算子を駆使したのだ。

7.インターフェースのメリット

改めてインターフェースについて考えてみた。
2つの共通点が多いが一部の処理が違うクラスを作りたいとする。
そんな時いちいちコピペして、クラスを作るのは効率が悪い。
さらに何かあったときに、 [例えば2つのクラスに共通する処理を変更するときは親クラスだけ変更] できた方が良い。
全体のコード量も削減できる。

メソッドのみが羅列されている謎のクラスのメリットだったのだ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?