漢諾塔 動畫過程繪製實現

2021-07-24 13:57:38 字數 4334 閱讀 9470

人工智慧實驗要求:利用狀態空間法,實現漢諾塔求解過程的動畫(將n個盤子,從a柱移到c柱上)。

這裡是乙個c語言實現控制台繪製的例項,筆者將程式的思想寫了個詳細的注釋,方便大家學習。

程式效果圖及思路:

這裡的思路是:以三進製資料表示3個盤子的狀態:比如0,1,2分別表示在a,b,c柱子上,一種狀態值為220,就表示:最小盤在a柱,其他在c柱上

這裡如果是n個盤子,還是用0,1,2三進製數表示盤子所在柱子,數字的組合就是乙個整體的狀態,就是三進製數序列,轉化為10進製,就是乙個整型值

這個數值就是整個盤子擺放的一種狀態,狀態的取值有3^n種這裡顯示的是最短可行的狀態路徑(狀態之間是相關聯的,0.....0是起點,2.....2是要到達的狀態),演算法就是要在這些狀態中選擇一條最佳路徑,到達目的地!

詳細解答請看程式注釋:

#include

#include

#include

#include

#include

#define false 0

#define true 1

char graph[10][43]=,,,

,,,,

,,,};

typedef struct qnode qnode, *queueptr;

typedef struct linkqueue;

/* 初始化佇列 */

int initqueue(linkqueue *q)

/* 銷毀佇列 */

int destroyqueue(linkqueue *q)

q->rear = q->front = null;

return true;

}/* 判斷是否為空佇列 */

int queueempty(linkqueue q)

/* 元素入佇列 */

int enqueue(linkqueue *q, int e)

/* 元素出佇列 */

int dequeue(linkqueue *q, int *e)

void i***ist(int *state,int tnum,int num,linkqueue &q)

}/* --------- 影象輸出函式集 ------------ */

void printgraph()

void initgraph(int n)

}void moveto(int from, int to, int size)//from to 只有0,1,2

// i 為當前層, j 為目標層

for(k=i-1; k>=0; k--)//上移

printgraph();

}slen=size*2+1;

if (from1

for(k=from1; k<=to1; k++)//右移

else//左移

for(k=from1; k>=to1; k--)

//平移結束

/* 下移 */

for(k=1; k<=j; k++)

printgraph();}}

void display(int **recd, int num, int len)//演示函式

}initgraph(len);//根據層數進行初始化影象

printgraph();

i=0;

dowhile(i

printf("over...");

getchar();

getchar();

}/* ------------------------------------- */

/* 起始狀態為0.....0 終止狀態為2......2 */

int main()

initqueue(&q); // 初始化佇列

num = 0;  //num記錄的是所有盤子元素狀態序列對應的整數,可轉化為一串0,1,2數字序列。

enqueue(&q, num);//狀態1入棧,即0000(此時所有的盤子的狀態都是0)

record_of_state[num] = -2;// 狀態數的大小是根據n的取值來確定的(num代表乙個狀態的取值,num的最大值即為最大狀態數)

/*這裡是在出佇列狀態值的基礎上,獲取每乙個盤子的狀態(由整數得到乙個數字序列),在逐位來判斷,確定下一狀態值

這裡的規律:確定最底盤後(序列下標相對最小),該位就一直不變

*//*  這裡會篩選所需的狀態值,以及他們的先後關係(每個狀態值都進入了佇列,有些被排除了,最後得到

關鍵的狀態值路徑)  */

while (queueempty(q) == false)//狀態空間的生成(如果佇列不為空,擴充套件狀態空間)

if (temp[bricknum - 1] == 0)   //最後一位是0=>最上層盤子狀態(該狀態下:最小的盤子在a柱子上)

else if (temp[i] == 2)

temp_of_add *= 3;}}

else if (temp[bricknum - 1] == 1)  //最後一位是1(該種狀態下:最小的盤子在b柱子上)

else if (temp[i] == 2)

temp_of_add *= 3;}}

else  // 該狀態下:最小的盤子在c柱子上

else if (temp[i] == 1)

temp_of_add *= 3;}}

}/*1: 如何完成的所有狀態值無序入佇列

2: 前後結點(狀態值之間聯絡)查詢,篩選的演算法

*//*  order_of_state 陣列裝載的是篩選的路徑中入隊的狀態值,雖然所有的狀態值都入過對列,但從中選擇出了最短需要路徑*/

num = num_of_state - 1;  // 狀態值陣列最大下標

// 初始record_of_state陣列的值都被賦值為-1,如果要入佇列就將其值賦值為上一狀態值的大小

i = 0;// 從後往前遍歷狀態值陣列:如果當前狀態值入過佇列,則其值為上一狀態值

while (record_of_state[num] != -2)// 跳出口為第乙個狀態值0...0,其對應狀態值陣列值為-2.它是作為起點單獨處理的

order_of_state[i] = num; // 在num=0時並沒有裝入order_of_state就跳出了迴圈

int mycount=0;

int **recd = (int **)malloc((i+1)*sizeof(int *));//記錄狀態變化順序

for (j=0; j<=i; j++)

recd[j] = (int *)malloc(bricknum*sizeof(int));

//int **recd= new int[i][bricknum];//記錄狀態變化,以便影象演示使用

for (j=i; j>=0; j--)

memcpy(recd[mycount], temp, bricknum*sizeof(int));

mycount++;

for (k = 0; k < bricknum; k++)

printf("%d", temp[k]);

printf("\n");

}getchar();

getchar();

//輸出演示

if(bricknum!=0)

display(recd, i, bricknum);

//釋放變數

free(temp);

free(record_of_state);

free(order_of_state);

for (k=0; k<=i; k++)

free(recd[k]);

free(recd);

getchar();

return 0;

}這個程式的關鍵是:從所有的狀態值中,篩選出需要的狀態值,並確定他們之間的先後關係,以便能正確按序挪動盤子,完成任務

漢諾塔 遞迴過程

usr bin env python coding utf 8 author jia shilin 漢諾塔 list1,list2,list3三個陣列代表三個柱子和圓盤 數字的大小代表圓盤的大小 數字的順序代表圓盤的順序 漢諾塔函式 def h n,x list,y list,z list,x,y,...

python 漢諾塔 Python漢諾塔

import turtle class stack def init self self.items def isempty self return len self.items 0 def push self,item def pop self return self.items.pop def ...

漢諾塔的實現

漢諾塔是大學遇見的第乙個使用遞迴的問題。這個問題的解決方法充分展示了遞迴給程式帶來的遍歷 如果不使用遞迴的話,那麼就需要細緻的分析。這裡不談非遞迴的解法。漢諾塔問題介紹 在印度,有這麼乙個古老的傳說 在世界中心貝拿勒斯 在印度北部 的聖廟裡,一塊黃銅板上插著三根寶石針。印度教的主神梵天在創造世界的時...