㈠ A*搜尋演算法的代碼實現(C語言實現)
用C語言實現A*最短路徑搜索演算法,作者 Tittup frog(跳跳蛙)。 #include<stdio.h>#include<math.h>#defineMaxLength100 //用於優先隊列(Open表)的數組#defineHeight15 //地圖高度#defineWidth20 //地圖寬度#defineReachable0 //可以到達的結點#defineBar1 //障礙物#definePass2 //需要走的步數#defineSource3 //起點#defineDestination4 //終點#defineSequential0 //順序遍歷#defineNoSolution2 //無解決方案#defineInfinity0xfffffff#defineEast(1<<0)#defineSouth_East(1<<1)#defineSouth(1<<2)#defineSouth_West(1<<3)#defineWest(1<<4)#defineNorth_West(1<<5)#defineNorth(1<<6)#defineNorth_East(1<<7)typedefstruct{ signedcharx,y;}Point;constPointdir[8]={ {0,1},//East {1,1},//South_East {1,0},//South {1,-1},//South_West {0,-1},//West {-1,-1},//North_West {-1,0},//North {-1,1}//North_East};unsignedcharwithin(intx,inty){ return(x>=0&&y>=0 &&x<Height&&y<Width);}typedefstruct{ intx,y; unsignedcharreachable,sur,value;}MapNode;typedefstructClose{ MapNode*cur; charvis; structClose*from; floatF,G; intH;}Close;typedefstruct//優先隊列(Open表){ intlength; //當前隊列的長度 Close*Array[MaxLength]; //評價結點的指針}Open;staticMapNodegraph[Height][Width];staticintsrcX,srcY,dstX,dstY; //起始點、終點staticCloseclose[Height][Width];//優先隊列基本操作voidinitOpen(Open*q) //優先隊列初始化{ q->length=0; //隊內元素數初始為0}voidpush(Open*q,Closecls[Height][Width],intx,inty,floatg){ //向優先隊列(Open表)中添加元素 Close*t; inti,mintag; cls[x][y].G=g; //所添加節點的坐標 cls[x][y].F=cls[x][y].G+cls[x][y].H; q->Array[q->length++]=&(cls[x][y]); mintag=q->length-1; for(i=0;i<q->length-1;i++) { if(q->Array[i]->F<q->Array[mintag]->F) { mintag=i; } } t=q->Array[q->length-1]; q->Array[q->length-1]=q->Array[mintag]; q->Array[mintag]=t; //將評價函數值最小節點置於隊頭}Close*shift(Open*q){ returnq->Array[--q->length];}//地圖初始化操作voidinitClose(Closecls[Height][Width],intsx,intsy,intdx,intdy){ //地圖Close表初始化配置 inti,j; for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { cls[i][j].cur=&graph[i][j]; //Close表所指節點 cls[i][j].vis=!graph[i][j].reachable; //是否被訪問 cls[i][j].from=NULL; //所來節點 cls[i][j].G=cls[i][j].F=0; cls[i][j].H=abs(dx-i)+abs(dy-j); //評價函數值 } } cls[sx][sy].F=cls[sx][sy].H; //起始點評價初始值 // cls[sy][sy].G=0; //移步花費代價值 cls[dx][dy].G=Infinity;}voidinitGraph(constintmap[Height][Width],intsx,intsy,intdx,intdy){ //地圖發生變化時重新構造地 inti,j; srcX=sx; //起點X坐標 srcY=sy; //起點Y坐標 dstX=dx; //終點X坐標 dstY=dy; //終點Y坐標 for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { graph[i][j].x=i;//地圖坐標X graph[i][j].y=j;//地圖坐標Y graph[i][j].value=map[i][j]; graph[i][j].reachable=(graph[i][j].value==Reachable); //節點可到達性 graph[i][j].sur=0;//鄰接節點個數 if(!graph[i][j].reachable) { continue; } if(j>0) { if(graph[i][j-1].reachable) //left節點可以到達 { graph[i][j].sur|=West; graph[i][j-1].sur|=East; } if(i>0) { if(graph[i-1][j-1].reachable &&graph[i-1][j].reachable &&graph[i][j-1].reachable) //up-left節點可以到達 { graph[i][j].sur|=North_West; graph[i-1][j-1].sur|=South_East; } } } if(i>0) { if(graph[i-1][j].reachable) //up節點可以到達 { graph[i][j].sur|=North; graph[i-1][j].sur|=South; } if(j<Width-1) { if(graph[i-1][j+1].reachable &&graph[i-1][j].reachable &&map[i][j+1]==Reachable)//up-right節點可以到達 { graph[i][j].sur|=North_East; graph[i-1][j+1].sur|=South_West; } } } } }}intbfs(){ inttimes=0; inti,curX,curY,surX,surY; unsignedcharf=0,r=1; Close*p; Close*q[MaxLength]={&close[srcX][srcY]}; initClose(close,srcX,srcY,dstX,dstY); close[srcX][srcY].vis=1; while(r!=f) { p=q[f]; f=(f+1)%MaxLength; curX=p->cur->x; curY=p->cur->y; for(i=0;i<8;i++) { if(!(p->cur->sur&(1<<i))) { continue; } surX=curX+dir[i].x; surY=curY+dir[i].y; if(!close[surX][surY].vis) { close[surX][surY].from=p; close[surX][surY].vis=1; close[surX][surY].G=p->G+1; q[r]=&close[surX][surY]; r=(r+1)%MaxLength; } } times++; } returntimes;}intastar(){ //A*演算法遍歷 //inttimes=0; inti,curX,curY,surX,surY; floatsurG; Openq;//Open表 Close*p; initOpen(&q); initClose(close,srcX,srcY,dstX,dstY); close[srcX][srcY].vis=1; push(&q,close,srcX,srcY,0); while(q.length) { //times++; p=shift(&q); curX=p->cur->x; curY=p->cur->y; if(!p->H) { returnSequential; } for(i=0;i<8;i++) { if(!(p->cur->sur&(1<<i))) { continue; } surX=curX+dir[i].x; surY=curY+dir[i].y; if(!close[surX][surY].vis) { close[surX][surY].vis=1; close[surX][surY].from=p; surG=p->G+sqrt((curX-surX)*(curX-surX)+(curY-surY)*(curY-surY)); push(&q,close,surX,surY,surG); } } } //printf("times:%d ",times); returnNoSolution;//無結果}constintmap[Height][Width]={ {0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,1}, {0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1}, {0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,1}, {0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1}, {0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}, {0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0}, {0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,1}, {0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0}};constcharSymbol[5][3]={"□","▓","▽","☆","◎"};voidprintMap(){ inti,j; for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { printf("%s",Symbol[graph[i][j].value]); } puts(""); } puts("");}Close*getShortest(){ //獲取最短路徑 intresult=astar(); Close*p,*t,*q=NULL; switch(result) { caseSequential: //順序最近 p=&(close[dstX][dstY]); while(p) //轉置路徑 { t=p->from; p->from=q; q=p; p=t; } close[srcX][srcY].from=q->from; return&(close[srcX][srcY]); caseNoSolution: returnNULL; } returnNULL;}staticClose*start;staticintshortestep;intprintShortest(){ Close*p; intstep=0; p=getShortest(); start=p; if(!p) { return0; } else { while(p->from) { graph[p->cur->x][p->cur->y].value=Pass; printf("(%d,%d)→ ",p->cur->x,p->cur->y); p=p->from; step++; } printf("(%d,%d) ",p->cur->x,p->cur->y); graph[srcX][srcY].value=Source; graph[dstX][dstY].value=Destination; returnstep; }}voidclearMap(){ //ClearMapMarksofSteps Close*p=start; while(p) { graph[p->cur->x][p->cur->y].value=Reachable; p=p->from; } graph[srcX][srcY].value=map[srcX][srcY]; graph[dstX][dstY].value=map[dstX][dstY];}voidprintDepth(){ inti,j; for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { if(map[i][j]) { printf("%s",Symbol[graph[i][j].value]); } else { printf("%2.0lf",close[i][j].G); } } puts(""); } puts("");}voidprintSur(){ inti,j; for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { printf("%02x",graph[i][j].sur); } puts(""); } puts("");}voidprintH(){ inti,j; for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { printf("%02d",close[i][j].H); } puts(""); } puts("");}intmain(intargc,constchar**argv){ initGraph(map,0,0,0,0); printMap(); while(scanf("%d%d%d%d",&srcX,&srcY,&dstX,&dstY)!=EOF) { if(within(srcX,srcY)&&within(dstX,dstY)) { if(shortestep=printShortest()) { printf("從(%d,%d)到(%d,%d)的最短步數是:%d ", srcX,srcY,dstX,dstY,shortestep); printMap(); clearMap(); bfs(); //printDepth(); puts((shortestep==close[dstX][dstY].G)?"正確":"錯誤"); clearMap(); } else { printf("從(%d,%d)不可到達(%d,%d) ", srcX,srcY,dstX,dstY); } } else { puts("輸入錯誤!"); } } return(0);}
㈡ [UE4虛幻引擎教程]-003-游戲框架的基本概念:第一個玩家控制器
前排看文檔啦,看懂了就不用看下面這些廢話啦: https://docs.unrealengine.com/latest/CHN/Gameplay/Framework/index.html
來咱先看個簡單的例子:
以上的例子是不是簡單明了一看就懂呢?(並不……)
好吧沒事以後就慢慢懂了,來我們一起動手做一遍吧……
實戰部分:
註:學習本節你至少得知道引擎的界面吧……
再註:使用引擎自帶模板 ThirdPerson 進行參考,人家藍圖里都寫著呢……
再再註:推薦學習: 3小時速攻UE4
然後讓我們打開上一節創建的工程,在對象瀏覽器中點擊右鍵創建一個新的文件夾,起名為BluePrints,然後分別創建一個GameMode,一個PlayController和一個Character,記得規范命名哦,藍圖前面都帶上BP前綴。
然後在設置中打開世界設置,在世界設置面板中指定新建好的GameMode,playcontroller和character。此時點擊播放運行,如果設置正確的話會發現無法旋轉視角和移動。在這里需要注意的一點是,可以為整個游戲設定同一個GameMode,也可以單獨為一個場景設置GameMode,而且在發布程序的時候,需要在:編輯》項目設置》地圖模式》中指定GameMode和開始時的場景。
OK,現在來進行輸入控制吧,打開 編輯》項目設置》輸入 ,點擊Axis Mappings選項後的加號,創建輸入映射,起名為Turn,選擇對應輸入為滑鼠X,再創建一個映射,起名為LookUp,選擇滑鼠Y,並設置為-1。
關於此處映射,其實就是一個總體設定,方便以後的多輸入支持,比如綁定滑鼠輸入和手柄輸入之類的,如果不懂,可以看文檔這里: 輸入
雙擊建好的Character,在事件圖表中框選默認的事件,按delete刪除,然後右擊輸入trun,創建之前映射好的輸入Trun事件,再拖拽出新節點,輸入Add Controller Yaw Input,創建節點,並將輸毀早備入事件的值拖拽連接到Input節點的值上,如法創建LookUp事件,並連接Add Controller Pitch Input節點,最後選中所有節點,按C創建注釋面板,添加註釋以便識別。這時候點擊編譯,再關閉面板,然後播放場景,就會發現滑鼠可以控制視角改變了。
而關於Add Controller Yaw Input是什麼鬼呢,再來看文檔吧: Pawn Input
再次創建輸入映射,創建一個MoveFrward和一個MoveRight,如圖,注意值
然後來看輸入的藍圖,首先通過 Get Control Rotation 獲取睜塌到旋轉的值,這個值是個Rotator三維向量,由於我們只需要Z軸方向的值,所以需要break解開,再Make組成一個新的Rotator值, Get forward Vector 獲取到當前面向的正纖毀面方向,再通過Add Movement Input增加該方向的值,就完成了向前移動。
最後運行,就能自由移動和旋轉視角了,記得把地形改大點喲,不然掉下去就得重來了。
角色的創建:
由於我們一開始創建的是Character模型,自帶的mesh組件只能丟個特定的人形模型上去,於是我們再給他添加一個static mesh,然後隨便丟個啥玩意上去,我扔了個圓錐……調整合適的大小,至少在包裹的碰撞盒內吧……意思意思一下就行。
運行一下,轉動下視角,你會發現能看到有東西了,再回到character里,添加個 springArm ,然後將相機拖到下面,再勾選個使用pawn controller Rotation(此處很重要),如果你要玩第三人稱,距離就遠點,第一人稱,就設成0,約莫就醬紫了……
好,最後閑得無聊的我給Character加了倆棒子,就當這就是手了……記得加到arm下,這樣可以跟著視角旋轉。
啊對了我們是不是忘記PlayController了?主要是寫多了怕你們消化不良,所以咱就簡單加個功能吧,比如……HelloWord?
來在輸入中添加個動作映射,記得是Action Mappings,不是Axis喲,我比較習慣用F,其他的你看著辦了,然後打開PlayController,拖出節點,連個print,再運行,按F,屏幕上就出現Hello了。
哈哈哈哈哈這篇文章是不是很簡單很強大發現一看就會呢,其實就是天天加班沒時間好好寫而已啦(就是懶),好吧其實這個真的是基礎中的基礎沒啥好講的,下一篇的會比較多的實操,做一些無聊的小功能啦,親們可以先去看下藍圖的使用,作者估計就是一個動圖,一個藍圖截圖就講一個模塊啦,所以可以先預習下,就醬,諸君晚安……
㈢ 運用虛幻4需要學什麼
想要用虛幻4做游戲,會用虛幻4引擎就可以了。學習游戲設計,推薦翼狐網,在線靈活學習,不受地域時間限制,海內外知名講師眾多,實戰經驗豐富,值緩前得信賴。【進入官網,立即領取¥600 新人專屬大禮包 0元體驗VIP特權】
游戲規則設定是策劃的工作,先明確要做什麼類型的游戲,游戲復雜度,有哪些系統機制,數值,開發周期等等。定位好要做什麼類型的游戲就去找相關類型的游戲,分析它們的優缺點。起初可以模仿它們的設定,熟練以後整理出自己的理論。把這些規則變為現實,就是程序的笑哪滾工作,會c++就用c++不會就用虛幻的藍圖,藍圖可以將你的想法快速做出效果,也能反推想法的合理性。
想要了解更多關於虛幻4的信息,推薦咨詢翼狐碰余。翼狐網立足於實用性的要求,精選各類課程,與國內外資深講師、權威教育培訓機構建立合作,共同研發出數量可觀且製作精良的獨家課程,其中涵蓋了實用軟體、CG電影、游戲製作、C4D、平面設計、原畫設計、動畫製作、環境藝術、影視製作、工業設計、攝影修圖等十餘大門類課程,致力於打造國際頂尖的數字藝術在線學習平台,在同行業中有很高的美譽度。
㈣ python實現M-C問題的A*演算法,採用h(n)=m+c-2b(或具有更多啟發信息的)作為啟發
M-C問題是一個經典的人工智慧問題,它描述了一個傳教士和食人族的河岸過河問題。A*演算法是一種啟發式搜索演算法,它可以找到從初始狀態到目標狀態的最優路徑。A*演算法的核心是使用一個函數f(n)來評估每個狀態的優先順序,f(n)等於g(n)和h(n)的和,其中g(n)是從初始狀態到當前狀態的實際代價,h(n)是從當前狀態到目標狀態的預估代價。h(n)越接近真實代價,A*演算法越有效。
為了用Python實現M-C問題的A*演算法,我們需要定義以下幾個部分:
- 狀態:一個狀態是一個三元組(m, c, b),型腔表示河的左岸有m個傳教士,c個食人族,b為1表示旅唯船在左岸,為0表示船在右岸。
- 初始狀態:(3, 3, 1),表示左岸有3個傳教士,3個食人族,船在左岸。
- 目標狀態:(0, 0, 0),表示左岸沒有傳教士,沒有食人族,船在右岸。
- 操作:一個操作是一個二元組(x, y),表示從當前岸向另一岸運送x個傳教士,y個食人族,滿足以下條件:
- 0 <= x <= 1,0 <= y <= 2,x + y <= 2,x + y > 0,表示每次最多運送兩個人,最少運送一個人,可以是傳教士或者食人族。
- 如果b為1,表示船在左岸,那麼m >= x,c >= y,表示不能運送超過當前岸的人數。
- 如果b為0,表示船在右岸,那麼m <= 3 - x,c <= 3 - y,表示不能運送超過另一岸的人數。
- 在任何一岸,傳教士的人數不能少於食人族的人數,除非傳教士的人數為0,表示不會被吃掉。
- g(n):從初始狀態到當前狀態的實際代價,可以簡單地定義為已經運送的人數。
- h(n):從當前狀態到目標狀態的預估代價,可以根據題目給出的公式定義為h(n) = m + c - 2b,或者使用其他更有啟發性的公式,例如h(n) = max(m, c) - b,表示至少需要運送的次數。
Python代碼實現:
```python
# 定義狀態類
class State:
def __init__(self, m, c, b):
self.m = m # 左岸的傳教士數
self.c = c # 左岸的食人族數
self.b = b # 船的位置,1為左岸,0為右岸
def __eq__(self, other):
# 判斷兩個狀態是否相等
return self.m == other.m and self.c == other.c and self.b == other.b
def __hash__(self):
# 為了將狀態作為字典的鍵,需要定義哈希函數
return hash((self.m, self.c, self.b))
def __str__(self):
# 為了方便列印狀態卜鎮衫,需要定義字元串表示
return f"({self.m}, {self.c}, {self.b})"
def is_valid(self):
# 判斷一個狀態
㈤ 怎麼用C語言繪制3D圖形,實現類似於UE4這樣的效果
我先給個例子,#include <graphics.h>
#include<stdlib.h>
#include<stdio.h>
#include "conio.h"
#include"math.h"
void main()
{
int gdriver=DETECT,gmode; /*圖形模式設定*/
char f;
int m,n,x,y,t;
int color;
x=320;y=240;
m=0;n=0;
initgraph(&gdriver,&gmode,"c: \\tc");
printf("qweadzxc stand for eight direction,p to exit,and the number stand for color when paint\n");
printf("input anykey to start\n");
getch();
printf("PLEASE INPUT THE COLOR\n");
scanf("%d",&color);
loop:
while(!kbhit())
{
putpixel(x,y,color);
x=x+m;y=y+n;
for(t=0;t<=50;t++)
delay(100);
}
f=getch();
if(f=='w'||f=='W')
{
m=0;n=-1;
goto loop;
}
if(f=='x'||f=='X')
{
m=0;n=1;
goto loop;
}
if(f=='a'||f=='A')
{
m=-1;n=0;
goto loop;
}
if(f=='d'||f=='D')
{
m=1;n=0;
goto loop;
}
if(f=='q'||f=='Q'慶配)
{
m=-1;n=-1;
goto loop;
}
if(f=='e'||f=='E')
{
m=1;n=-1;
goto loop;
}
if(f=='橘純z'||f=='Z')
{
m=-1;n=1;
goto loop;
}
if(f=='c'||f=='C')
{
m=1;n=1;
goto loop;
}
if(f==' ')
{
m=0;n=0;
getch();
goto loop;
}
if(f=='圓差咐p'||f=='P')
goto end;
if(f=='s'||f=='S')
{
printf("please input the color you want to set\n");
scanf("%d",&color);
goto loop;
}
else
{
printf("ERROR!\n");
goto loop;
}
end:
getch();
closegraph(); /*退出圖形模式*/
}
㈥ UE4怎麼做去哪裡學習UE4
你可以先去【繪學霸】網站找「游戲特效/unity3D」板塊的【免費】視頻教程-【點擊進入】完整入門到精通視頻教程列表: www.huixueba.net/web/AppWebClient/AllCourseAndResourcePage?type=1&tagid=306&zdhhr-11y04r-1242922119980144339
想要系統的學習可以考慮報一個網路直播課,推薦CGWANG的網路課。老師講得細,上完還可以回看,還有同類型錄播課可以免費學(贈送終身VIP)。
自製能力相對較弱的話,建議還是去好點的培訓機構,實力和規模在國內排名前幾的大機構,推薦行業龍頭:王氏教育。
王氏教育全國直營校區面授課程試聽【復制後面鏈接在瀏覽器也可打開】:
www.cgwang.com/course/gecoursemobilecheck/?zdhhr-11y04r-1242922119980144339
在「游戲特效/unity3D」領域的培訓機構里,【王氏教育】是國內的老大,且沒有加盟分校,都是總部直營的連鎖校區。跟很多其它同類型大機構不一樣的是:王氏教育每個校區都是實體面授,老師是手把手教,而且有專門的班主任從早盯到晚,爆肝式的學習模式,提升會很快,特別適合基礎差的學生。
大家可以先把【繪學霸】APP下載到自己手機,方便碎片時間學習——繪學霸APP下載: www.huixueba.com.cn/Scripts/download.html
㈦ 問一下虛幻4引擎如果想自己做游戲是不是很難,很耗時間那個難學嗎我初中畢業後那一個暑假可以熟練掌
這個問題其實很難回答,這取決於你的基礎和決心,我學ue4,在入門到進階,可以自己製作大型單機游戲的水平其實只花了一個暑假時間,完整動手自學了何偉的《ue4從入門到精通》以及網路教程。但是這個暑假是大二的暑假,在這之前我有過兩年的c++學習,比賽,實踐經歷,實習經歷,其實對於ue4我的感覺是入門難度不高,但是精通難度很高,教材的選擇很重要,然後就是決心,我學習ue4之前有過996經驗,所以學c++,ue4,包括現在考研都會有每日10個小時的學習時間,最後就是動手非常非常重要,整個ue4學習,必須是學到哪做到哪,不會動手等於白學。對於提問者,相比是跟我一樣對於游戲開發有憧憬,但是請切記游戲開發學習是一件嚴肅的事,並且必須得有系統的學習階段,所以我的建議是一步一步來,學習ue4之前最好就是去學習編程,最好學習c/c++,因為游戲是軟體,編程技術才是其基礎與原理,ue4的底層一樣是通過大量的底層api調用與c++編寫,先學習編程才能讓你未來學習ue4更快走的更遠。其實這也看提問者對自己未來的定位,如果是僅僅覺得好玩,學下來圖一樂那另說,如果是想成為系統的游戲開發者,我比較推薦也是我曾經以及現在正走的路,就是從c/c++學起,較熟練掌握,最好能夠有比賽經歷,因為比賽會讓你快速掌握演算法基礎,提升編程能力,然後去學習windows程序設計,也就是底層api的學習,這是所有windows 應用的基礎,這部分可以不用精通,然後去學習DietctX 12,這部分可能會很難,主要利用比較高端的c++知識以及線性代數知識,學習DX,主要是讓你了解計算機圖形學,了解所有的游戲開發知識,以及原理,讓你再之後學習UE4可以快速上手同時有原理知識的掌握可以讓你得心應手,如果這部分有很大難度,也可以往後放放,但是一定要學,因為UE4雖然強大,但只是一個集成高層級所見即所得工具,用它只是快速實現,但是它的內部程序幫助你幹了很多的事,了解引擎的原理我覺得十分重要,不能只會用還要知道其中如何實現,這才能讓你走的更遠,會用兵器還更得有內功。然後就是ue4的學習,為了實現開發,這部分才是開發的重頭戲,因為如果光知道原理,啥都自己編寫對於如今的大型游戲開發是不現實的,選取合適的工具至關重要,對於ue4我是非常推崇的,ue4實現的特效效果,光的處理,開發效率,各種方面我都是非常膜拜的,同時對於開發虛擬現實vr,ue4可以說是最佳工具(你會發現現在的vr游戲大部分都是ue4開發),學習ue4肯定是得從藍圖開始學習,然後是材質製作,同時去學一點3dsMax建模,貼圖製作,選一本好教材,多在網上找教程,邊學邊動手,對於ue4的學習我的認知是,在有了一定程度的基礎之後,以項目為學習單位,不斷實現項目,不斷解決問題,水平越來越高,實現的東西會越來越厲害,找不到項目?淘寶上十來塊錢一個教程後面都會有數個大型項目。
寫了這么多,全部手打,全當一個學長的嘮叨好了,因為這一路我是走過來的,我現大四准備考研的。如果你問學了這么多得花多久,我是高中畢業暑假開始接觸c++的,就是說這么多自學下來花了3年,不過都是課下學習的。不要想著急於求成,學習是沒有止境的,技術水平的提升也是沒有止境的,少說多做,一步一腳印,祝你成功!
㈧ 能否實現vbs搭界面,C語言實現演算法
能的;
思路關鍵是要使用程序間通信(這個是很復雜的), 或者是程序間互相調用(這個很簡單,也是我的回答所用的方法)
e.g.
㈨ UE4基礎知識總結(四)
六、自動測試技術
1.自動測試分為簡單測試和復雜測試,簡單測試用來描述單個原子測試,復雜測試用來運行基於多個輸入的相同代碼。
2.簡單測試可用來確認特定功能如預期般可操作。一般都是單元測試或功能測試。
3.復雜測試可被用來對一系列物品迭代並對每個物品運行相同的功能。一般就是內容壓力測試。例如載入所有地圖或編譯所有藍本。
4.當前的規則是將所有的自動測試放置到相關模塊內的PrivateTests目錄。測試文件命名為[ClassFilename]Test.cpp
5.這些測試通過應用RunTest()函數來單獨定義其功能,而且Parameters字元串將保持為空字元串。
IMPLEMENT_SIMPLE_AUTOMATION_TEST( TClass, PrettyName, TFlags )
IMPLEMENT_COMPLEX_AUTOMATION_TEST( TClass, PrettyName, TFlags )
七、編碼規范
1.編碼規范對於程序員來說非常重要,原因如下:
a.一套軟體80%的生命周期都是維護。
b.在軟體的整個生命周期中,幾乎不可能一直是軟體的原始作者來對其進行維護。
c.編碼規范可以改進軟體的可讀性,從而使得工程師可以快速並透徹地理解新的代碼。
d.如果我們決定將源代碼公布到 MOD 開發者社區,那麼我們想讓它通俗易懂。
e.大部分編碼規范實際上是交叉編譯器兼容性所要求的。
2.變數、方法及類的名稱應該清晰、明確且具有描述性。
3.注釋應該是輔助加強代碼的,代碼是功能實現,注釋表明了代碼的目的。
八、對象
1.虛幻引擎中的對象基礎類為UObject。UCLASS宏可用於標記從UObject派生的類,使UObject處理系統識別到它們。
2.UCLASS宏為UObject提供一個對UCLASS的引用,描述其基於虛幻引擎的類型。
3.每個UCLASS保留一個稱作「類默認對象(Class Default Object)」的對象,簡稱CDO。
4.新建UObject示例的函數有:
a.NewObject () 創建一個自動生成命名的新實例。在簡單情況下使用最佳。
b.NewNamedObject () 使用特定命名以及其他幾項任選參數創建一個新實例。將判斷新實例的Outer中是否存在命名沖突。
c.ConstructObject () 創建一個提供所有可用創建選項的新實例。僅限需要靈活性時使用。
d.new 用於在特定低層情況下構建對象,如構建函數需要參數時。
5.UObjects提供的功能有:
a.垃圾回收:虛幻引擎實現了一個垃圾回收方案,定期清理不再被引用或被顯式標記為待銷毀的 UObject。
b.引用更新:對象被垃圾回收清理時,對它的UPROPERTY引用將自動被更新為 NULL。
c.映象
d.序列化:當一個 UObject 被序列化時,所有 UProperty 數值將被自動書寫或讀取。
e.默認屬性變化自動更新:UClass 的CDO發生變化時,引擎將嘗試把這些變化智能應用到類的所有實例上(在它們被載入時)。
f.自動屬性初始化:初始化時,在構建函數被調用之前,UObject 將被自動清零。
g.自動編輯器整合:編輯器理解 UObjects 和 UProperties,還可將這些數值自動公開進行編輯,而無需編寫特殊代碼。
h.運行時類型信息可用:UObject 明確其為何種 UClass,運行時可作出類型相關的決定。
i.網路復制:UObject 系統包括一個穩定的功能集,實現網路通訊和多人 游戲 。
6.UObjects的頭文件格式:
#include 'Object.h'
#include 'MyObject.generated.h'
UCLASS() //UCLASS 宏使虛幻引擎 4 能識別 UMyObject。
class MYPROJECT_API UMyObject : public UObject //如 MyProject 希望將 UMyObject 類公開到其他模塊,則需要指定 MYPROJECT_API。
{
GENERATED_BODY() //對類進行設置,以支持引擎要求的基礎結構。
};
㈩ 急求用C實現的Apriori演算法的 代碼
http://www.csc.liv.ac.uk/~frans/Notes/KDD/AssocRuleMine/apriori.html
.h
====================================
/*----------------------------------------------------------------------
File : apriori.h
Contents: apriori algorithm for finding frequent item sets
(specialized version for FIMI 2003 workshop)
Author : Christian Borgelt
History : 15.08.2003 file created from normal apriori.c
16.08.2003 parameter for transaction filtering added
18.08.2003 dynamic filtering decision based on times added
21.08.2003 transaction sort changed to heapsort
20.09.2003 output file made optional
----------------------------------------------------------------------*/
/*
Modified by : Frédéric Flouvat
Modifications : store the positive and negative border into an
an input trie for ABS
process stastical informations on dataset to stop
the apriori classical iterations
Author : Frédéric Flouvat
----------------------------------------------------------------------*/
#ifndef APRIRORI_H
#define APRIRORI_H
#include <iostream>
using namespace std;
#define MAXIMAL
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include "tract.h"
#include "istree.h"
#include "Application.h"
/*----------------------------------------------------------------------
Preprocessor Definitions
----------------------------------------------------------------------*/
#define PRGNAME "fim/apriori"
#define DESCRIPTION "frequent item sets miner for FIMI 2003"
#define VERSION "version 1.7 (2003.12.02) " \
"(c) 2003 Christian Borgelt"
/* --- error codes --- */
#define E_OPTION (-5) /* unknown option */
#define E_OPTARG (-6) /* missing option argument */
#define E_ARGCNT (-7) /* too few/many arguments */
#define E_SUPP (-8) /* invalid minimum support */
#define E_NOTAS (-9) /* no items or transactions */
#define E_UNKNOWN (-18) /* unknown error */
#ifndef QUIET /* if not quiet version */
#define MSG(x) x /* print messages */
#else /* if quiet version */
#define MSG(x) /* suppress messages */
#endif
#define SEC_SINCE(t) ((clock()-(t)) /(double)CLOCKS_PER_SEC)
#define RECCNT(s) (tfs_reccnt(is_tfscan(s)) \
+ ((tfs_delim(is_tfscan(s)) == TFS_REC) ? 0 : 1))
#define BUFFER(s) tfs_buf(is_tfscan(s))
/*----------------------------------------------------------------------
Constants
----------------------------------------------------------------------*/
#ifndef QUIET /* if not quiet version */
/* --- error messages --- */
static const char *errmsgs[] = {
/* E_NONE 0 */ "no error\n",
/* E_NOMEM -1 */ "not enough memory\n",
/* E_FOPEN -2 */ "cannot open file %s\n",
/* E_FREAD -3 */ "read error on file %s\n",
/* E_FWRITE -4 */ "write error on file %s\n",
/* E_OPTION -5 */ "unknown option -%c\n",
/* E_OPTARG -6 */ "missing option argument\n",
/* E_ARGCNT -7 */ "wrong number of arguments\n",
/* E_SUPP -8 */ "invalid minimal support %d\n",
/* E_NOTAS -9 */ "no items or transactions to work on\n",
/* -10 to -15 */ NULL, NULL, NULL, NULL, NULL, NULL,
/* E_ITEMEXP -16 */ "file %s, record %d: item expected\n",
/* E_DUPITEM -17 */ "file %s, record %d: plicate item %s\n",
/* E_UNKNOWN -18 */ "unknown error\n"
};
#endif
/*----------------------------------------------------------------------
Global Variables
----------------------------------------------------------------------*/
#ifndef QUIET
static char *prgname; /* program name for error messages */
#endif
static ITEMSET *itemset = NULL; /* item set */
static TASET *taset = NULL; /* transaction set */
static TATREE *tatree = NULL; /* transaction tree */
static ISTREE *istree = NULL; /* item set tree */
static FILE *in = NULL; /* input file */
static FILE *out = NULL; /* output file */
extern "C" TATREE * apriori( char*fn_in, char*fn_out, int supp, int & level,
Trie * bdPapriori, Trie * bdn, set<Element> * relist, double ratioNfC, double & eps, int ismax,
vector< unsigned int > * stat, int & maxBdP, bool & generatedFk, bool verbose ) ;
#endif
.c
============================================
/*----------------------------------------------------------------------
File : apriori.c
Contents: apriori algorithm for finding frequent item sets
(specialized version for FIMI 2003 workshop)
Author : Christian Borgelt
History : 15.08.2003 file created from normal apriori.c
16.08.2003 parameter for transaction filtering added
18.08.2003 dynamic filtering decision based on times added
21.08.2003 transaction sort changed to heapsort
20.09.2003 output file made optional
----------------------------------------------------------------------*/
/*
Modified by : Frédéric Flouvat
Modifications : store the positive and negative border into an
an input trie for ABS
process stastical informations on dataset to stop
the apriori classical iterations
Author : Frédéric Flouvat
----------------------------------------------------------------------*/
#include "apriori.h"
/*----------------------------------------------------------------------
Main Functions
----------------------------------------------------------------------*/
static void error (int code, ...)
{ /* --- print an error message */
#ifndef QUIET /* if not quiet version */
va_list args; /* list of variable arguments */
const char *msg; /* error message */
assert(prgname); /* check the program name */
if (code < E_UNKNOWN) code = E_UNKNOWN;
if (code < 0) { /* if to report an error, */
msg = errmsgs[-code]; /* get the error message */
if (!msg) msg = errmsgs[-E_UNKNOWN];
fprintf(stderr, "\n%s: ", prgname);
va_start(args, code); /* get variable arguments */
vfprintf(stderr, msg, args);/* print error message */
va_end(args); /* end argument evaluation */
}
#endif
#ifndef NDEBUG /* if debug version */
if (istree) ist_delete(istree);
if (tatree) tat_delete(tatree);
if (taset) tas_delete(taset, 0);
if (itemset) is_delete(itemset);
if (in) fclose(in); /* clean up memory */
if (out) fclose(out); /* and close files */
#endif
exit(code); /* abort the program */
} /* error() */
/*--------------------------------------------------------------------*/
TATREE * apriori( char*fn_in, char*fn_out, int supp, int & level, Trie * bdPapriori,
Trie * bdn , set<Element> * relist , double ratioNfC, double & eps,int ismax,
vector< unsigned int > * stat, int & maxBdP, bool & generatedFk, bool verbose )
{
int i, k, n; /* loop variables, counters */
int tacnt = 0; /* number of transactions */
int max = 0; /* maximum transaction size */
int empty = 1; /* number of empty item sets */
int *map, *set; /* identifier map, item set */
char *usage; /* flag vector for item usage */
clock_t t, tt, tc, x; /* timer for measurements */
double actNfC = 1 ;
double avgNfC = 0 ;
int nbgen = 0 ;
int nbfreq = 0 ;
level = 1 ;
bool endApriori = false ; // boolean to stop the initial classial apriori approach
int bdnsize = 0 ; // number of itemsets found infrequent
/* --- create item set and transaction set --- */
itemset = is_create(); /* create an item set and */
if (!itemset) error(E_NOMEM); /* set the special characters */
taset = tas_create(itemset); /* create a transaction set */
if (!taset) error(E_NOMEM); /* to store the transactions */
if( verbose ) MSG(fprintf(stderr, "\n")); /* terminate the startup message */
/* --- read transactions --- */
if( verbose )MSG(fprintf(stderr, "reading %s ... ", fn_in));
t = clock(); /* start the timer and */
in = fopen(fn_in, "r"); /* open the input file */
if (!in) error(E_FOPEN, fn_in);
for (tacnt = 0; 1; tacnt++) { /* transaction read loop */
k = is_read(itemset, in); /* read the next transaction */
if (k < 0) error(k, fn_in, RECCNT(itemset), BUFFER(itemset));
if (k > 0) break; /* check for error and end of file */
k = is_tsize(itemset); /* update the maximal */
if (k > max) max = k; /* transaction size */
if (taset && (tas_add(taset, NULL, 0) != 0))
error(E_NOMEM); /* add the loaded transaction */
} /* to the transaction set */
fclose(in); in = NULL; /* close the input file */
n = is_cnt(itemset); /* get the number of items */
if( verbose ) MSG(fprintf(stderr, "[%d item(s),", n));
if( verbose ) MSG(fprintf(stderr, " %d transaction(s)] done ", tacnt));
if( verbose ) MSG(fprintf(stderr, "[%.2fs].\n", SEC_SINCE(t)));
/* --- sort and recode items --- */
if( verbose ) MSG(fprintf(stderr, "sorting and recoding items ... "));
t = clock(); /* start the timer */
map = (int*)malloc(is_cnt(itemset) *sizeof(int));
if (!map) error(E_NOMEM); /* create an item identifier map */
n = is_recode(itemset, supp, 2, map); /* 2: sorting mode */
tas_recode(taset, map, n); /* recode the loaded transactions */
max = tas_max(taset); /* get the new maximal t.a. size */
// use in the other part of the implementation to have the corresponding
// identifiant to an internal id
stat->reserve( n+2 ) ;
stat->push_back( 0 ) ;
for(int j= 0; j< n ; j++ )
{
stat->push_back( 0 ) ;
relist->insert( Element( atoi( is_name( itemset, j ) ) ,j) );
}
if( verbose ) MSG(fprintf(stderr, "[%d item(s)] ", n));
if( verbose ) MSG(fprintf(stderr, "done [%.2fs].\n", SEC_SINCE(t)));
/* --- create a transaction tree --- */
if( verbose ) MSG(fprintf(stderr, "creating transaction tree ... "));
t = clock(); /* start the timer */
tatree = tat_create(taset,1); /* create a transaction tree */
if (!tatree) error(E_NOMEM); /* (compactify transactions) */
tt = clock() -t; /* note the construction time */
if( verbose ) MSG(fprintf(stderr, "done [%.2fs].\n", SEC_SINCE(t)));
/* --- create an item set tree --- */
if( verbose ) MSG(fprintf(stderr, "checking subsets of size 1"));
t = clock(); tc = 0; /* start the timer and */
istree = ist_create(n, supp); /* create an item set tree */
if (!istree) error(E_NOMEM);
for (k = n; --k >= 0; ) /* set single item frequencies */
ist_setcnt(istree, k, is_getfrq(itemset, k));
ist_settac(istree, tacnt); /* set the number of transactions */
usage = (char*)malloc(n *sizeof(char));
if (!usage) error(E_NOMEM); /* create a item usage vector */
/* --- check item subsets --- */
while (ist_height(istree) < max && ( ( ismax == -1 && endApriori == false )
|| ist_height(istree) < ismax )
)
{
nbgen = 0 ;
nbfreq = 0 ;
level ++ ;
i = ist_check(istree,usage);/* check current item usage */
if (i < max) max = i; /* update the maximum set size */
if (ist_height(istree) >= i) break;
k = ist_addlvl(istree, nbgen); /* while max. height is not reached, */
if (k < 0) error(E_NOMEM); /* add a level to the item set tree */
if (k != 0) break; /* if no level was added, abort */
if( verbose ) MSG(fprintf(stderr, " %d", ist_height(istree)));
if ((i < n) /* check item usage on current level */
&& (i *(double)tt < 0.1 *n *tc)) {
n = i; x = clock(); /* if items were removed and */
tas_filter(taset, usage); /* the counting time is long enough, */
tat_delete(tatree); /* remove unnecessary items */
tatree = tat_create(taset, 1);
if (!tatree) error(E_NOMEM);
tt = clock() -x; /* rebuild the transaction tree and */
} /* note the new construction time */
x = clock(); /* start the timer */
ist_countx(istree, tatree, nbfreq, istree->supp ); /* count the transaction tree */
tc = clock() -x; /* in the item set tree */
actNfC = 1-double(nbfreq)/double(nbgen) ;
avgNfC = avgNfC + actNfC ;
if( verbose )
{
cout<<" \t Fk : "<<nbfreq<<" Ck : "<<nbgen<<" NFk/Ck "<<actNfC<<" avg NFk/Ck "<<avgNfC/(level-1)<<endl;
}
bdnsize += nbgen - nbfreq ;
if( level >=4 && ( bdnsize / nbgen < 1.5 ) && ( bdnsize > 100 ) )
{
if( actNfC < ratioNfC )
{
eps = 0 ;
endApriori = true ;
}
else if( actNfC > 0.25 )
endApriori = true ;
}
} /* and note the new counting time */
if( verbose ) MSG(fprintf(stderr, " done [%.2fs].\n", SEC_SINCE(t)));
/* --- filter item sets --- */
t = clock(); /* start the timer */
#ifdef MAXIMAL /* filter maximal item sets */
if( verbose ) MSG(fprintf(stderr, "filtering maximal item sets ... "));
if( ratioNfC == 0 || nbgen < k+1 || ist_height(istree)>= max )
ist_filter2(istree, IST_MAXFRQ, 0);
else
ist_filter2(istree, IST_MAXFRQ, bdn);
if( verbose ) MSG(fprintf(stderr, " done [%.2fs].\n", SEC_SINCE(t)));
empty = (n <= 0) ? 1 : 0; /* check whether the empty item set */
#endif /* is maximal */
#ifdef CLOSED /* filter closed item sets */
if( verbose ) MSG(fprintf(stderr, "filtering closed item sets ... "));
ist_filter(istree, IST_CLOSED);
if( verbose ) MSG(fprintf(stderr, " done [%.2fs].\n", SEC_SINCE(t)));
for (k = n; --k >= 0; ) /* check for an item in all t.a. */
if (is_getfrq(itemset, k) == tacnt) break;
empty = (k <= 0) ? 1 : 0; /* check whether the empty item set */
#endif /* is closed */
/* --- print item sets --- */
for (i = ist_height(istree); --i >= 0; )
map[i] = 0; /* clear the item set counters */
if( verbose ) MSG(fprintf(stderr, "writing %s ... ", (fn_out) ? fn_out : "<none>"));
t = clock(); /* start the timer and */
if (fn_out) { /* if an output file is given, */
out = fopen(fn_out, "w"); /* open the output file */
if (!out) error(E_FOPEN, fn_out);
if (empty) fprintf(out, " (%d)\n", tacnt);
} /* report empty item set */
ist_init(istree); /* init. the item set extraction */
set = is_tract(itemset); /* get the transaction buffer */
for (n = empty; 1; n++) { /* extract item sets from the tree */
k = ist_set(istree, set, &supp);
if (k <= 0) break; /* get the next frequent item set */
map[k-1]++; /* count the item set */
if (fn_out) { /* if an output file is given */
for (i = 0; i < k; i++) { /* traverse the items */
fputs(is_name(itemset, set[i]), out);
fputc(' ', out); /* print the name of the next item */
} /* followed by a separator */
fprintf(out, "(%d)\n", supp);
} /* print the item set's support */
else
{
short unsigned * is = new short unsigned[k] ;
for (i = 0; i < k; i++) /* traverse the items */
{
is[i] = set[i] ;
}
if( k < level || nbgen < k+1 || ist_height(istree)>= max )
{
bdPapriori->insert(is, k ,supp ) ;
(*stat)[ 0 ] ++;
(*stat)[ k+1 ]++;
if( maxBdP < k )
maxBdP = k ;
}
else
{
generatedFk = true ;
}
delete[] is;
}
}
if (fn_out) { /* if an output file is given */
if (fflush(out) != 0) error(E_FWRITE, fn_out);
if (out != stdout) fclose(out);
out = NULL; /* close the output file */
}
if( verbose ) MSG(fprintf(stderr, "[%d set(s)] done ", n));
if( verbose ) MSG(fprintf(stderr, "[%.2fs].\n", SEC_SINCE(t)));
/* --- print item set statistics --- */
k = ist_height(istree); /* find last nonzero counter */
if ((k > 0) && (map[k-1] <= 0)) k--;
if( verbose ){
printf("%d\n", empty); /* print the numbers of item sets */
for (i = 0; i < k; i++) printf("%d\n", map[i]);
}
/* --- clean up --- */
#ifndef NDEBUG /* if this is a debug version */
free(usage); /* delete the item usage vector */
free(map); /* and the identifier map */
ist_delete(istree); /* delete the item set tree, */
if (taset) tas_delete(taset, 0); /* the transaction set, */
is_delete(itemset); /* and the item set */
#endif
return tatree ;
}