八数码问题,Puzzle

Puzz.h

/*
 * Puzzle.h
 *
 *  Created on: 2011-9-15
 *      Author: brunie
 */

#ifndef PUZZLE_H_
#define PUZZLE_H_

#define R 3
#define G 0
#define H 1
#define Left  1
#define Right 2
#define Up    3
#define Down  4
#define Max   5000
#define STEP  500

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct Node
{
	struct Node *pcome_from;
	int f_score;
	int g_score;
	int h_score;
	char data[R*R + 1];
}Node;

typedef struct Set
{
	int size;
	struct Node *set[Max + 1];
}Set;

extern int PlayGame();

#endif /* PUZZLE_H_ */


Puzz.c

/*
 * Puzzle.c
 *
 *  Created on: 2011-9-15
 *      Author: brunie
 */

#include "Puzzle.h"

	Node	*goal;
	Node	*start;
	Set 	*openset;
	Set 	*closedset;
	int 	step = 0;
	Node	*path[STEP];

extern	Node*	Get_Min_Node(Set *aset);
extern 	int 	Insert_Node(Set *aset, Node *node);
extern	int 	Search_Node(Set *aset, Node *node);
extern	int 	IsEqual(Node *a, Node *b);

void Swap(char *a, char *b)
{
	char t = *a; *a = *b; *b = t;
}
int Get_H_Score(Node *current)
{
	int i;
	int len = R * R;
	int h_score = 0;
	for(i = 0; i < len ; i++)
	{
		if(i != current->data[len])
		{
			h_score += abs(current->data[i]/R - i/R);
			h_score += abs(current->data[i]%R - i%R);
		}
	}
	return h_score;
}

Node* GetNextNode(Node *cur, int flag)
{
	Node *next = (Node*)malloc(sizeof(Node));
	int i;
	int len = R*R;
	for(i = 0; i <= len; i++)
		next->data[i] = cur->data[i];

	int n = next->data[len];
	switch(flag)
	{
		case Left:
			if(n%R == 0)
				return 0;
			else
			{Swap(next->data + n - 1, next->data + n); next->data[len]--;}
			break;
		case Right:
			if((n+1)%R == 0)
				return 0;
			else
			{Swap(next->data + n, next->data + n + 1);next->data[len]++;}
			break;
		case Up:
			if(n/R == 0)
				return 0;
			else
			{Swap(next->data + n, next->data + n - R);next->data[len] -= R;}
			break;
		case Down:
			if(n/R == R - 1)
				return 0;
			else
			{Swap(next->data + n, next->data + n + R);next->data[len] += R;}
			break;
		default:
			return 0;
	}

	return next;
}

int InitSet()
{
	openset = (Set*)malloc(sizeof(Set));
	closedset = (Set*)malloc(sizeof(Set));
	if(0 == openset || 0 == closedset)
		return -1;
	openset->size = 0;
	closedset->size = 0;

	return 0;
}

int IsFeasible(Node *start)
{
	int i,j,t = 0;
	int len = R*R;
	for (i = 1; i < len; i++)
	{
		if(start->data[i] != 0)
		{
			for(j = 0; j < i; j++)
			{
				if(start->data[j] > start->data[i])
						t++;
			}
		}
	}
	if (t % 2 == 0)
		return 0;
	return -1;
}

int GetRandStart()
{
		int i,n;
		int len = R * R;
		start = (Node*)malloc(sizeof(Node));
		if (start)
		{
			for (i = 0; i < len; i++)
				start->data[i] = i;
		}
		else	return -1;

		while(1)
		{
			srand((unsigned)time(0));
			for (i = 0; i < len; i++)
			{
				n = rand() % len;
				Swap(start->data + i, start->data + n);
			}
			if(0 == IsFeasible(start))
				break;
		}

		for (i = 0; i < len; i++)
		{
			if(start->data[i] == 0)
			{
				start->data[len] = i;break;
			}
		}

		start->pcome_from = 0;
		start->g_score = 0;
		start->h_score = Get_H_Score(start);
		start->f_score = start->h_score;

		return 0;
}

int GetSpecStart()
{
	int i;
	int len = R * R;
	start = (Node*)malloc(sizeof(Node));
	if (start)
	{
		for (i = 0; i < len; i++)
			start->data[i] = len - i -1;
	}
	else return -1;

	start->pcome_from = 0;
	start->g_score = 0;
	start->h_score = Get_H_Score(start);
	start->f_score = start->h_score;

	return 0;
}
int Init()
{
	if(-1 == InitSet()) return -1;

	if(-1 == GetRandStart()) return -1;
	//if(-1 == GetSpecStart()) return -1;

	openset->set[1] = start;
	openset->size++;

	return 0;
}

