質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Generics

Genericsはパラメトリックなポリモーフィズムの形態であり、.NET やJavaなど、様々な言語に実装されています。C++のテンプレートと同等の機能を持ち合わせています。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

Q&A

2回答

1798閲覧

[Unity][C#][Linq]クラフトシステムで素材ベースから絞り込む手法について

koz555

総合スコア5

Generics

Genericsはパラメトリックなポリモーフィズムの形態であり、.NET やJavaなど、様々な言語に実装されています。C++のテンプレートと同等の機能を持ち合わせています。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

0グッド

0クリップ

投稿2022/04/01 09:55

編集2022/04/01 09:58

お世話になっております。
Unity2021+C#+RPGフレームワークのクラフトシステムで、OverCook2のような料理ゲームを作っています。
素材ベースから絞り込んだレシピを組み立てる手法について分からないので相談させてください。

クラフトシステムにはレシピがあります。
レシピには素材のリストがあります。

C#

1List<Item> ingredientsList = recipe.ingredientsList 2Item outcomeItem = recipe.outcome

といった形です。

レシピから素材が足りているかをチェックし、足りていればクラフトするという、レシピベースのクラフトは普通に可能です。
しかし、皿には先に素材から乗せていきます。
素材を起点として、作れるレシピを絞り込んで、足りた時点で自動でクラフトするという手法がうまく実現出来ず悩んでいます。

たとえばこのようなレシピがあるとします。

recipeoutcomeingredient
cca,b
ddc,e
ggd,f

dから見るとaはcの材料なので、aやbは孫材料と呼ぶとします。
おなじくdから見てcやeは子材料と呼ぶとします。

そこで、皿に最初にfを入れた場合、全レシピから

C#

1List<recipe> allRecipeList.Where(x => x.ingredientsList.name == f.name)

でレシピはgのみに絞り込めるので、次に入れられる材料が確定し、dを持てばrecipe.useでクラフト可能です。
しかし、ここでdではなく孫材料であるaが皿に入った時、孫材料である、という判別のしかたが分かりません。
さらに、可能性のある対象レシピの子材料でも孫材料でもないものは皿に入れられないように弾きたいです。

また、f->aと皿に入れた後に、次に受け入れ可能なのはbとdとeのみに制限したい(cは既に孫材料であるaが皿にあるため持てない)という仕様にしたいのですが、
その実現方法が分かりません。
f,a,dが皿に入った場合は、次に受け入れ可能なのはbのみです。
つまり、孫材料が皿に入っている場合は、子材料は弾きたいという事です。

recipeoutcomeingredient
かけうどんかけうどん茹でたうどん,かけスープ
わかめうどんわかめうどんかけうどん,わかめ
わかめエビうどんわかめエビうどんわかめうどん,エビ

の場合、エビと茹でたうどんが皿にある場合は、かけうどんは(茹でたうどんが既に皿にあるため)持てないようにしたいという事です。

このような挙動を解決したい場合、どのような手法でググればよいかなどが分かりません。
何かパターン名や再帰、LinqのSelectManyやGroupBy、集合などで解決出来そうな気はしているのですが、あちらが解決すればこちらが実現出来ないなどで
グルグルと混乱してしまい悩んでいます。

どなたか解決方法を教えていただけないでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

素材を起点として、作れるレシピを絞り込んで、足りた時点で自動でクラフトする

普通の(Unity 固有のものではない)「プログラミング」の問題だと思います。なので Unity ではない普通のプログラムを示します。

実行環境も示しておきます。

csharp

1using System; 2using System.Collections.Generic; 3using System.Linq; 4 5class Program 6{ 7 public static void Main(string[] args) 8 { 9 Recipe[] recipes = { new Recipe("c", new string[]{ "a", "b"}), 10 new Recipe("d", new string[]{ "c", "e"}), 11 new Recipe("g", new string[]{ "d", "f"}) }; 12 List<string> ingredientes = new List<string>(); 13 14 while (true) 15 { 16 Console.Write("Add an ingredient:"); 17 ingredientes.Add(Console.ReadLine()); 18 var cookables = recipes.Where(r => !r.Ingredients.Except(ingredientes).Any()); 19 20 if (cookables.Count() > 0) 21 { 22 foreach (var cookable in cookables) 23 { 24 Console.WriteLine($"{cookable.Name} can be cooked."); 25 } 26 27 break; 28 } 29 else 30 { 31 Console.WriteLine("Nothing can be cooked."); 32 } 33 } 34 } 35} 36 37struct Recipe 38{ 39 public string Name; 40 public string[] Ingredients; 41 42 public Recipe (string name, string[] ingredients) 43 { 44 this.Name = name; 45 this.Ingredients = ingredients; 46 } 47}

dから見るとaはcの材料なので、aやbは孫材料と呼ぶとします。

ここから先の孫云々は設計として何の意味があるのかわかりませんでした。

投稿2022/04/01 12:44

bboydaisuke

総合スコア5291

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bboydaisuke

2022/04/01 12:59 編集

> ここから先の孫云々は設計として何の意味があるのかわかりませんでした。 なんとなく理解しました。レシピとして構成する要素以外は弾きたいということかな?でもそれってレシピの材料が3つ以上だったり材料に包含関係がある場合(候補が複数ある場合)ってどうすんの?とか考えちゃうんで、もう少し仕様を詰めたくなりました。
koz555

2022/04/01 14:03 編集

ありがとうございます。 var cookables = recipes.Where(r => !r.Ingredients.Except(ingredientes).Any()); の部分が素晴らしいと考え込んでしまいました。 Exceptの具体的な使用方法がようやく理解出来ました。さらにそれをAnyで!をフィルタ条件にするとは 入力したものをレシピ材料から消去して存在しなくなったレシピを逆に残す、という意味ですね。 >レシピとして構成する要素以外は弾きたいということかな? そうとも取れます。が、子材料がまだ皿に無い場合は孫材料は弾きたくないです。わかりにくくて申し訳ないです。 そして、レシピはoutcomeが重複したレシピが作られるのを避けたいわけです。 つまり、わかめうどんのレシピ材料が「茹でたうどん、かけスープ、わかめ」となるレシピは(レシピ数が爆増するため)存在してほしくないです。 わかめうどんのレシピは「かけうどん、わかめ」の1つだけにしたいという趣旨です。 >包含関係がある場合(候補が複数ある場合) 候補が一つになりそれ以上クラフト出来なくなるまで、皿に盛り続けたいです 候補が絞りきれなくなるようなレシピはレシピのバグとして、そのような材料が重複したレシピが無くなるよう、レシピ側を見直したいです。 具体的な流れで実例を示すと、 1.皿にわかめを入れる 2.レシピ候補はわかめうどんとわかめエビうどんにしぼられる 3.かけスープを入れる→まだクラフト出来ないので入れるだけ。かけスープはかけうどんの子材料(わかめうどんの孫材料)なので、皿に入れる事が出来ると判定 4.かけうどんを入れようとする→かけスープが既に皿にあるため、(かけうどんはわかめうどんのレシピ材料だが)弾きたい 5.茹でたうどんを入れる→かけうどんがクラフトされる 6.と同時にわかめうどんがクラフトされる 7.その状態からさらにエビも弾かずに入れる事が出来る→入れると自動的にわかめエビうどんがクラフトされる このような挙動になって欲しいという意味になります。
guest

0

近いデザインパターンで言うとCompositeパターンでしょうか?

Compositeパターンは、容器と中身を同一化し、再帰的な構造を作る方式

デザインパターン ~Composite~ - Qiita

投稿2022/04/01 12:28

KomoriGameDev

総合スコア433

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

koz555

2022/04/01 13:59

ありがとうございます。 Compositeパターンを深堀してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問