【C#】抽象クラスで購入する宝くじの銘柄と当選確率を(？)広げてみよう

# 1.はじめに

前回は、インターフェースを体感してみた。
ロト６、たまにロト７と購入するもまだまだ高額当選の道は長い。
一攫千金を狙っているため、小さい勝負に拘るのは好きではない。
しかしながらそんなことを言っている状況でもないため、他の数字系のクジについても調べることにした。
ナンバーズでは、ボックス、ストレート、セットという組み合わせがあるらしい。
今回は今までのloto6,loto7に加えてnumbers4,numbers3にも枠を広げてみることにした。

インターフェースもいいかもしれないが、自由度が欲しい。
宝くじ購入の共通手順は下記のようになる

`1.銘柄と購入方法を選ぶ`
`2.銘柄に応じた数字を選ぶ`
(~~自己選択は入力チェックが面倒くさい~~今回はQPで購入することにしている。)
`3.代金を支払う`

手順2は、ナンバーズかロトかで、数字の選び方が異なる。
この場所に柔軟性を持たせたい。　
今後、 __別の宝くじに望みを託す場合__ も出てくることを考えると、
 __インターフェースでは厳しい__ のではないか。
そこで抽象クラスというものを考えることにした。

# 2.よくある抽象クラスの例
抽象クラス：動物クラス(abs_animal)
+ 名前
+ 挨拶メソッド

上記の機能を持つ猫クラス(cat)、犬クラス(dog)
```c#:program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Console_animal
{
 internal class Program
 {
  public static void Main(string[] args)
  {
   dog dog1=new dog();
   dog1.Name = "米津玄師";
   dog1.greeting();
   cat cat1=new cat();
   cat1.Name = "橋本環奈";
   cat1.greeting();
  }
 }
}

```
__動物クラス__

```c#:abs_animal.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Console_animal
{
 abstract class abs_animal
 {
  private string _name;
  public string Name { 
   get { return _name; } 
   set { _name = value; }
  }
  public abstract void greeting();
 }
}

```
__猫クラス__

```c#:cat.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Console_animal
{
 internal class cat:abs_animal
 {
  public override void greeting()
  {
   Console.WriteLine(Name+"だけどニャンか用？");
  }
 }
}

```
__犬クラス__
```c#:dog.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Console_animal
{
 internal class dog : abs_animal
 {
  public override void greeting()
  {
   Console.WriteLine(Name + "てつくづくナンバーワン！");
  }
 }
}

```
上記の実行結果は
__米津玄師てつくづくナンバーワン！__
__橋本環奈だけどニャンか用？__
という寒いものである。
### 「だから何？？こんなの作る必要なくね？？？」
というほど、 __効果がイメージしずらいもの__ である。
そこで以下の項目では、自分でもわかりやすくなるように
抽象クラスの性質をまとめてみた。

# 3.抽象クラスに関するメモ
## 3-1.抽象クラスの宣言
抽象クラスは下記のようにして宣言する。

__`abstract`__ `class 抽象クラス名`
`{`
` フィールド`
` プロパティ`
` ` __`abstract`__  `メソッド()`
`}`

__抽象クラスの特徴__
+ メソッドの前に abstractをつける
+ メソッド名を宣言するだけで処理は一切記述しない

抽象クラスで宣言されているメソッドは、利用先で
処理を定義する。

## 3-2.抽象クラスを利用するには

__`class 利用クラス名:抽象クラス名`__
`{`
` ` __`override`__  `メソッド1()`
` //やりたい処理を書く`
` ` __`override`__  `メソッド2()`
` //やりたい処理を書く`
`}`


## 3-3.抽象クラスとインターフェースのイメージ
勝手なイメージをしてみた。
__`インターフェース：`__ __事業仕分けなどをして仕切る人。__
（全体から用途に合わせて一部の機能を使うところから）
「2番じゃだめですか？」のパワーワードが光る。
__`抽象クラス：`__　__「聴く力」を強調する人。__
（このクラスにあるメソッドを実装先クラスで、 __好き放題の内容を再定義__ できることから）


__※この記事は、特定の人を攻撃するものでもなく、ギャンブルを推奨するものではありません。__


# 4.ソース例
## 4-1.くじの種類の入力
```c#:program0.cs
using Console_kuji;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Console_kuji
{
 class Program0
 {

  //入力文字列のチェック
  public static Boolean Check_input(string s0, int opnum = 0)
  {
   int type0;
   //入力文字列が数字以外の時
   if (int.TryParse(s0, out type0) == false)
    return true;

   type0 = int.Parse(s0);
   //銘柄選択(0:loto6,1:loto7,2:numbers4,3:numbers3)
   if (opnum == 0)
    return (type0 > 3 || type0 < 0) ? true : false;

   //ナンバーズの場合
   //購入タイプ選択(1:ストレート,2:セット,3:ボックス)
   if (opnum == 1)
    return (type0 > 3 || type0 < 1) ? 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("銘柄を選択してください(ロト6:0,ロト7:1,ナンバーズ3:2,ナンバーズ4:3)");
   s1 = Console.ReadLine();

   if (Check_input(s1) == true )
   {
    Console.WriteLine("不正な値です");
    return;
   }

   type0 = int.Parse(s1);
   type2 = 0;
   if (type0 > 1)
   {
    Console.WriteLine("ストレートは1,セットは2,ボックスは3で指定してください");
    s2 = Console.ReadLine();
    if (Check_input(s2,1) == true)
    {
     Console.WriteLine("不正な値です");
     return;
    }
    type2 = int.Parse(s2);
   }

   Console.WriteLine("購入本数");
   s3 = Console.ReadLine();
   if(Check_input(s3,2) == true )
   {
    Console.WriteLine("不正な値です");
    return;
   }

   n = int.Parse(s3);

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

    retname = (type0 == 0) ? "ロト6" : "ロト7";
    Loto lt = new Loto();
    lt.Name = retname;
    lt.Type0 = rettype;
    lt.Num = n;
    lt.Price = price0;
    lt.Max = nmax;

    lt.Buyqp();
    lt.PrintTotalAmount();
   }
   else
   {
    //ナンバーズの銘柄
    rettype = (type0 == 2) ? 3 : 4;
    retname = (type0 == 2) ? "ナンバーズ3" : "ナンバーズ4";
    if (type2 == 1)
     retname = retname + "(ストレート)";
    if (type2 == 2)
     retname = retname + "(セット)";
    if (type2 == 3)
     retname = retname + "(ボックス)";

    Kuji_numbers kuji_nbs = new Kuji_numbers();
    kuji_nbs.Type0 = rettype;
    kuji_nbs.Type_qp = type2;
    //くじ番号の最大値
    kuji_nbs.Max = 9;
    kuji_nbs.Num = n;
    //一本当たりの金額
    kuji_nbs.Price = 200;
    kuji_nbs.Name = retname;
    
    kuji_nbs.Buyqp();
    kuji_nbs.PrintTotalAmount();
   }
  }
 }

}

```
## 4-2.くじ抽象クラス

