最近学数据结构,基于贪心算法写了个马踏棋盘。。。
//
// main.cpp
// 马踏棋盘
//
// Created by minug on 14/10/30.
//
#include
using namespace std;
int popnumber =0;
int Htry1[8] = {-2,-1,1,2 ,2,1,-1,-2};
int Htry2[8] = {1,2,2,1 ,-1,-2,-2,-1};
typedef struct {
int x;
int y;
int allowzuobiao;
}dianzuobiao;
typedefstruct zuobiaojiedian {
dianzuobiao zuobiao;
struct zuobiaojiedian *next;
dianzuobiao child[8];
int now;
int number;
}zuobiaodian ,*zuobiaoLink;
typedef struct {
zuobiaoLink first;
int count;
zuobiaoLink top;
} zuobiaoStack;
//函数声明
zuobiaoStack initzuobiaoStack();
int childcount(dianzuobiao zuobiao);
void initqipan();
void findchild(zuobiaoLink &link);
void start(zuobiaoStack &stack);
void push (zuobiaoStack &stack );//入栈操作
void pop(zuobiaoStack &stack);//出栈操作
//全局变量 8*8棋盘,每个格子里面,放一个zuobiaolink,已经定义好了的
zuobiaoLink qipan[8][8];
int main() {
initqipan();//初始化棋盘 能不能把这个抽出来,不需要每一次运行都计算一次??? 涉及到内存地址。。。。
zuobiaoStack stack = initzuobiaoStack();
start(stack);
}
//初始化棋盘,另外在初始化棋盘中每个坐标的数据
void initqipan(){
for (int x =0; x<8; x++) {
for (int y =0; y<8; y++) {
zuobiaoLink link = (zuobiaoLink)malloc(sizeof(zuobiaodian));
dianzuobiao zuobiao ;
zuobiao.x = x;
zuobiao.y = y;
link->number =0;
link->zuobiao = zuobiao;
link->zuobiao.allowzuobiao = childcount(zuobiao);
link->now = -1;
findchild(link);
qipan[x][y] = link;
}
}
}
zuobiaoStack initzuobiaoStack(){
zuobiaoStack a ;
int x,y;
printf("请输入初始位置: (已逗号分隔)\n");
l1: printf("输入的数字在0-7之间\n");
scanf("%d,%d",&x,&y);
if (x>7||x<0||y>7||y<0) {
printf("对不起,您输入的数字不正确");
goto l1;
}
//定义first结点 //在棋盘里面找这个坐标
zuobiaoLink link = qipan[x][y];
a.first = link;
a.count =1;
link->number =1;
a.top = a.first;
return a;
}
void findchild(zuobiaoLink &link){
//机内乱码,需要初始化
dianzuobiao a[8] ;
dianzuobiao temp;
temp.x = -1;
temp.y = -1;
temp.allowzuobiao =0;
for (int i =0; i<8; i++) {
a[i] = temp;
}
int number = 0;
for (int i =0; i<8; i++) {
dianzuobiao zuobiao;
zuobiao.x = link->zuobiao.x + Htry1[i];
zuobiao.y = link->zuobiao.y + Htry2[i];
//这个点存在,就把这个点塞到上面的数组里面
if (zuobiao.x>=0&&zuobiao.x<=7&&zuobiao.y>=0&&zuobiao.y<=7) {
zuobiao.allowzuobiao = childcount(zuobiao)-1; //需要去掉自己的点!
a[ number] = zuobiao;
number++;
}
}
//排序函数
for (int i =0; i for (int j =0; j if (a[j].allowzuobiao >a[j+1].allowzuobiao ){ temp = a [j]; a[j] = a[j+1]; a[j+1] = temp; } } } //改变link的child值 for (int i =0; i<8; i++) { link->child[i]= a[i]; } } int childcount(dianzuobiao zuobiao){ int x ,y; int a = 0; for (int i =0; i<8; i++) { x = zuobiao.x + Htry1[i]; y = zuobiao.y + Htry2[i]; if (x>=0&&x<=7&&y>=0&&y<=7) { a++; } } return a; } void start(zuobiaoStack &stack){ //开始从第一个允许的结点,进行入栈操作 while (stack.count !=64 && stack.count !=0) { /* 只要count不等于64,就不断进行入栈操作, 至于压入什么东西,由当前的top来决定 top所值的指针的now 如果全部不行了,在进行出栈操作,然后在回到这个函数,进行下一步的操作 在入栈操作里面调用出栈操作 */ push(stack); } //输出操作 if (stack.count ==0 ) { printf("对不起没有找到合适的路线"); printf("\n%d\n",popnumber); exit(0); } if (stack.count ==64) { for (int i =0; i<8; i++) { for (int j =0; j<8; j++) { if (qipan[i][j]->number<10) { printf(" %d ",qipan[i][j]->number); }else printf("%d ",qipan[i][j]->number); if (j == 7) { printf("\n"); } } } printf("\n%d\n",popnumber); exit(0); } } //入栈操作 void push (zuobiaoStack &stack ){ zuobiaoLink top = stack.top; if (top->now +1 == top->zuobiao.allowzuobiao) {//这个点不符合,需要出栈 pop(stack); return;//结束这个函数 } //可以写成 do while 形式。。。。 int x = top->child[top->now + 1].x; int y = top->child[top->now + 1].y; top->now = top->now +1; //需要判断这个点是否已经被使用。。。利用now这个值是不是-1。如果找到最后也没有合适的值,把这个top出栈 while (qipan[x][y]->now != -1 ) { if (top->now +1 == top->zuobiao.allowzuobiao) {//这个点不符合,需要出栈 pop(stack); return;//结束这个函数 } x = top->child[top->now +1].x; y = top->child[top->now +1].y; top->now ++; } zuobiaoLink next = qipan[x][y]; next->number = stack.count +1; next->next = top; stack.top = next; stack.count ++; // printf("%d",stack.count); } //出栈操作 void pop(zuobiaoStack &stack){ /*把这个结点出栈之后,需要把这个结点的数据还原,需要更改now这个值,把这个值还原成-1....number这个值,可以不用还原 */ zuobiaoLink top = stack.top; stack.top = top->next; top->now = -1; top->next =NULL; stack.count = stack.count -1; popnumber++; } /* 定义结点,每个结点里面再放一个东西储存这个结点的下一步可以运算的结点,按照下一个结点可以走的 路数进行排序,路数越少的越在前面。。。 坐标结点类 : 1->该结点的坐标(坐标结构体) 2->该节点的下一部结点 next 3->该节点的能够走的下一个结点(链表,方便插入,按照能够走的个数进行排序(考虑到如果每定义一个新结点,都需要重新判断当前的结点的数据,为了方便)) //需要定义一个数组来储存这些数据,按照从小到大的顺序存放 4->该节点的当前走的结点哪一个下一结点 数组的下标 5->该坐标目前是第几步,方便输出 6->是否已经被使用 bool值 true false 不需要了,根据坐标的2 -> next是否为空,来判断该点是否被使用 7-> 首节点 //利用栈来实现 1->坐标结点 2->当前的个数 当个数 == 64的时候,结束算法,输出结果 3->top指针 坐标结点类中第3点 也就是说,我只需要64个结点的内存地址 ,建立一个类似字典的东西,储存每个结点的地址,使用一个8*8的指针数组,用坐标作为key 第一步,创建“字典” 就是每一个结点的1,3数据 (考虑到这个固定不变的,不需要多次创建 只需要创建一个 ) 另外,可以把这个专门抽出来放在一个地方,不需要每次运行程序都创建一次 1.创建字典 2.输入数据 3.开始循环查找 可以利用棋盘的对称性 */