20210513のJavaに関する記事は13件です。

【Java】ラムダ式を何となく理解する

ラムダ式を理解するための前置き 関数オブジェクト JavaSE7まででは、変数に代入できるのは第一級オブジェクト(データ、インスタンスなど)のみであるとされていたが、 JavaSE8以降では、関数も変数に代入できるようになった。 関数にとって、名前はあってもなくても良いものである。 入力(引数)と出力(返り値)さえあれば関数の役割は果たせる。 例えば… =============================== 職場の上司に、 「この手順書に沿って折り紙折っといて~、午前中に100個作っておくように!」 と指示され、手順書と折り紙100枚を渡された(どんな仕事やねん) しかし、手順書には折り方が載ってあるだけで、 何が出来上がるのかとか、手順書の名前なんてものはない。 それでも、手順に沿って折り紙をしていった結果、 なにか良くわからないけど100個分完成した =============================== …みたいな感じである。 プログラミングにおける関数も同様で、 「名前なんか無くても入力・出力さえあれば関数でいいよね~」 って考えでJavaSE8からは変数に関数が代入できるようになった。 変数に代入される関数のことを、関数オブジェクトといったりもする。 変数への関数オブジェクト代入の例 import java.util.function.*; public class Sample { private static int sum(int x, int y) { return x + y; } public static void main(String[] args) { IntBinaryOperator func = Sample::sum; int x = func.applyAsInt(10, 20); System.out.println(x);//result: 30 } } ざっくり説明すると、Sampleクラスにあるstaticなsumメソッドへの参照を、IntBinaryOperatorインターフェース)のfuncに代入することで、 IntBinaryOperatorインターフェースで予め定義されているapplyAsIntメソッドはsumメソッドの機能としてオーバーライドされ、 func.applyAsIntはsumの機能を提供するようになった、という感じ。 なお、今回のように関数オブジェクトを変数に代入できるのには条件がある。 ================================ 1.変数(左側)の条件…抽象メソッドを1つしか有していない関数型インターフェースである(*1)こと 2.関数オブジェクト(右側)の条件…関数型インターフェースのメソッドと関数オブジェクトの「戻り値の型・引数の数・引数の型」が一致していること (*1)SAMインターフェース(Single Abstract Method Interface)という ================================ 実際、↑のコードでも条件は満たす。 IntBinaryOperatorというのをリファレンスで調べてみると、 これは関数型インタフェースなので、ラムダ式またはメソッド参照の代入先として使用できます。 int applyAsInt​(int left, int right) これ1つのみメソッドをもつ との記載がされている。 今回の関数オブジェクトint sum(int x, int y)と比較をしても条件は満たしている。 IntBinaryOperatorの他にも関数型インターフェースは以下のようなものがある 関数型インターフェース メソッド int IntToDoubleFunction(int, int) applyAsDouble void IntConsumer(int) accept int IntSupplier() getAsInt boolean IntPredicate(boolean) test ラムダ式 ラムダ式とは、関数を必要なタイミングで即座に利用できるようにするための構文のこと 先ほどの関数オブジェクト代入コードを、ラムダ式を用いて表すと以下のようになる import java.util.function.*; public class Sample2 { public static void main(String[] args) { IntBinaryOperator func = (int x, int y) -> { return x + y; }; int x = func.applyAsInt(10, 20); System.out.println(x);// result: 30 } } 非常にシンプルなコードになったが、実態は先ほどと変わらず、 引数x, yの合計値を戻り値として返す関数への参照を、IntBinaryOperatorインターフェースのfunc変数に代入している。 また、以下のように、条件を満たせばもっと簡略化することも可能である。 import java.util.function.*; public class Sample3 { public static void main(String[] args) { IntBinaryOperator func = (x, y) -> x + y; int x = func.applyAsInt(10, 20); System.out.println(x);// result: 30 } } ラムダ式の実践的な使い方の具体例 StreamAPI void forEach(Consumer) 関数型インターフェースConsumerの変数を引数に取り、要素の数だけ処理を繰り返す import java.util.ArrayList; import java.util.List; public class RamdaSample2 { public static void main(String[] args) { int[] nums = { 9, -3, 1, 0, 2 }; List<Integer> numsList = new ArrayList<>(); for (int n : nums) numsList.add(n); numsList.stream().forEach((i) -> { System.out.println(i); }); } } //9 //-3 //1 //0 //2 ちなみに、よく使う関数型インターフェースには以下のようなものがある (T:引数, R:戻り値) 関数型インターフェース メソッド Functions<T, R> R apply(T) Consumer<T> void accept(T) Supplier T get() Predicate<T> boolean test(T) おわりに 関数オブジェクトの項目だけでも読んでおけば、 ラムダ式がなぜあんな意味不明な構造になっているかのかは何となくわかるはず
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java アルゴリズム修行⑯】文字列探索 ~力まかせ法~

文字列探索とは ここまでは数列からの探索や、数列を期待通りにソートするなど、 数字を中心に扱ってきましたが、次に文字列を扱う探索を学んでいきたいと思います! 文字列探索というのがどういうことかという話なんですが、 ある文字列中とは別の文字列が含まれているかどうかを調べ、含まれていれば、その位置も調べるということです。 例えば、STRINGという文字列からINGを探索すれば、それは含まれていることになり、 文字列中の4番目に位置しているということになります。 探索される側の文字列はテキスト、探索する文字列をパターンと呼ばれることが多いようです。 今回はその文字列探索の中でも基礎的な力まかせ法について見ていきましょう。 力まかせ法とは 力まかせ法とは、その名の通り、 パターンが現れるまで、テキストを頭からひたすら走査していくという、 効率もへったくれもない筋肉質なアルゴリズムのようです。。笑 テキストが ABABCDEFG で、パターンが ABCとしたら、 最初の ABAと比較し、合ってなかったら1文字ずつずらして照合していくというのを繰り返していきます。
 数列であれば前から一つずつ値を比較して確認する線形探索にも似ているため、
単純法や素朴法とも呼ばれるそうです。 ABABCDEFGで実際に流れを見てみると、まずは頭からパターンと照合してみます。 パターンの2文字目までは合致しましたが、3文字目が異なったので、 次にテキストの2文字目から照合します。 パターンの1文字目から一致しなかったので、テキストの3文字目から照合します。 3文字目から照合したところ、パターンの全てと一致したので、ここで初めて探索成功となります。 しかし、見て分かる通り、パターンと照らし合わせる際に合わなければ テキストとの比較はリセットされて、1文字ずつしか前進することができないので、その点は非効率かもしれませんね。。 流れは掴めたので、実際にコードに落とし込んでみましょう! コードに落とし込んでみる Match.java static int bfMatch(String target, String pat) { int pt = 0; // targetをなぞるカーソル int pp = 0; // patをなぞるカーソル while (pt != target.length() && pp != pat.length()) { if (target.charAt(pt) == pat.charAt(pp)) { pt++; pp++; } else { pt = pt - pp + 1; pp = 0; } } if (pp == pat.length()) { // 探索成功 return pt - pp; } return -1; // 探索失敗 } 文字列targetから文字列patを探索し、成功した場合は、patと一致するtargetのインデックスを返します。

 文字列target中に文字列patが複数含まれる場合は、一番最初にくる位置のインデックスを返すようにしています。 

targetを走査するカーソルをpt、patを走査するカーソルをpp として、最初のインデックスである0で初期化しています

。 その後、 pt がtargetの文字列の長さと同じ かつ ppがpatの文字列の長さと同じ になるまでwhile文を繰り返します patが見つかるまで走査するか、そのままtarget全ての走査が終われば探索は終了なので どちらかがtrueとなれば、探索のwhile文を抜けます。 一番最初の流れは、if文内で

target.chartAt(0) == pat.charAt(0)として1文字目が一致していれば targetとpatのカーソルを1個ずつ増やしていき、走査対象を前へと進めます。 

もし一致していなければ、targetのカーソルを patと合わせて進んだ分の次の要素に合わせたいので、 pt - pp + 1としています。 そして、patのppは最初へと戻していく という繰り返しです。 

while文を抜けた後、ppが patの文字列の長さと一致していれば ppが全て一致する文字列がtargetの中にあったということになるので、 ptが進んだカーソルから、パターン分の文字数を引いて、 パターンと一致した箇所の最初のインデックスを返すようにしています。 

もしそうでなければ探索失敗として -1を返しています。 例えば、ABAABCというテキストから、ABCというパターンを探索するとなると、 target に ABAABCを pat にABCが渡されたあと、pt も pp も0から始まります。 target.chartAt(0) == pat.charAt(0) として A同士で一致します そのままpt と ppをインクリメントして target.chartAt(1) == pat.charAt(1) としてB同士で一致します
 そのままpt と ppをインクリメントして target.chartAt(2) == pat.charAt(2) としてAとCなのでここで ptのカーソルは2-2+1で1に戻り、ppは0からとなります 

target.chartAt(1) == pat.charAt(0) としてBとAなのでここで 
ptのカーソルは1-0+12に戻り、ppは0からとなります

 target.chartAt(2) == pat.charAt(0) ` としてAとAなのでここで 
そのままpt と ppをインクリメントして target.chartAt(3) == pat.charAt(1) としてAとBなのでここで
 ptのカーソルは3-1+1で3に戻り、ppは0からとなります target.chartAt(3) == pat.charAt(0) としてAとAなのでここで
 そのままpt と ppをインクリメントして target.chartAt(4) == pat.charAt(1) としてBとBなのでここで
 そのままpt と ppをインクリメントして target.chartAt(5) == pat.charAt(2) としてCとCなのでここで 
そのままpt と ppをインクリメントすると

ptは6となり、targetの文字列長と一致し ppも3となり、patの文字列長さと一致するので、ここでwhile文を抜けます。 その後、ppとpatの文字列長さが一致するので、そのまま ptからppを引いて、一致する文字の最初のインデックスである3を返す という流れになりますね! テキストの文字列がnとして、パターンの文字数がmであるとして、
 力まかせ法の計算量はO(mn)で、実質的にはO(n)なので、力まかせというものの、そこまで遅いというわけではなさそうです。。 学んだこと 文字列探索の基礎に力まかせ法というのが存在し、その名の通り頭かひたすら照合を繰り返す。 照合するパターン側は一致しなければリセットされるので、その分は非効率になりやすい。 これまでの探索はkeyとなる数字を見つけてきたり、昇順に数列をソートしたりというのが多かったので セットとなる文字列を探索するというのはなかなか新鮮でした。。! 力まかせな部分をより効率化したKMP法というのがあるらしいので、引き続き頑張っていきます!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MinecraftでMODを開発したい#5

MinecraftでMODの開発をします 試行錯誤を書いていくだけのものになります 概要 MODをjar形式にし、一般の人に配布して使えるように 動作環境 2021/05/12 Version Mac OS Big Sur 11.1 IntelliJ IDEA 2021.1.1 AdoptOpenJDK (HotSpot) 1.8.0_282 Minecraft 1.16.5 Forge 36.1.0 目次 - 設定 - 確認 設定 build.gradleのversionを1.16.5-1.0.0に変更 IntelliJ IDEAのGradle Tool Windowを開き、Tasks > build > buildをダブルクリックで実行 確認 IntelliJ IDEAの画面下側に表示される実行ログに「BUILD SUCCESSFUL」と表示され、build/libs/にexamplemod-1.16.5-1.0.0.jarが生成されたことを確認してください。 他のMODを導入する時と同様に、jarファイルをMinecraftのmodsフォルダに入れてランチャーからMinecraftを起動 タイトル画面の「Mods」ボタンを押し、MOD一覧に「Titanium Mod」が表示されていることを確認 また、ワールドに入ってアイテム・ブロック・レシピが正しく追加されていることを確認 導入できていた 参考文献
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MinecraftでMODを開発したい#4

MinecraftでMODの開発をします 試行錯誤を書いていくだけのものになります 概要 MOD一覧などに表示される情報の登録 動作環境 2021/05/12 Version Mac OS Big Sur 11.1 IntelliJ IDEA 2021.1.1 AdoptOpenJDK (HotSpot) 1.8.0_282 Minecraft 1.16.5 Forge 36.1.0 目次 - リソースパックの情報 - mods.toml - ロゴ画像 - build.gradle リソースパックの情報 src/main/resources/pack.mcmeta { "pack": { "description": "Example Mod Resources", "pack_format": 6 } } mods.toml src/main/resources/META-INF/mods.toml modLoader = "javafml" loaderVersion = "[36,)" license = "The Unlicense" issueTrackerURL = "https://www.xxxxxx.com [[mods]] modId = "examplemod" version = "${file.jarVersion}" displayName = "Example Mod" displayURL = "https://www.xxxxxxxxxx.com logoFile = "logo.png" credits = "xxx" authors = "xxxxx" description = "練習用MOD" [[dependencies.examplemod]] modId = "forge" mandatory = true versionRange = "[36,)" ordering = "NONE" side = "BOTH" [[dependencies.examplemod]] modId = "minecraft" mandatory = true versionRange = "[1.16.5,1.17)" ordering = "NONE" side = "BOTH" MODの読み込みや一覧表示に使われる情報を記述 licenseはMODの利用条件を指定 このMODは例なので「Unlicense」という極めて緩いライセンスを採用 デフォルトはAll rights reserved(すべての権利を留保する)で、著作権法上の例外や別途の許諾を除き、複製や再配布などを禁止 Modpackでの利用や改変、再配布などをどこまで許容するか考え、自分で利用条件を決めたり、既存のライセンスを選ぶ issueTrackerURLは不具合の報告を受け付けるURL、logoFileはロゴ画像のファイル名、creditsは謝辞をそれぞれ指定 issueTrackerURL、displayURL、logoFile、credits、authorsは無くても問題なし descriptionなどでTOMLの複数行文字列を使うと、改行コードをCRLFにして保存した時にCRが正常に表示されないため、LF(\n)だけで改行しています。改行コードをLFにして保存すれば、複数行文字列も問題なく使える ロゴ画像 src/main/resources/logo.png build.gradle 元のbuild.gradleからの変更点 groupをcom.ドメイン名.examplemodに、archivesBaseNameをexamplemodに変更 ビルド時に出力されるファイルの名前は(archivesBaseName)-(version).jar minecraft { runs {内の4つのexamplemodをexamplemodに置換(今回は同じのため置換なし) JSONファイルの自動生成を行う時に必要になる設定 jar {とmanifest {との間に行を追加し、compileJava { options.encoding = 'UTF-8' }を挿入 コード内コメントに日本語が入っていた時の文字化けを防ぐため、文字コードを指定 jar { manifest { attributes([内のSpecification-TitleとImplementation-TitleをExample Modに、Specification-VendorとImplementation-Vendorを任意のものに変更 jarファイル内のMETA-INF/MANIFEST.MFに記載される情報 確認 参考文献
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【自分用】Java Gold SE 11 紫本 Chapter5 関数型インターフェースとラムダ式

README.md # 目的 Java Gold SE 11 各章のエッセンスを一つのコードに盛り込むことで、効率的な学習を図る。   「プログラミング界の『システム英単語』」を目指して... # 学べる内容 Java Gold SE 11 関数型インターフェース, Javaの基礎(インターフェース) - ラムダ式 cf. 匿名クラス - ジェネリクス - メソッド参照 # 使用する変数・関数 定数 DIFF = 1 変数 diff = 1 関数 iteration() {return diff*2;} # テーマ ライフゲーム(ライフモデル) 人間各々が関数(現:iteration())を有するものとし、その変数の変化によってoutput(人生)が決定するモデルを考える。 差異(diff, DIFF)を人生に与える指標ととらえ、差異を関数の変数と見立てた。 ここでいう差異とは、「人間各々を取り巻く属性・性質の違い」と捉えてよい。 関数iteration()のアウトプットは差異によって変化していく。      cf.)バタフライエフェクト(蝶がはばたく程度の非常に小さな撹乱でも、遠くの場所の気象に影響を与えるか?) 今回は人間1人(HK氏)のモデルを考える。 人間はインスタンスの有無に関わらずDIFF(先天的差異)を、インスタンス化されたときにdiff(後天的差異)を獲得している(する)。 関数iteration()の実装は1次関数に、差異は実質的な定数とすることで、モデルの単純化に努めた。 # 今後やりたいこと - 関数の実行を反復(iteration)させること。 - TODO記載内容 Init.java // 関数型インターフェースに付すアノテーション @FunctionalInterface public interface Init { // 定数の定義 int DIFF = 1; // 先天的差異 // TODO: 先天的差異をdefaltメソッドで算出 // TODO: privateメソッドで切り出し // TODO: staticメソッドでsysout題名表示 // 抽象メソッドの定義 int iteration(int diff); } HK.java import java.util.*; import java.util.function.Function; import java.util.function.Supplier; public class HK implements Init { // フィールド // 後天的差異 private int diff; // コンストラクタ public HK() { this.diff = 1; // this.diff = new Random().nextInt(10); } public HK(int diff) { this.diff = diff; } // getter() public int getDiff() { return this.diff; } // 1. オーバーライド(implements Init) @Override public int iteration(int diff) { // test f(x): x*2 return diff*2; // f(x, y): k^x - k^y // return (int) (Math.pow(this.diff, new Random().nextInt(10)) - Math.pow(this.diff, new Random().nextInt(10))); } public static void main(String[] args) { // 1. オーバーライド(implements Init) HK hk = new HK(1); // 先天的差異+後天的差異 int difference = hk.getDiff() + HK.DIFF; // difference = 2 int output1 = hk.iteration(difference); // difference*2 = 4 System.out.println("output1: " + output1); //4 // 以降、後天的差異のみ考慮 // 2. 匿名クラス Integer output2 = new Function<Integer, Integer>() { @Override public Integer apply(Integer diff) { return diff*2; } }.apply(DIFF); System.out.println("output2: " + output2); // 3. ラムダ式 // インターフェースを実装するイメージ Function<Integer, Integer> temp3 = (Integer diff) -> { return diff*2; }; Integer output3 = temp3.apply(DIFF); System.out.println("output3: " + output3); // 4. ラムダ式 簡略化 Function<Integer, Integer> temp4 = diff -> diff*2; Integer output4 = temp4.apply(DIFF); System.out.println("output4: " + output4); // 5. staticメソッド参照 // DIFFを2進数表記にして、1の数をカウント(TODO: ライフイベント発生トリガーになりうる?) Function<Integer, Integer> temp5 = diff -> Integer.bitCount(diff); Integer output5 = temp5.apply(DIFF); System.out.println("output5(2進数表記にして1の数をカウント): " + output5); // 6. コンストラクタ参照 // ラムダ式を使う場合 // Supplier<HK> hk2 = () -> new HK(); // コンストラクタ参照を使う場合 Supplier<HK> hk2 = HK::new; System.out.println("先天的差異: " + HK.DIFF); System.out.println("後天的差異: " + hk2.get().diff); // 7. インスタンスメソッド参照 List<Integer> diffList = List.of(HK.DIFF, hk.getDiff()); // ラムダ式を使う場合 diffList.forEach(diff -> System.out.println("差異: " + diff)); // 繰り返しのdiffを省略したい→メソッド参照 diffList.forEach(System.out::println); // +演算子で結合できない // diffList.forEach(System.out::println + ", "); //NG // TODO: int用の関数型インターフェースを用いる } } output1: 4 output2: 2 output3: 2 output4: 2 output5(2進数表記にして1の数をカウント): 1 先天的差異: 1 後天的差異: 1 差異: 1 差異: 1 1 1
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MinecraftでMODを開発したい#3

MinecraftでMODの開発をします 試行錯誤を書いていくだけのものになります 概要 特殊な機能を持たないブロックの追加 動作環境 2021/05/12 Version Mac OS Big Sur 11.1 IntelliJ IDEA 2021.1.1 AdoptOpenJDK (HotSpot) 1.8.0_282 Minecraft 1.16.5 Forge 36.1.0 目次 プログラムの記述 Block Stateの記述 ブロックモデルの記述 アイテムモデルの記述 テクスチャの配置 翻訳設定 ルートテーブルの記述 確認 プログラムの記述 src/main/java/com/ドメイン名/examplemod/ExampleMod.java package com.tntmodders.examplemod; import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.material.MaterialColor; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraftforge.common.ToolType; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.RegistryObject; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; @Mod(ExampleMod.MOD_ID) public class ExampleMod { public static final String MOD_ID = "examplemod"; public ExampleMod() { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); Blocks.register(modEventBus); Items.register(modEventBus); } public static class Blocks { private static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MOD_ID); public static final RegistryObject<Block> EXAMPLE_BLOCK = BLOCKS.register("example_block", () -> new Block(AbstractBlock.Properties .of(Material.METAL, MaterialColor.METAL) .requiresCorrectToolForDrops() .strength(5.0F, 6.0F) .sound(SoundType.METAL) .harvestTool(ToolType.PICKAXE) .harvestLevel(1) )); public static void register(IEventBus eventBus) { BLOCKS.register(eventBus); } } public static class Items { private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MOD_ID); public static final RegistryObject<Item> EXAMPLE_BLOCK = ITEMS.register("example_block", () -> new BlockItem(Blocks.EXAMPLE_BLOCK.get(), new Item.Properties() .tab(ItemGroup.TAB_BUILDING_BLOCKS))); public static final RegistryObject<Item> EXAMPLE_INGOT = ITEMS.register("example_ingot", () -> new Item(new Item.Properties() .tab(ItemGroup.TAB_MATERIALS))); public static void register(IEventBus eventBus) { ITEMS.register(eventBus); } } } BLOCKS.register("example_block", ...)でブロックの登録名を指定 ブロックIDはexamplemod:example_blockとなります。 BlockクラスのインスタンスはMinecraftのブロックの種類を表す 硬さや爆破耐性など、ブロックの種類によって変わる性質を保持 AbstractBlock.Properties.of(Material.METAL, MaterialColor.METAL)で、燃えるかどうかなどの基本的な性質をまとめたMaterialと、地図上の表示色であるMaterialColorを指定 requiresCorrectToolForDropsで、ブロックを回収するために適切な道具が必要であると設定 strength(5.0F, 6.0F)でブロックの硬さと爆破耐性を指定 第一引数は硬さで、数値が大きいほど壊すために時間がかかる 第二引数は爆破耐性で、数値が大きいほど爆発で壊れにくくなる sound(SoundType.METAL)でブロックの設置、破壊、上を歩いた時などに発生する音の種類を指定 harvestTool(ToolType.PICKAXE)でブロックを回収するための適正な道具の種類を指定 斧(AXE)、ツルハシ(PICKAXE)、シャベル(SHOVEL)、クワ(HOE)の中から選ぶ 指定しない場合は、どの道具を使っても早く壊せなくなる harvestLevel(1)でブロックを回収するために必要な道具の素材水準を指定 初期値は-1で、0が木か金、1が石、2が鉄、3がダイヤモンドの道具を要求 BlockItemは、プレイヤーのインベントリの中にある時など、アイテムとしてのブロックを表すクラス ほとんどのブロックは破壊されると対応するアイテムをドロップし、対応するアイテムを右クリックするとブロックをワールドに設置する このような対応関係を示すための、Itemを継承したクラス tab(ItemGroup.TAB_BUILDING_BLOCKS)で通常のアイテムと同様に、クリエイティブタブを指定します。今回は「建築ブロック」タブを指定 Block Stateの記述 src/main/resources/assets/examplemod/blockstates/example_block.json { "variants": { "": { "model": "examplemod:block/example_block" } } } ブロックの状態とモデルとの対応をJSONで記述 今回は状態を扱わないので、モデルを1つ指定 ブロックモデルの記述 src/main/resources/assets/examplemod/models/block/example_block.json { "parent": "minecraft:block/cube_all", "textures": { "all": "examplemod:block/example_block" } } 今回は正六面体のフルブロックで全面同じテクスチャを使う アイテムモデルの記述 src/main/resources/assets/examplemod/models/item/example_block.json { "parent": "examplemod:block/example_block" } 今回はブロックのモデルを指定 テクスチャの配置 src/main/resources/assets/examplemod/textures/blockのファイル構造を構築 そこにブロックの各面に表示される16×16ピクセルのpng画像ファイルexample_block.pngを配置する 翻訳設定 英語翻訳 src/main/resources/assets/examplemod/lang/en_us.json { "block.examplemod.example_block": "Block of Example", "item.examplemod.example_item": "Example Item" } 日本語翻訳 src/main/resources/assets/examplemod/lang/ja_jp.json { "block.examplemod.example_block": "お試しブロック", "item.examplemod.example_item": "お試しアイテム" } ルートテーブルの記述 src/main/resources/data/examplemod/loot_tables/blocks/example_block.json { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "examplemod:example_block" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ブロックを適正な道具で破壊した際にドロップするアイテムをJSONで記述 今回は常にお試しアイテムをアイテムとして1つドロップするよう指定 フォルダ名が複数形なので注意 "condition": "minecraft:survives_explosion"により、他のブロックと同様、爆発により壊された時に1/(爆発力)の確率でアイテムをドロップするようになる 確認 ブロックとして確認できたが、ドロップはしなかった 参考文献
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Kotlin学習記

はじめに 今回はKotlinのnull安全についてJavaとの比較を交えながらまとめたいと思います。 null安全とは? null安全とは、コードからnull参照の危険性を排除することを目的としたKotlinの機能であり、null参照を使用とするとコンパイルエラーが発生する。 この機能はJavaで頻出のNullPointerExceptionを避けるために有効であると考えられます。 Non-Null型とNullable型 KotlinにはNon-Null型とNullable型が存在しており、以下のように実装する。 var str : String = "あいうえお" //Non-Null型 str = null //コンパイルエラー var str2: String? = "かきくけこ" //Nullable型 str2 = null //問題なし 上記のように、nullを格納できないNon-Null型、nullを格納できるNullable型が存在することで、潜在的なnull参照の危険性を排除し、視覚的にnullの存在を把握することができることは可読性や保守性の向上に繋がると私は感じました。 Nullable型の処理について(ここからが本題) 次に、Nullable型の処理について、もう少し詳細を記述します。 【疑問】 Nullable型にnullが格納できるのであれば、Nullable型の値を参照すればNullPointerExceptionが発生するのでは? 上記の疑問に関しては、Nullable型を参照するためにはnullが格納されていないかを事前に確認する必要があり、確認していない場合はコンパイルエラーが発生する仕組みになっている。 var str2: String? = "かきくけこ" print("この文字列の長さは${str2.length}です。") //コンパイルエラー コンパイルエラーが発生するため、nullが格納されていないことを確認する必要がある。 var str2: String? = "かきくけこ" if (str2 != null) //nullではないことを確認している print("この文字列の長さは${str2.length}です。") else print("この文字列はnullです。") また、場合によってはエルビス演算子を用いることでより簡潔に記述できる。 (Nullable型の変数)?.(trueの時の処理)?:(falseの時の処理) まとめ Javaを学習しつつ、Kotlinを学習していると、より理解が深まりやすく利便性についても享受できると感じています。引き続き、学習していきたいと思います。 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】ArrayListの使い方

ArrayListとは Javaの通常の配列では、最初から配列の数を決める必要がありました。 a=new int[10] これでは、後から配列の数を変更できなかったり、最初から配列の数が決まっていないときなどに不便ですね。 ArrayListは、このような不便を解決してくれる予め用意されたJavaのクラスです。 ArrayListの特徴 下記のような特徴があります。 1. オブジェクトであればどんな型でも扱える 2. 配列に値を後から追加することができる 3. 追加した順に並ぶ 4. nullも値として追加できる 5. 重複した値も追加できる 6. スレッドセーフではない 通常の配列に比べて、各段に使いやすいですよね。 実際の開発では、配列よりもArrayListを使うことが多いようです。 ArrayListの書き方 ArrayListは、次のように書きます。 ArrayList<型> リスト名 = new ArrayList<型>(); 「型」には、クラス名を指定します。 指定したクラスのオブジェクトを、リストに要素として格納することができます。 実際に書いてみます。 Stringの場合 ArrayList<String> strList = new ArrayList<String>(); Integerの場合 ArrayList<Integer> intList = new ArrayList<Integer>(); ここで1つ注意。リストの要素は参照型である必要があります。 例えばintのように基本データ型を要素に持つリストは作成できません。 intのような基本データ型をリストに入れたい場合は、上記の「Integerの場合」のようにラッパークラスを用いて定義します。 (基本データ型とは:参照型とは異なり、直接値を格納する型のことです。) ArrayListの主なメソッド AllayListにはあらかじめ便利なメソッドが用意されています。 よく使われるメソッドを下記にまとめました。 メソッド名 機能 void add(int index, Object element) リストの指定した位置に、指定した要素を追加する。 boolean add(Object element) リストの末尾に要素を追加する。 void clear() リストからすべての要素を削除する。 Object get(int idex) リストの指定した位置の要素を取得する。 int indexOf(Object element) 引数と同じ要素を先頭から検索する。 boolean isEmpty() リストが空かどうか調べる。空の場合、trueを返す。 Object remove(int index) リストの指定した位置から要素を削除する。 Object set(int index, Object element) リストの指定した位置の要素を、指定した新しい要素に置き換える。 int size() リストに入っている要素の数を取得する。 実際に書いてみる ではArrayListを使って実際にコードを書いてみます。 例1 ソースコード //ArrayListクラスのインポート import java.util.ArrayList; public class Main{ public static void main(String[] args){ //型を指定しなくてもよい ArrayList list = new ArrayList<>; //要素を追加していく list.add("みかん"); list.add(5); list.add('A'); //リストの中身を出力する for (Object obj : list){ System.out.print(obj); } } } 実行結果 みかん5A このように型が異なる要素を、一つのリストに追加することができます。 例2 ソースコード //ArrayListクラスのインポート import java.util.ArrayList; public class Main{ public static void main(String[] args){ //変数strに、文字列abcdefgを代入 String str = "abcdefg"; //indexOfメソッドを使用して引数aを変数strから検索 System.out.print(str.indexOf("a")); } } 実行結果 0 今回はindexOfメソッドを使った例です。 変数strに代入した文字列「abcdefg」から、indexOfメソッドの引数に設定した「a」を検索してみました。 実行結果の「0」は、文字列「abcdefg」における「a」の位置を表しています。 「a(0) b(1) c(2) d(3) e(4) f(5) g(6)」  ※()内の数字は位置を表しています。 なので、例えばindexOfメソッドの引数がdなら3、gなら6になります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初学者なりにPythonのクラス定義を調べてみた

Pythonのクラス定義の特徴 自分はJavaからプログラム言語の世界に入ったため、静的型付け言語のJavaやC#の記述方法が好き。 そのため、Pythonの勉強を始めたときも、クラス定義はJavaのように、クラス宣言、フィールド、コンストラクタ、メソッドのように作ったりしていた。 ただ、当然ながらPythonはJavaとは違うので、適当に作るとうまく動かなかったり、ネットに転がっている既存のPythonのクラスを見てもいまいちよく分からない記述があったりで、理解するのになかなか苦労した。 というわけで本記事は、Pythonのクラス定義に関する自分向けもしくは初学者用の備忘録だ。 自分もPythonに触れ始めてまだ間もないため、誤っている点がいくつかあると思う... Pythonのクラス定義の基本 Pythonのクラス宣言は以下のようにやるらしい python class TestClass: pass tc = TestClass() passは何もしないということ 要するにTestClassクラスは具体的な処理のない空っぽのクラスだ tc = TestClass() は、Javaでいう java TestClass tc = new TestClass(); のようなことをしている。 インスタンス変数を定義することもできる ただし python class TestClass: val1 = "変数" tc = TestClass() print(tc.val1) 実行結果 変数 ちなみに注意が必要で このTestClassクラス直下に宣言されている変数val1はインスタンス変数ではない python class TestClass: val1 = "変数" tc = TestClass() print(tc.val1) tc.val1 = "変更してやったぜ" # tcオブジェクトのval1は変わったが、TestClassのクラス変数val1は変わらない print(tc.val1) print(TestClass.val1) 実行結果 変数 変更してやったぜ 変数 この変数はあくまでクラス変数であるため、定義する際には注意が必要だ。 Javaで例えるとstaticがつく感じだろうか java public class TestClass{ public static String val1 = "変数"; } Pythonのインスタンス変数、コンストラクタの定義 Pythonのクラスでインスタンス変数を使うには、基本的にはコンストラクタの中で定義してやる必要がある。 そこでPythonのコンストラクタの定義方法についてだが、これもまたJavaとはだいぶ違う。 python class TestClass: def __init__(self): self.val1 = "変数" tc = TestClass() print(tc.val1) 実行結果 変数 Pythonでは、コンストラクタは python def __init__(self): # 処理 のように定義する。 Javaではコンストラクタは大文字から始まるクラス名と同じ名称である必要があったため、ここも毛色が違う。 この__init__と名前の付いたメソッドは、クラスのインスタンスが作られたときにそのオブジェクト当たり一回だけ実行される(つまりコンストラクタ) このメソッドの引数にあるselfは、このクラスのインスタンス自身を指している。 Pythonのクラス内でメソッドを定義する際に、必ず引数が1つは必要というPythonの仕様がある。 この引数に渡されるものの正体はインスタンス自身であり、メソッドを呼び出すときに自動的に第一引数として渡される。 そのため定義側に引数を用意してやらないと {メソッド名} takes 0 positional arguments but 1 was given というエラーが発生する。このエラーの内容は メソッドに引数が定義されていないのに1つ渡されたぞオイ! みたいな感じ、自動的に渡されるため定義してやる必要があるね。 selfという引数名を付けるのは慣習だとかなんとか。 整合性が取れればhogeでもhugaでもargでもなんでもいいらしい。 また python def __init__(self): self.val1 = "変数" のように、インスタンス変数にもselfをつけてあげる必要がある これによって、val1というのがこのクラスのインスタンスの変数だよという事を表している。 なのでインスタンスが別のものであれば、このval1という変数もまた別に用意される。 コンストラクタの中で定義された変数は、インスタンス変数として使うことが出来る。 インスタンス変数を宣言するときに、代入なしで宣言できないものか?と思った java public class TestClass{ String val1; int val2; } Javaでは、上記のように変数を宣言だけして用意しておくことが出来るが、Pythonでは、変数の宣言は必ず代入をセットで行わないとならないようだ。 なので、これと似たような宣言方法をとりたい場合、Pythonではインスタンス変数にNoneを代入して初期化しながら用意しておくと良い(らしい) Pythonで使われるNoneは、Javaにおけるnullのように存在しないという意味合いだ 厳密には他にも意味があるのだが、nullみたいなものと思えばいいらしい。(初学者だし) python class TestClass: def __init__(self): self.val1 = None self.val2 = None tc = TestClass() print(tc.val1) tc.val1 = "変数1" tc.val2 = "変数2" print(tc.val1 + "と" + tc.val2) 実行結果 None 変数1と変数2 Pythonのメソッドの定義 もう既にコンストラクタの定義の部分で触れてはいるが、あえて分けた。 といってもPythonではあくまでどちらもメソッドとして構造は全く同じため、あまり気にする必要はない。 ただ、Javaを学ぶ上ではコンストラクタとメソッドって結構しっかり分けられてた印象があったため、こちらでもそれに従った。 python class TestClass: def __init__(self): self.val1 = None self.val2 = None def method1(self): print("method1が呼び出されました") def method2(self): print("val1 = " + self.val1 + "\nval2 = " + self.val2) tc = TestClass() tc.val1 = "変数1" tc.val2 = "変数2" tc.method1() tc.method2() 実行結果 method1が呼び出されました val1 = 変数1 val2 = 変数2 このように、コンストラクタと同じように定義する。 違う点は、コンストラクタはインスタンスが生成されたときに自動的に一度だけ呼び出されるのに対して、通常のメソッドは明示的に呼び出す必要がある。 また、戻り値のあるメソッドに関しては、return文を用意するだけで良い。 python class TestClass: def __init__(self): self.val1 = None self.val2 = None def method1(self): return self.val1 + self.val2 tc = TestClass() # 文字列を渡した場合 tc.val1 = "変数1" tc.val2 = "変数2" print(tc.method1()) # 数値を渡した場合 tc.val1 = 2 tc.val2 = 5 print(tc.method1()) 実行結果 変数1変数2 7 ここでJavaと違う点は、メソッドの戻り値をカンマ区切りで複数用意することが出来る。 python class TestClass: def __init__(self): self.val1 = None self.val2 = None def method1(self): return self.val1, self.val2, self.val1 + self.val2 tc = TestClass() tc.val1 = 3 tc.val2 = 5 result = tc.method1() # この状態だとtuple型のデータが返される print(result) # tuple型として返された複数の戻り値は要素番号で個別に呼び出すことが出来る print(result[0]) print(result[1]) print(result[2]) 実行結果 (3, 5, 8) 3 5 8 カンマで区切られた戻り値は、タプル型として返される。 Javaでは配列やリスト、マップで返していたのに比較すると、直感的でわかりやすいと思う。 if __name__ == "__main__": とは Pythonで書かれたクラスのコードを見ると度々出会うこの謎の条件文 この条件文のブロックの中にメインの処理が書かれている場合が多い。 Pythonは実行させたいメインの処理をグローバルな場所に記述しても動く。 しかし、グローバルな場所に記述した場合、そのクラスをimportした時も勝手に処理が呼び出されてしまう。 if __name__ == "__main__": という条件文のブロック内にメインの処理を記述すると、そのクラスを実行したときのみ処理が呼び出されるようにできる。 Javaでいうと java public static void main(String[] args){} おなじみのメインメソッドのようなものと思ってもらえればいい。 class_test1.py class TestClass: def __init__(self): self.val1 = None self.val2 = None def pow_numbers(self): return self.val1 ** self.val2 if __name__ == "__main__": tc = TestClass() tc.val1 = 5 tc.val2 = 3 print(tc.pow_numbers()) 実行結果 125 多くのサイトやブログでは、この条件文をおまじないのようなものとして説明していることが多い。 実際Javaのメインメソッドも、しばらくはおまじないとして書かされがちだ。 しかしPythonのこれは、あくまで条件文 __name__ と "__main__" さえ分かれば意味も理解できそうだ。 __name__ とはそもそも何か 下記の結果を見ればわかりやすいと思う class_test1.py import numpy as np print(__name__) print(np.__name__) 実行結果 __main__ numpy __name__の正体は、Pythonがコードを実行するときに自動的に生成するグローバル変数の一つ 中には、モジュール名が格納される。つまり、importされたモジュールの__name__には、そのモジュール名が入る しかし、プログラムを実行しているPythonスクリプトは、自動的に__main__というモジュール名で識別される。 要するに、if __name__ == "__main__":という条件文は このスクリプトが実行元である場合、という意味合いになる。 別のスクリプトファイルでclass_test1.pyをインポートしてモジュールとして使う時は、この条件文のブロック内の処理は行われない。 Pythonのクラス定義のおさらい 今回はPythonのクラスを構成するインスタンス変数、コンストラクタ、メソッドについてまとめてみた。 これらを理解すると、下記のようにある程度自由にクラスを定義することが出来る。 class_test2.py class TestClass1: def __init__(self): self.array = [] self.num1 = None self.num2 = None self.str1 = None self.str2 = None def set_numbers(self, num1, num2): self.num1 = num1 self.num2 = num2 def pow_numbers(self): return self.num1 ** self.num2 def set_strings(self, str1, str2): self.str1 = str1 self.str2 = str2 # このclass_test.pyが実行されたときに動く if __name__ == '__main__': # 上に定義したTestClass1クラスをインスタンス化 tc1 = TestClass1() # set_numbers()メソッドで数値をインスタンス変数にセット # sum_numbers()メソッドがインスタンス変数の数値同士を冪乗して戻す tc1.set_numbers(2, 6) sum_num = tc1.pow_numbers() print(str(tc1.num1) + "の" + str(tc1.num2) + "乗は" + str(sum_num) + "です") # set_strings()メソッドで文字列をインスタンス変数にセット tc1.set_strings("こんにちは", "今日はいい天気ですね") print(tc1.str1 + "、" + tc1.str2) # インスタンス変数arrayに1から25までの奇数を順番に追加 for i in range(1, 27, 2): tc1.array.append(i) print(tc1.array) # 一つ飛ばしで要素を削除 last_index = len(tc1.array) count = int(last_index / 2) for i in range(count): tc1.array.pop(i + 1) print(tc1.array) # arrayの中身をクリア tc1.array.clear() print(tc1.array) 実行結果 2の6乗は64です こんにちは、今日はいい天気ですね [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25] [1, 5, 9, 13, 17, 21, 25] [] 自分がまだまだPythonの勉強を始めたばかりのため、色々と誤った認識のままでいる点等あると思う 今後新たな発見があったり、修正点を見つけたりしたら、その都度またまとめていこうと思う。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MinecraftでMODを開発したい#2

MinecraftでMODの開発をします 試行錯誤を書いていくだけのものになります 概要 特殊な機能を持たないアイテムの追加 動作環境 2021/05/12 Version Mac OS Big Sur 11.1 IntelliJ IDEA 2021.1.1 AdoptOpenJDK (HotSpot) 1.8.0_282 Minecraft 1.16.5 Forge 36.1.0 目次 プログラムの記述 アイテムモデルの記述 テクスチャの配置 翻訳設定 確認 プログラムの記述 src/main/java/com/ドメイン名/examplemod/ExampleMod.java package com.ドメイン名.examplemod; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.RegistryObject; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; @Mod(ExampleMod.MOD_ID) public class ExampleMod { public static final String MOD_ID = "examplemod"; public ExampleMod() { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); Items.register(modEventBus); } public static class Items { private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MOD_ID); public static final RegistryObject<Item> TITANIUM_INGOT = ITEMS.register("example_item", () -> new Item(new Item.Properties() .tab(ItemGroup.TAB_MATERIALS))); public static void register(IEventBus eventBus) { ITEMS.register(eventBus); } } } MOD_IDはmods.tomlに記載したものと一致する必要があり、すべて小文字の必要がある ITEMS.register("example_item", …)でアイテムの登録名を指定 アイテムIDはexamplemod:example_itemとなる ItemクラスのインスタンスはMinecraftのアイテムの種類を表す。耐久上限や最大スタック数など、アイテムの種類によって変わる性質を保持している tab(ItemGroup.TAB_MATERIALS)でクリエイティブタブ「その他」に表示されるよう指定 この指定を行わなかった場合、クリエイティブタブからは取得できなくなる アイテムモデルの作成 src/main/resources/assets/examplemod/models/item/example_item.json { "parent": "minecraft:item/generated", "textures": { "layer0": "examplemod:item/example_item" } } テクスチャの配置 src/main/resources/assets/examplemod/textures/itemのファイル構造を構築 そこにアイテムのアイコンになる16×16ピクセルのpng画像ファイルexample_item.pngを配置する 翻訳設定 英語翻訳 src/main/resources/assets/examplemod/lang/en_us.json { "item.examplemod.example_item": "Example Item" } 翻訳が設定されていない言語の代わりとしても表示される 日本語翻訳 src/main/resources/assets/examplemod/lang/ja_jp.json { "item.examplemod.example_item": "お試しアイテム" } 文字コードはUTF-8で保存 確認 参考文献
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ざっくり理解するプログラミング入門基礎編(Java)第2回

この記事は、ざっくり理解するプログラミング入門基礎編(Java)第1回の続きです。 読んでない方はぜひそちらを読んでからこの記事を読んでください。 今回は前回に引き続き、Javaにおける基本的なプログラムの書き方について、解説していきたいと思います。 この辺は何回もコードを書くうちに必ずわかるようになると思うので、わからなかったらとりあえず、こういうものがあるんだなくらいの感じで進めてもらっても構いません。 Javaプログラムの書き方2 今回の内容は以下の二つです コンピューターに計算をさせる。 変数について知る コンピューターに計算をさせよう まずは、プログラムでコンピューターに計算をさせる方法です。計算が使えるようになると一気にプログラミングをしている感が強まると思います。計算といってもそんなに難しくはないので、数学が苦手な方もそんなに身構えずにやっていきましょう。 四則演算 まず計算の基本の足し算、引き算、割り算、掛け算です。 下のコードを見てください。 Main.java public class Main { public static void main(String [] args){ System.out.println(1+2); //1+2の計算をし出力する System.out.println(4-2); //4-2の計算をし出力する System.out.println(2*3); //2×3の計算をし出力する System.out.println(6/2); //6÷2の計算をし出力する } } 計算し、その結果を順番に出力するというプログラムです 3行目と4行目の足し算引き算は記号も数学と同じなのですぐにわかると思います。 5行目と6行目ですが、これらはそれぞれ掛け算と割り算を表します。 なぜわざわざ違う記号を使うのかというと、キーボードに×や÷といったキーがないからです。 この+ - * /などの記号を演算子といいます。 またこの演算子の左右にある数字などをオペランドといいます。 このコードを実行すると以下のようになります。 実行結果 3 2 6 3 処理の順番は、まず計算式が実行され、計算式はその式の結果に置き換わります。 そして計算結果が、System.out.println();によって出力されます。 この、計算式がその結果に置き換わるということを、評価といいます。この評価をしっかりと理解することで後々出てくる、計算も理解しやすくなるので、しっかりと覚えておいてください。 (例) System.out.println(1+2);      評価 ↓ System.out.println(3);      出力 ↓         3 ここで一部の人はあることに気づいたかもしれません。 これはこの前のHello World!と表示するプログラムです。 Main.java public class Main { public static void main(String[] args){ System.out.println("Hello World!"); } } この、プログラムとさっきの計算をするプログラムを見比べてみてください。違いがわかりますか? 正解は、System.out.println();の引数が"で囲まれているかいないかです。 これにどのような意味があるかを文章で説明するのは難しいので実際の例を挙げます。 Main.java public class Main { public static void main(String[] args){ System.out.println("1+1"); } } このプログラムは一見2と表示されるように思えますが、実際に実行してみると以下のようになります。 実行結果 1+1 "で囲まれているかいないかでどんな差があるかわかったでしょうか? そう、"で囲まれた範囲は式として認識されず、ただの文字列としてそのまま表示されます。 割り算の注意点 計算はほとんど、数学と同じだったと思いますが、割り算だけは少し違います。 割り算の結果は、整数同士の場合、計算結果も整数になります。 ちなみに、計算式の片方でも少数だったら答えも少数になります。 (例) 5 / 2 → 2 3 / 2 → 1 3.0 / 2.0 → 2.5 また、%演算子を使うことによって割り算の余りを求めることができます。 (例) 5 % 2 → 1 3 % 2 → 1 演算子の優先順位 数学では掛け算や割り算は足し算や引き算よりも先に計算しますよね。 プログラムにも同じような優先順位があります。 優先度が高い演算子ほど、先に計算されます。 ※この優先度は、計算される順番をわかりやすくするために筆者が勝手につけたものです。なので順番さえわかれば覚える必要はありません 優先度 記号 意味 計算する方向 2 * 掛け算 左から右 2 / 割り算 左から右 2 % 割り算の余り 左から右 1 + 足し算 左から右 1 - 引き算 左から右 計算する方向というのは、同じ優先度のものがあったらどちらにあるものから先に計算されるかを示したものです。この表だとすべて左から右ですが今後出てくる演算子には右から左のものもあります。 なお、数学と同じように先に計算したい部分を()で囲むと先に計算させることができます。 演算子が2つ以上の計算 演算子が2つ以上の計算も、評価について知っていれば、簡単に仕組みを理解することができます。 3+6/2を例に説明します。 (1) この中で一番優先順位が高い演算子を探します。 この場合、一番優先順位が高い演算子は/です。 (2) 次に、(1)で見つけた演算子とその周りのオペランドを評価し置き換えます。 この場合、計算式は3+3に置き換わります。 (3)計算が完了するまでこれを繰り返します。 こういった仕組みで、演算子が2つ以上の計算式は実行されます。 文字列の連結 例えば、画面に1+1の答えは2ですと表示させたい場合、1+1の答えはという文字列と、1+1の計算結果と、ですという文字列の3つをくっつける必要があります。 これを文字列の連結といいます。 やり方はとてもシンプルです。単純にくっつけたいもの同士を+でつないであげるだけでいいんです。 Main.java public class Main { public static void main(String [] args){ System.out.println("1+1の答えは"+ (1+1) + "です"); } } 実行結果 1+1の答えは2です このコードで1+1が()で囲まれている理由は、+演算子は、左から順番に計算していくため、()で囲まないと1+1の計算がされる前に1+1の答えはという文字列に1がくっついてしまうからです。 最後に 今回は、計算と文字列の連結について解説しました。計算をすることで、一気にプログラミングをしている感が増してきたのではないでしょうか?次回は変数や分岐について解説しようと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

How to Update Android Apps

I'll explain how to update Android Apps. I am using Android Studio. [Steps] 1. Open "build.gradle" file on the Android Studio. 2. Update Version. We must set the versionCode as an Integer. (ex.) You must write the versionCode and version name in the file like this. versionCode 4 to 5 versionName "1.0.4" to "1.0.5" 3. Click "Sync Now" on the upper right. 4. After the sync, Click Build on the menu. And then, choose Generate Signed APK... 5. Choose "Android App Bundle" on another pop-up window and click next. 6. Set your Key store path and fill in the Key store password, Key alias, and Key password. After that, click next. 7. Choose your Build Variants, debug or release and click finish. 8. After executing tasks, the android studio generates the signed bundle apps. 9. Login Google Play Developer Console. 10. Pick the app up and click the production of the Release 11. Open the Releases Tab, and then you click "Create new release." 12. Upload the app bundle (.aab) file. 13. Fill in the release notes. 14. Click the save on the bottom. 15. After saving, click the review release. 16. Click "Start rollout to production" after checking the detail. Android アプリ更新の際の自分用のメモです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MinecraftでMODを開発したい#1

MinecraftでMODの開発をします 試行錯誤を書いていくだけのものになります 概要 環境構築をする 動作環境 2021/05/12 Version Mac OS Big Sur 11.1 IntelliJ IDEA 2021.1.1 AdoptOpenJDK (HotSpot) 1.8.0_282 Minecraft 1.16.5 Forge 36.1.0 目次 IntelliJ IDEAのインストール Forgeのインストール Example Modの削除 IntelliJ IDEAのインストール ダウンロードページから「Community」をダウンロード ダウンロードしたインストーラを実行し、デフォルト設定のまま画面に従ってインストール IntelliJ IDEAを起動し、タイトル画面で「New Project」を選択 「Project SDK」から「Download JDK」を選択 「Version」に「1.8」、「Vendor」に「AdoptOpenJDK (HotSpot)」を指定し、「Download」 「Project SDK」に「adopt-openjdk-1.8」が選択されていることを確認する Forgeのインストール ダウンロードページから1.16.5を選択し、「Download Recommended」の「Mdk」をダウンロード ダウンロードしたzipファイルを解凍し、任意の場所に移動させておく IntelliJ IDEAを起動して解凍したファイルを選択 自動で読み込みが始まるので、右下の進捗表示が完了するまで待つ 画面右側のTool Window Barにある「Gradle」を選択し、GradleのTool Windowを開く Tasks > fg_runsと階層を下りて「genIntellijRuns」をダブルクリックすると、実行構成が自動で作成される 「BUILD SUCCESSFUL」の表示がでれば成功 Terminalから$ ./gradlew genIntellijRunsを実行でもできる Gradle Tool Window左上の同期ボタン(Reload All Gradle Projects)を押す 画面右上の「TitaniumMod [genIntellijRuns]」などと表示されている実行構成選択ボタンを押して「runClient」を選択 実行ボタンを押して、Minecraftが起動すれば成功 起動しない場合、Terminalから$ ./gradlew runClientを実行すると起動できる場合がある Example Modの削除 src/main/java/にあるcom.example.examplemodを削除 com.exampleが残るので削除 src/main/javaを右クリックし、New > Packageからcom.ドメイン名.examplemodパッケージを作成 com.ドメイン名.examplemodを右クリックし、New > Java ClassからExampleModを作成 src/main/resources/META-INF/mods.tomlを開き、modId="examplemod"をmodId="examplemod"に変更(*今回はMOD名を変更しないため変更なしとする) changelog.txt、CREDITS.txt、LICENSE.txt、README.txtを削除 参考文献 https://www.tntmodders.com/tutorial/env-1165/ https://qiita.com/niwasawa/items/ca565091468abce48f53
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む