```c#:abs_kuji.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Console_kuji
{
 abstract class abs_kuji
 {
  //銘柄
  private int _type0;
  public int Type0
  {
   get { return _type0; }
   set { _type0 = value; }
  }
  //購入タイプ
  private int _type_qp;
  public int Type_qp { 
   get { return _type_qp; }
   set { _type_qp = value; }
  }
  //銘柄名
  private string _name;
  public string Name
  {
   get { return _name; }
   set { _name = value; }
  }
  //1本当たりの価格
  private int _price;
  public int Price
  {
   get { return _price; }
   set { _price = value; }
  }
  //購入本数
  private int _num;
  public int Num
  {
   get { return _num; }
   set { _num = value; }
  }

  //最大値
  private int _max;
  public int Max
  {
   get { return  _max; }
   set { _max = value; }
  }
  //QPで買う
  public abstract void Buyqp();
  //購入金額と意気込みを表示
  public abstract void PrintTotalAmount();
 }
}

```
## 4-3.ナンバーズQPクラス
```Kuji_numbers.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Console_kuji
{
 internal class Kuji_numbers:abs_kuji

 {
  public override void Buyqp()
  {
   Random rand = new Random();
   int nn;
   //可変配列
   List<string> ret_list = new List<string>();

   for (int i = 0; i < Num; i++)
   {
    List<int> lotoqp_list = new List<int>();

    int[] tmparr = new int[Type0];

    for (int j = 0; j < Type0; j++)
    {
     nn = rand.Next(Max);
     tmparr[j] = nn+1;
    }
    ret_list.Add(string.Join(",", tmparr));
   }

   for (int i = 0; i < Num; i++)
   {
    if (Type_qp == 1)
     Console.WriteLine(Name + ": " + (i + 1) + "回目:" + ret_list[i].Replace(",",""));
    if (Type_qp == 2)
    {
     Console.WriteLine(Name + ": " + (i + 1) + "回目:" + ret_list[i].Replace(",", ""));
     Console.WriteLine(Name + ": " + (i + 1) + "回目:順番関係なく右記数字の組み合わせ" + ret_list[i]);
     Console.WriteLine("上の数字の組み合わせの2種類で勝負！！");
    }
    if (Type_qp == 3)
     Console.WriteLine(Name + ": " + (i + 1) + "回目:順番関係なく右記数字の組み合わせ" + ret_list[i]);
   }

  }

  public override void PrintTotalAmount()
  {
   int total = 0;
   total = Num * Price;
   Console.WriteLine("******************************");
   Console.WriteLine(total);
   if(Type_qp==1)
    Console.WriteLine(Name + "で勝負師で行く！！");
   if (Type_qp == 2)
    Console.WriteLine(Name + "で良いとこ取りで行く！！");
   if (Type_qp == 3)
    Console.WriteLine(Name + "で確率をあげる！！これで外したら、ぴえん超えてぱおん！！");
  }
 }
}
```
## 4-4.ロトQPクラス
```Loto.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Console_kuji
{
 internal class Loto : abs_kuji
 {
  public override void Buyqp()
  {

   Random rand = new Random();
   int nn;
   //可変配列
   List<string> ret_list = new List<string>();

   for (int i = 0; i < Num; i++)
   {
    List<int> lotoqp_list = new List<int>();
    for (int j = 1; j <= Max; j++)
    {
     lotoqp_list.Add(j);
    }
    int[] tmparr = new int[Type0];

    for (int j = 0; j < Type0; j++)
    {
     nn = rand.Next(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 < Num; i++)
    Console.WriteLine(Name + ": " + (i + 1) + "回目:" + ret_list[i]);
  }

  public override void PrintTotalAmount()
  {
   int total = 0;
   total = Num * Price;
   Console.WriteLine("******************************");
   Console.WriteLine(total);
   Console.WriteLine(Name+"で一攫千金しか勝たん！！");
  }
 }
}

```
# 5.実行結果

## 5-1.ロト7

![console_kuji2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689780/2ac2d011-f9bb-f920-f58d-1fdb918997c6.jpeg)

## 5-2.ナンバーズ4でボックス

![console_kuji3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689780/75612a5a-a99b-dd0a-6fc5-50596f7ba404.jpeg)

# 6.最後に

何とか、ロト以外の銘柄での購入に成功した。
わけのわからない動物クラスでは、得られなかった
「抽象クラスが使えている感覚」を得る事ができた。
そして、この記事を見た人に「幸運が訪れる」事を　__少し__ 願っている。