More Related Content More from Unity Technologies Japan K.K. (20) 【Unity道場スペシャル 2018京都】プロなら当然!プログラミング技能解説6. 曖昧さがない
int a = 1 + 2 * 3;
2*3が先に計算される
int a = (1 + 2) * 3;
1+2が先に計算される
自然言語 プログラム言語
美しい王国の姫
ハッキリ
しなさいよ
美しいのは王国?姫?
11. 1.字句解析
public class A {
int c = 0;
• スペースは単語の区切り
• 改行も単語の区切り
• ; は式の区切り
• {} は始まりと終わり
public class A {
int c = 0;
単語や記号の区切りを検出
12. public class Test : MonoBehaviour { void Start(){} void Update(){} }
public class Test : MonoBehaviour {
void Start() {
}
void Update() {
}
}
一行にまとめても同じ
字句解析を
理解すれば
15. void Start() {
int a = 10;
}
構文解析を
理解すれば
void Start() {
int a = ((((10))));
}
()をたくさん書いても問題なし
16. #define/*__Int3rn^ti[]n/l_()I3fusc^t3|]_C_C<>I7E_C[]nt3st__*/L/*__MMXVIII__*/for
#include/*!"'()*+,-./12357:;<=>?CEFGHIJKLMNSTUVWXYZ[]^_`cfhijklmnrstuvwxyz{|}*/<stdio.h>
char*r,F[1<<21]="~T/}3(|+G{>/zUhy;Jx+5wG<v>>u55t.?sIZrC]n.;m+:l+Hk]WjNJi/Sh+2f1>c2H`)(_2(^L
-]=([1/Z<2Y7/X12W:.VFFU1,T77S+;N?;M/>L..K1+JCCI<<H:(G*5F--E11C=5?.(>+(=3)Z-;*(:*.Y/5(-=)2*-U,
/+-?5'(,+++***''EE>T,215IEUF:N`2`:?GK;+^`+?>)5?>U>_)5GxG).2K.2};}_235(]:5,S7E1(vTSS,-SSTvU(<-HG
-2E2/2L2/EE->E:?EE,2XMMMM1Hy`)5rHK;+.T+?[n2/_2{LKN2/_|cK2+.2`;}:?{KL57?|cK:2{NrHKtMMMK2nrH;rH[n"
"CkM_E21-E,-1->E(_:mSE/LhLE/mm:2Ul;2M>,2KW-+.-u).5Lm?fM`2`2nZXjj?[n<YcK?2}yC}H[^7N7LX^7N7UN</:-
ZWXI<^I2K?>T+?KH~-?f<;G_x2;;2XT7LXIuuVF2X(G(GVV-:-:KjJ]HKLyN7UjJ3.WXjNI2KN<l|cKt2~[IsHfI2w{[<VV"
"GIfZG>x#&#&&$#$;ZXIc###$&$$#>7[LMv{&&&&#&##L,l2TY.&$#$#&&$,(iiii,#&&&#$#$?TY2.$#$1(x###;2EE[t,
SSEz.SW-k,T&&jC?E-.$## &#&57+$$# &&&W1-&$$7W -J$#$kEN&#& $##C^+$##W,h###n/+L2YE"
"2nJk/H;YNs#$[,:TU(#$ ,: &&~H>&# Y; &&G_x ,mT&$YE-#& 5G $#VVF$#&zNs$$&Ej]HELy
CN/U^Jk71<(#&:G7E+^&# l|?1 $$Y.2$$ 7lzs WzZw>&$E -<V-wE(2$$ G>x; 2zsW/$$#HKt&$$v>+t1(>"
"7>S7S,;TT,&$;S7S>7&#>E_::U $$'",op ,*G= F,*I=957+F ;int*t,k,O, i, j,T[+060<<+020];int M(
int m,int nop){;;;return+ m%(0+nop );;} int*tOo,w, h,z,W;void(C) (int n){n=putchar(n);}int
f,c,H=11,Y=64<<2,Z,pq,X ;void(E/*d */)( int/*RP*/n ){L(Z=k+00; Z; Z/=+2+000)G[000]=*G*!!f
|M(n,2)<<f,pq=2,f=+06 <f?++pq,++pq ,G++ ,z:f+001,n /=2;;}void (V)( int/*opqrstabd*/n){C(n
%Y);;C(n/Y+00);;}void J(){L(pq--,pq =j =O=-1+0;++ j<240;I[6+ (h +6+j/12/2*2+M(j/2,2))*
W+M(j/2/2,+06)*2+w*014 +00+M(00+ 000+j,002 +00)]=000 +00+k)k=M(G[j/2/2+(*r-+
32)**"<nopqabdeg"],/*4649&96#*/3);/*&oaogoqo*/;}/*xD%P$Q#Rq*/int/*dbqpdbqpxyzzyboo3570OQ*/main()
{L(X=Y-1;i<21*3;i++,I++)L(r=G,G+=2;*G++;)*G>=13*3?*G-*r?*I++=*G:(*I++=r[1],*I++=r[2]):1;L(j=12,r
=I;(*I=i=getchar())>-1;I++)i-7-3?I-=i<32||127<=i,j+=12:(H+=17+3,W=W<j?j:W,j=12);L(;*r>-1;r++)*r-
7-3?J(),w++:(w=z,h+=17+3);C(71);C(73);V('*'*'1'*7);C(57);C(32*3+1);V(W);V(H);C(122*2);L(V(i=z);i
<32*3;)C(i++/3*X/31);C(33);C(X);C(11);L(G="SJYXHFUJ735";*G;)C(*G++-5);C(3);V(1);L(V(j=z);j<21*3;
j++){k=257;V(63777);V(k<<2);V(M(j,32)?11:511);V(z);C(22*2);V(i=f=z);V(z);V(W);V(H);V(1<<11);r=
G=I+W*H;L(t=T;i<1<<21;i++)T[i]=i<Y?i:-1;E(Y);L(i=-1;++i<W*H;t=T+Z*Y+Y)c=I[i]?I[i]*31-31:(31<
j?j-31:31-j),Z=c[t[c]<z?E(Z),k<(1<<12)-2?t[c]=++k,T:T:t];E(Z);E(257);L(G++;k=G-r>X?X:G-r
,C(k),k;)L(;k--;C(*r++/*---#$%&04689@ABDOPQRabdegopq---*/));}C(53+6);return(z);}
https://www.ioccc.org/2018/endoh1/prog.c
参考:IOCCC(国際難読化Cコードコンテスト)
21. int f(int x) {
return x*x - 1;
}
f 2
− 1xx( ) = 関数の定義
関数の評価
(呼び出し)
f 10( )=y y = f(10);
数学 プログラム
22. int f(int x) {
return x*x - 1;
}
関数は必ず結果を返す
f 2
− 1xx( ) = 関数の定義
関数の評価
(呼び出し)
f 10( )=y y = f(10);
数学 プログラム
24. int f(int x) {
return x*x - 1;
}
関数は引数と返り値がある
f 2
− 1xx( ) = 関数の定義
関数の評価
(呼び出し)
f 10( )=y y = f(10);
数学 プログラム返り値が
整数 引数が
整数
26. ??? f(int x) {
処理
return;
}
プログラムでは、値を返さないこともある
構文解析しやすいように
??? はvoid
と書くことにしよう
値を返さない!
・・・ということでした
35. class Date {
long year;
long month;
long day;
}
2148685152
2148685160
2148685168
2148685176
2148685184
2148685192
2148685200
2148685208
2148685144
2148685136
2148685128
この時点では何も起きない
36. 2018
11
24
Date d = new Date();
2148685152
2148685160
2148685168
2148685176
2148685184
2148685192
2148685200
2148685208
2148685144
2148685136
2148685128class Date {
long year;
long month;
long day;
} メモリが確保される
40. struct Date {
long year;
long month;
long day;
}
2148685152
2148685160
2148685168
2148685176
2148685184
2148685192
2148685200
2148685208
2148685144
2148685136
2148685128
classを
structに変える
45. int a = b + c;
int d = a * 2;
一時変数を使う記述
int d = (b+c) * 2;
一時変数を使わない記述
46. Rigidbody rb = GetComponent<Rigidbody>();
rb.AddForce(f);
一時変数を使う記述
一時変数を使わない記述
GetComponent<Rigidbody>().AddForce(f);
51. Vector3 pos = transform.position;
pos.x = 10;
transform.position = pos;
正しい書き方
transform.position は
実体返しだから
複製のposを代入する
複製にposという名前を与える
52. void func(int x) {
x = 10;
}
引数の値を変更したら?
Debug.Logに渡されるのは 5? 10?
int x = 5;
func(x);
Debug.Log(x);
53. void func(int x) {
x = 10;
}
引数の値を変更したら?
Debug.Logに渡されるのは 5? 10?
int x = 5;
func(x);
Debug.Log(x);
この関数は
無意味
実体を
更新している
54. void func(int[] x) {
x[0] = 10;
}
引数の値を変更したら?
Debug.Logに渡されるのは 5? 10?
int[] x = {5};
func(x);
Debug.Log(x[0]);
55. void func(int[] x) {
x[0] = 10;
}
引数の値を変更したら?
Debug.Logに渡されるのは 5? 10?
int[] x = {5};
func(x);
Debug.Log(x[0]);
参照を
更新している
この関数は
狙い通り
56. List<Quaternion> rots = new List<Quaternion>();
rots[0]. SetLookRotation(Vector3.up);
エラーすら出てくれない例
rots[0]に変化なし!(実体返しなので)
Quaternion[] rots = new Quaternion[10];
rots[0]. SetLookRotation(Vector3.up);
期待通りに動作
76. delegate void MyFunc();
void Update() {
MyFunc h = f;
h();
}
void f() {
…
}
関数fを変数に入れたい
関数fと同じ返り値と引数で
delegate宣言
MyFuncで定義した
変数hにfを代入
変数hを実行
77. static void OnMouseButton0() {
…
}
void Start() {
set(OnMouseButton0);
}
delegate void MyFunc();
static MyFunc cb;
static void set(MyFunc f) { cb = f; }
void Update() {
if (Input.GetMouseButton(0)) {
cb();
}
}
プル型を
プッシュ型に変換
装置
呼んで欲しい関数
呼んで欲しい関数をセット
78. switch (n) {
case 0: func0(); break;
case 1: func1(); break;
case 2: func2(); break;
case 3: func3(); break;
case 4: func4(); break;
case 5: func5(); break;
case 6: func6(); break;
case 7: func7(); break;
}
func[n]();
delegateを使うと・・・
87. プログラム
int f(int n) {
if (n <= 0)
return 0;
else
return f(n-1);
}f(n) = f( −1)n
f(n) = 0
≤ 0n のとき
> 0n のとき
数式
91. [MenuItem("GameObject/DumpName", false, 0)]
static void DumpName() {
var obj = Selection.activeGameObject;
string str = createString(obj.transform);
Debug.Log(str);
}
static string createString(Transform tfm) {
string name = "";
name += tfm.name + "n";
foreach(Transform child in tfm) {
name += createString(child);
}
return name;
}
92. [MenuItem("GameObject/DumpName(Indent)", false, 0)]
static void DumpNameIndent() {
var obj = Selection.activeGameObject;
string str = createString(obj.transform, 0);
Debug.Log(str);
}
static string createString(Transform tfm, int indent) {
string name = "";
for (int i = 0; i < indent; ++i) name += " ";
name += tfm.name + "n";
foreach(Transform child in tfm) {
name += createString(child, indent+4);
}
return name;
}
94. var g = new GameObject();
g.AddComponent<MyScript>();
AddComponentすると
class MyScript: MonoBehaviour {
void Start() {
}
}
Startが呼ばれる
これを利用して再帰プログラムを書いてみよう
Start で AddComponent すると・・・?
95. using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fractal : MonoBehaviour {
[SerializeField] Mesh mesh_;
[SerializeField] Material material_;
const int MAX_DEPTH = 7;
Vector3 start_ = Vector3.zero;
Vector3 end_ = Vector3.up;
float width_ = 0.1f;
int depth_ = 0;
void initialize(Fractal parent, float given_length, float given_width,
Quaternion given_rotation, int depth)
{
mesh_ = parent.mesh_;
material_ = parent.material_;
transform.position = parent.transform.position + Vector3.up;
start_ = parent.end_;
end_ = start_ + given_rotation * (Vector3.up * given_length);
width_ = given_width;
depth_ = depth;
}
IEnumerator Start()
{
gameObject.AddComponent<MeshFilter>().mesh = mesh_;
gameObject.AddComponent<MeshRenderer>().material = material_;
transform.position = (start_ + end_) * 0.5f;
var diff = end_ - start_;
var length = diff.magnitude;
transform.rotation = Quaternion.LookRotation(diff) *
Quaternion.Euler(90f, 0f, 0f);
transform.localScale = new Vector3(width_, length * 1f, width_);
if (depth_ >= MAX_DEPTH)
yield break;
float roty = Random.Range(0f, 360f);
for (var i = 0; i < 5; ++i) {
if (Random.Range(0, 2) != 0)
continue;
yield return new WaitForSeconds(0.1f);
var child = new GameObject();
child.name = gameObject.name;
var fractal = child.AddComponent<Fractal>();
fractal.initialize(this,
length * 0.75f,
width_ * 0.75f,
transform.rotation * Quaternion.Euler(30f, roty, 0f),
depth_+1);
roty += 137.5f;
97. using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fractal : MonoBehaviour {
[SerializeField] Mesh mesh_;
[SerializeField] Material material_;
const int MAX_DEPTH = 7;
Vector3 start_ = Vector3.zero;
Vector3 end_ = Vector3.up;
float width_ = 0.1f;
int depth_ = 0;
void initialize(Fractal parent, float given_length, float given_width,
Quaternion given_rotation, int depth)
{
mesh_ = parent.mesh_;
material_ = parent.material_;
transform.position = parent.transform.position + Vector3.up;
start_ = parent.end_;
end_ = start_ + given_rotation * (Vector3.up * given_length);
width_ = given_width;
depth_ = depth;
}
IEnumerator Start()
{
gameObject.AddComponent<MeshFilter>().mesh = mesh_;
gameObject.AddComponent<MeshRenderer>().material = material_;
transform.position = (start_ + end_) * 0.5f;
var diff = end_ - start_;
var length = diff.magnitude;
transform.rotation = Quaternion.LookRotation(diff) *
Quaternion.Euler(90f, 0f, 0f);
transform.localScale = new Vector3(width_, length * 1f, width_);
if (depth_ >= MAX_DEPTH)
yield break;
float roty = Random.Range(0f, 360f);
for (var i = 0; i < 5; ++i) {
if (Random.Range(0, 2) != 0)
continue;
yield return new WaitForSeconds(0.1f);
var child = new GameObject();
child.name = gameObject.name;
var fractal = child.AddComponent<Fractal>();
fractal.initialize(this,
length * 0.75f,
width_ * 0.75f,
transform.rotation * Quaternion.Euler(30f, roty, 0f),
depth_+1);
roty += 137.5f;再掲