1. 程式人生 > 遊戲 >忍者潛行ACT《荒神2》IGN 5分:食之無味棄之可惜

忍者潛行ACT《荒神2》IGN 5分:食之無味棄之可惜

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <time.h>

using namespace std;
#define N 3 // 數碼組大小
#define Max_STEP 50 // 最大搜索深度
#define MAX 50

typedef struct node // 八數碼結構體
{
int form[N][N];
int evalue; // 評估值
int udirect; // 所遮蔽方向,防止往回推到上已狀態,1上2下3左4右
struct node *parent; // 父節點
}Graph;

Graph *Qu[MAX]; // 佇列
Graph *St[MAX]; // 堆疊

// 列印數碼組
void Print(Graph *The_graph)
{
int i, j;
if (The_graph == NULL)
{
printf("圖為空\n");
}
else
{
printf("----------------\n");
for (i = 0; i < N; ++i)
{
printf("|\t");
for (j = 0; j < N; ++j)
{
printf("%d\t", The_graph->form[i][j]); // 遍歷列印
}
printf("\t|\n");
}
printf("|\t\t\t差距:%d\t\n", The_graph->evalue); // 差距顯示
printf("----------------\n");
}
}

// 評價函式
int Evaluate(Graph *The_graph, Graph *End_graph)
{
int valute = 0; // 差距數
int i, j;
for (i = 0; i < N; ++i)
{
for (j = 0; j < N; ++j)
{
if (The_graph->form[i][j] != End_graph->form[i][j])
{
valute++;
}
}
}
The_graph->evalue = valute;
return valute;
}

// 移動數碼組
Graph *Move(Graph *The_graph, int Direct, int CreatNew_graph)
{
Graph *New_graph;
int HasGetBlank = 0; // 是否獲取空格位置
int AbleMove = 1; // 是否可移動
int i, j, t_i, t_j, x, y;
for (i = 0; i < N; ++i)
{
for (j = 0; j < N; ++j)
{
if (The_graph->form[i][j] == 0)
{
HasGetBlank = 1;
break;
}
}
if (HasGetBlank == 1)
{
break;
}
}
// printf("空格位置:%d,%d\n", i, j);
t_i = i;
t_j = j;

// 移動空格
switch(Direct)
{
case 1:// 上
t_i--;
if (t_i < 0)
AbleMove = 0;
break;
case 2:// 下
t_i++;
if (t_i >= N)
AbleMove = 0;
break;
case 3: // 左
t_j--;
if (t_j < 0)
AbleMove = 0;
break;
case 4: // 右
t_j++;
if (t_j >= N)
AbleMove = 0;
break;
}
if (AbleMove == 0) // 不能移動則返回原結點
{
return The_graph;
}
if (CreatNew_graph == 1)
{
New_graph = new Graph; // 生成節點
for (x = 0; x < 3; ++x)
{
for (y = 0; y < 3; ++y)
{
New_graph->form[x][y] = The_graph->form[x][y]; // 複製數碼組
}
}
}
else
{
New_graph = The_graph;
}
// 移動後
New_graph->form[i][j] = New_graph->form[t_i][t_j];
New_graph->form[t_i][t_j] = 0;
return New_graph;
}

// 搜尋函式
Graph *Search(Graph *Begin, Graph *End)
{
Graph *g1, *g2, *g;
int Step = 0; // 深度
int Direct = 0; // 方向
int i;
int front, rear;
front = rear = -1; // 佇列初始化
g = NULL;
rear++; // 入隊
Qu[rear] = Begin;
while (rear != front)
{ // 佇列不為空
front++; // 出隊
g1 = Qu[front];
for (i = 1; i <= 4; ++i) // 分別從4個方向推匯出新子節點
{
Direct = i;
if (Direct == g1->udirect) // 跳過遮蔽方向
{
continue;
}
g2 = Move(g1, Direct, 1); // 移動數碼組

if (g2 != g1) // 數碼組是否可以移動
{
// 可以移動
Evaluate(g2, End); // 評價新的節點
if (g2->evalue <= g1->evalue + 1)
{ // 是優越節點
g2->parent = g1;
// 移動空格
switch(Direct) // 設定遮蔽方向,防止往回推
{
case 1:// 上
g2->udirect = 2;
break;
case 2: // 下
g2->udirect = 1;
break;
case 3:
g2->udirect = 4;
break;
case 4:
g2->udirect = 3;
break;
}
rear++;
Qu[rear] = g2; // 儲存節點到待處理佇列
if (g2->evalue == 0) // 為0則搜尋完成
{
g = g2;
// i = 5;
break;
}
}
else
{
free(g2); // 拋棄劣質節點
g2 = NULL;
}
}
}
if (g != NULL)
{
if (g->evalue == 0)
{
break;
}
}
++Step; // 統計深度
if (Step > Max_STEP)
{
break;
}
}
return g;
}
int main(int argc, const char *argv[])
{
cout << "------------------實驗一:八數碼遊戲-------------------" << endl;
cout << "------------------貝佳洋 2012020052-------------------" << endl;

Graph Begin_graph = {
{
{
2, 8, 3
},
{
1, 6, 4
},
{
7, 0, 5
}
}, 0, 0, NULL
};
// 目標數碼組
Graph End_graph = {
{
{
1, 2, 3
},
{
8, 0, 4
},
{
7, 6, 5
}
}, 0, 0, NULL
};
Evaluate(&Begin_graph, &End_graph); // 對初始的數碼組評價
printf("初始數碼組:\n");
Print(&Begin_graph);
printf("目標數碼組:\n");
Print(&End_graph);

Graph *G, *P;
int top = -1;
// 圖搜尋
G = Search(&Begin_graph, &End_graph);
// 列印
if (G)
{
// 把路徑倒序
P = G;
// 壓棧
while (P != NULL)
{
++top;
St[top] = P;
P = P->parent;
}
printf("<<<<<<<<<<<<<<<<<搜尋結果>>>>>>>>>>>>>>>\n");
// 彈棧列印
while (top > -1)
{
P = St[top];
--top;
Print(P);
}
printf("<<<<<<<<<<<<<<<<<完成>>>>>>>>>>>>>>>\n");
}
else
{
printf("搜尋不到結果,深度為%d\n", Max_STEP);
// 設計搜尋深度範圍主要是防止佇列記憶體越界
}
return 0;
}