😇

【bun】乱数だけで運命が決まる鬼畜マッチングストーリーアプリ作成😧

2024/06/08に公開2

はじめに

どうも、恋愛経験ほぼ0のてるし〜です😭
今回は友人のふざけた発想から鬼畜マッチングストーリーアプリを作りましたのでその紹介をしますw

面白いと周りから好評だったので紹介します。

アルゴリズムなど学べるところはありプログラミングの処理の発想の勉強になるかなと思います。

よかったら最後までゆっくりしていってください。

対象とする人たち

流石に現実の人たちでやるのはちょっとアレなのでアニメのキャラクタ達をミックスして作りました。

作品

作品としては2作品です。

  • かぐや様は告らせたい
  • やはり、俺の青春ラブコメはまちがっている(俺ガイル)

https://kaguya.love/
https://www.tbs.co.jp/anime/oregairu/

登場人物

それでは登場人物を見ていきましょう!

男性陣

  • 八幡(俺ガイル)
  • 戸塚(俺ガイル)
  • しろがね(かぐや様)
  • 石上(かぐや様)
  • 材木座(俺ガイル)
  • 戸部(俺ガイル)
  • 葉山(俺ガイル)

女性陣

  • かぐや(かぐや様)
  • 雪ノ下(俺ガイル)
  • 由比ヶ浜(俺ガイル)
  • 藤原千花(かぐや様)
  • 一色(俺ガイル)
  • 早坂(かぐや様)
  • イイノ(かぐや様)

実行の結果

実行の結果の一例です。乱数を使っているので毎回結果が変わります。

マッチング1回目
しろがねは藤原千花にアタックしました。
藤原千花はしろがねを好きになりました。
よって2人は付き合いました。

マッチング2回目
石上は一色にアタックしました。
一色は石上を好きになりました。
よって2人は付き合いました。

マッチング3回目
材木座はイイノにアタックしました。
イイノは材木座を好きになりました。
よって2人は付き合いました。

マッチング4回目
戸塚はかぐやにアタックしました。
かぐやは戸塚を好きになりました。
よって2人は付き合いました。

マッチング5回目
葉山は由比ヶ浜にアタックしました。
由比ヶ浜は葉山を好きになりました。
よって2人は付き合いました。

マッチング6回目
八幡は一色にアタックしました。
一色は八幡のアプローチに負けて付き合うことになりました。
石上は一色とお別れしました。

マッチング7回目
戸部は由比ヶ浜にアタックしました。
由比ヶ浜は戸部のアプローチに負けて付き合うことになりました。
葉山は由比ヶ浜とお別れしました。

マッチング8回目
石上は由比ヶ浜にアタックしました。
由比ヶ浜は戸部とラブラブなため断られてしまいました。
石上は由比ヶ浜を諦めました


マッチング9回目
石上は早坂にアタックしました。
早坂は石上を好きになりました。
よって2人は付き合いました。

マッチング10回目
葉山はかぐやにアタックしました。
かぐやは葉山のアプローチに負けて付き合うことになりました。
戸塚はかぐやとお別れしました。

マッチング11回目
戸塚は雪ノ下にアタックしました。
雪ノ下は戸塚を好きになれませんでした。
よって2人はお付き合いしませんでした。

マッチング12回目
戸塚はイイノにアタックしました。
イイノは戸塚のアプローチに負けて付き合うことになりました。
材木座はイイノとお別れしました。

マッチング13回目
材木座は雪ノ下にアタックしました。
雪ノ下は材木座を好きになりました。
よって2人は付き合いました。

マッチング14回目
終了しました
八幡は一色とくっつきました。
戸塚はイイノとくっつきました。
しろがねは藤原千花とくっつきました。
石上は早坂とくっつきました。
材木座は雪ノ下とくっつきました。
戸部は由比ヶ浜とくっつきました。
葉山はかぐやとくっつきました。

あくまでもプログラムミングの中での世界ですが、場合によっては誰かが尻軽女になったり一途な男が出てきたりと展開的に面白なることもあるので個人的には面白いかなと思いますが、現実で起こると、、、🥹

使用技術

恋愛の話は一旦ここまでにして、技術の話に入っていきましょう。

まずは使用技術についてです。以下のものを使いました。

  • bun
  • typescript

https://bun.sh/

bunは実行速度が爆速らしいですね。まだ自分の中では実感が湧いていないのですが、実際にexpressでサーバーを作るとなると肌感で分かるのでしょうかね?

ちなみにソースコードをgithubに記載してます。

https://github.com/ShionTerunaga/matching-app-for-animes

データについて

上記githubを見てもらうと分かると思いますが、人材のデータはsrc/people.tsに入っています。

型定義

typescriptなのでオブジェクトに型定義をしています。

people.ts
export type person = {
    name: string
    pair: number
    matchProbability: number
    pairProbability: number[]
}
key 説明 初期値 補足
name string 各人物の名前 - -
pair number パートナーの番号 -1 配列のindexがここに格納される。いない場合は-1
matchProbability number パートナーがいる人が乗り換えるかどうかの基準値 0 0~1の数値を使う。パートナーがいた場合はこの基準値を使う
pairProbability numberの配列 パートナーがいない場合の付き合うかどうかの基準値 全て0の配列 0~1の数値を使う。ペアがいない女性で付き合えるかどうかの基準値をここに示す。また、これは女性のみの基準値が使用される

