人工智慧實驗要求:利用狀態空間法,實現漢諾塔求解過程的動畫(將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 ...
漢諾塔的實現
漢諾塔是大學遇見的第乙個使用遞迴的問題。這個問題的解決方法充分展示了遞迴給程式帶來的遍歷 如果不使用遞迴的話,那麼就需要細緻的分析。這裡不談非遞迴的解法。漢諾塔問題介紹 在印度,有這麼乙個古老的傳說 在世界中心貝拿勒斯 在印度北部 的聖廟裡,一塊黃銅板上插著三根寶石針。印度教的主神梵天在創造世界的時...