数据结构---马踏棋盘

来源:互联网 发布:通达oa迁移linux 编辑:程序博客网 时间:2024/05/01 01:23

最近学数据结构,基于贪心算法写了个马踏棋盘。。。

//

//  main.cpp

//  马踏棋盘

//

//  Created by minug on 14/10/30.

//


#include <iostream>

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<number; i++) {

       for (int j =0; j<number - i -1; j++) {

           if (a[j].allowzuobiao >a[j+1].allowzuobiao ){

                temp = a [j];

                a[j] = a[j+1];

                a[j+1] = temp;

            }

        }

    }

    //改变linkchild

   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

 第一步,创建字典”  就是每一个结点的13数据      

(考虑到这个固定不变的,不需要多次创建   只需要创建一个  另外,可以把这个专门抽出来放在一个地方,不需要每次运行程序都创建一次

 

 1.创建字典

 2.输入数据

 3.开始循环查找

 

 可以利用棋盘的对称性

 */




0 0
原创粉丝点击