初期データ

初期データを示します。
まずは男性陣から!

people.ts
export const men: person[] = [
    {
        name: "八幡",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "戸塚",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "しろがね",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "石上",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "材木座",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "戸部",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "葉山",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    }
]

次に女性陣!

people.ts
export const women: person[] = [
    {
        name: "かぐや",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "雪ノ下",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "由比ヶ浜",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "藤原千花",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "一色",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "早坂",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    },
    {
        name: "イイノ",
        pair: -1,
        matchProbability: 0,
        pairProbability: [0, 0, 0, 0, 0, 0, 0]
    }
]

アルゴリズム

今回は全体のソースコードは載せません。
要所要所でコードを書きますが、全体を見渡したい人はgithubを参照してください。

初期設定アルゴリズム

初期設定のアルゴリズムを紹介します。
ここは単純なソースなので、ファイル毎ソースコードを記載してしまします。

init.ts
import { women } from "./people"

//初期化処理
export const init = () => {
    for (let i = 0; i < women.length; i++) {
        for (let j = 0; j < women[i].pairProbability.length; j++) {
            const randomNum = Math.random()
            women[i].pairProbability[j] = randomNum
        }
    }
}

基本的に初期設定をするのは女性陣なので女性のデータを使用します。
forを使って女性の人数ぶん回しその中のネストのforで各男性の基準を乱数で算出してオブジェクトに格納しています。

メインのアルゴリズム

それでは全体のアルゴリズムを見ていきましょう。

アルゴリズム

1. 初期設定した関数を呼び出す
2. 以下の試行を50回繰り返す
3. 全ての人がマッチした、もしくは50回になった場合、プログラム終了
4. 乱数で対象の男性を決める
5. 乱数でアタック対象の女性を決める
6. 乱数でアタック値を算出しておく
7. アタック対象の女性にペアがいなかった場合は以下 a,b の処理のいずれかを行う
    a. アタック値が基準値(pairProbability)を超えた場合は付き合うことができる
        a1. pairにそれぞれ異性の対象のindexを代入
        a2. matchProbabilityにアタック値を代入
    b. アタック値が基準値を超えない場合は付き合うことができない
8. アタック対象に女性ペアがいる場合は以下の a,b の処理のいずれかを行う
    a. アタック値が基準値(matchProbability)を超えた場合は付き合うことができる
        a1. pairにそれぞれ異性の対象のindexを代入
        a2. matchProbabilityにアタック値を代入
        a3. もともとその女性と付き合っていた男性のpairを-1にする
        a3. もともとその女性と付き合っていた男性のmatchProbabilityを0にする
    b. アタック値が基準値を超えない場合は付き合うことができない

部分部分をコードで

2つほどアルゴリズムをコードで表現してみようと思います。

3. 全ての人がマッチした、もしくは50回になった場合、プログラム終了

ここの部分をソースコードで表してみます。

main.ts
count++

let singleNum: number = 0

console.log(`マッチング${count}回目`)

        
men.forEach((item) => {
    if (item.pair === -1) singleNum++
})

if (singleNum === 0 || count === 50) {
    console.log("終了しました")

    men.forEach((item) => {
        if (item.pair === -1) {
            console.log(`${item.name}はマッチできませんでした`)
        } else {
            console.log(
                `${item.name}${women[item.pair].name}とくっつきました。`
            )
        }
    })

    return
}

簡単に説明するとマッチしていない女性がいたらsingleNumにどんどん加算していき
終了条件としてsingleNumが0または試行回数が50の時にそこの条件に入るようにプログラムします。
実際のifの中では結果の算出を出しています。

a. アタック値が基準値(matchProbability)を超えた場合は付き合うことができる

では次にこちらのアルゴリズムをソースコードで表現してみましょう。

main.ts
if (women[womenRandom].matchProbability > attackProbability) {
    console.log(`${women[womenRandom].name}${men[menRandom].name}のアプローチに負けて付き合うことになりました。`)
    console.log(`${men[women[womenRandom].pair].name}${women[womenRandom].name}とお別れしました。\n`)

    men[menRandom].pair = womenRandom
    men[menRandom].matchProbability = attackProbability

    men[women[womenRandom].pair].pair = -1
    men[women[womenRandom].pair].matchProbability = 0

    women[womenRandom].pair = menRandom
    women[womenRandom].matchProbability = attackProbability
} else {
...以下略
}

「恋愛というのは残酷な時もあるもので、他の人に乗り換えてしまうこともありますよね、、、(う、う、びえーーん😭)」という状況ををプログラムで書いています。

乱数を算出してifの条件で「アタック値が基準値を超えたら」ということをしていますね。

ログを出したあとに付き合ったカップルはpairmatchProbabilityの設定、残念ながら別れてしまった男性は初期値を戻すということをしています。

その他の処理

その他の処理はgithubのソースコードで確認してください!

まとめ

いかがでしたでしょうか?
恋愛経験0の自分でも結構面白い内容だったかなと思いますw
乱数を使っているので次実行した時には別の結果になります。

恋愛の話は置いておいてループや条件分岐、配列についてなどなどプログラミングの基礎やJS/TSの基礎が盛り込まれたものになっているので初心者の方が「何か作りたい!」という場合にお勧めします。

今度このプログラムに結婚チャンスを盛り込もうかな....

ということは置いておいて
今回も読んでいただきありがとうございます!

ではまた👋

Discussion