int Output(Node *cur)
{
	int i;
	int len = R * R;
	if (0 == cur) return -1;
	printf("hscore: %d\n", cur->h_score);
	for(i = 0; i < len; i++)
	{
		printf("%d ",cur->data[i]);
		if (i % R == R - 1)
			printf("\n");
	}
	printf("\n");
	return 0;
}

int Get_Path(Node  *goal)
{
	Node *p = goal;
	while(p)
	{
		path[step++] = p;
		p = p->pcome_from;
	}
	step--;
	return 0;
}

int AStar()
{
		Node *cur = 0,*next;
		int ng_score;
		int i;
		int modify, exist;
		while (openset->size)
		{
			cur = Get_Min_Node(openset);

			//Output(cur);
			if(cur->h_score == 0)
			{
				goal = cur;
				return Get_Path(goal);
			}

			if(-1 == Insert_Node(closedset, cur))
				break;

			for (i = 1; i <= 4; i++)
			{
				next = GetNextNode(cur, i);
				if(0 == next)
					continue;
				next->h_score = Get_H_Score(next);
				if(Search_Node(closedset, next) == 0)
					continue;

				ng_score = cur->g_score + 1;

				if (Search_Node(openset, next) != 0)
				{
					modify = 1;
					exist = 0;
				}
				else if (ng_score < next->g_score)
				{
					modify = 1;
					exist = 1;
				}
				else
				{
					modify = 0;
					exist = 1;
				}

				if (modify)
				{
					next->pcome_from = cur;
					next->g_score = ng_score;
					next->f_score = G * next->g_score + H * next->h_score;
					if (!exist)
					if( Insert_Node(openset, next)) break;
				}
			}
		}

		return -1;
}

int PrintPath()
{
	int i;
	for (i = step; i >= 0; i--)
	{
		if(Output(path[i]) == -1)
			return  -1;
	}
	printf("Total steps: %d\n",step);
	return 0;
}

int PlayGame()
{
	if(0 == Init())
	{
		if(0 == AStar())
		{
			return PrintPath();
		}
		else
			printf("Memory not enough!\n");
	}
	else
		printf("Init failure!\n");
	return -1;
}


MinHeap.c
/*
 * Minheap.c
 *
 *  Created on: 2011-9-18
 *      Author: brunie
 */

#include "Puzzle.h"


Node* Get_Min_Node(Set *aset)
{
	int set_size = aset->size;
	Node **set = aset->set;

	if (set_size == 0)
		return 0;

	Node *min = set[1];
	Node *y = set[set_size--];

	int i = 1,  // current node of heap
		ci = 2; // child of i
	while (ci <= set_size)
	{
		if (ci < set_size && set[ci]->f_score > set[ci+1]->f_score)
			ci++;

		if (y->f_score <= set[ci]->f_score) break;

	      // no
		set[i] = set[ci]; // move child up
		i = ci;  // move down a level
		ci *= 2;
	}
	set[i] = y;

	aset->size--;
	return min;
}

int Insert_Node(Set *aset, Node *node)
{
	int set_size = aset->size;
	Node **set = aset->set;

	if(set_size == Max)
		return -1;

	int i = ++set_size;
	while (i != 1 && node->f_score < set[i/2]->f_score)
	{
	      // cannot put x in heap[i]
	      set[i] = set[i/2]; // move element down
	      i /= 2; // move to parent
	}
	set[i] = node;

	aset->size++;
	return 0;
}

int IsEqual(Node *a, Node *b)
{
	int i;
	int len = R*R;
	if(a->h_score != b->h_score)
		return -1;
	for (i = len; i >= 0; i--)
	{
		if(a->data[i] != b->data[i])
			return -1;
	}
	return 0;
}

int Search_Node(Set *aset, Node *node)
{
	int set_size = aset->size;
	Node **set = aset->set;

	int i;
	for (i = 1; i <= set_size; i++)
	{
		if (IsEqual(set[i], node) == 0)
			return 0;
	}
	return -1;
}


Main.c

/*
 * Main.c
 *
 *  Created on: 2011-9-15
 *      Author: brunie
 */
#include "Puzzle.h"

int main()
{
	PlayGame();
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值