国际象棋马走日(华科软院上机)

问题描述:假设国际象棋棋盘有5*5共25个格子。设计一个程序,使棋子从初始位置(棋盘编号为1的位置)开始跳马,能够把棋盘的格子全部都走一遍,每个格子只允许走一次。要求:

1):输出一个解(用二维数组来记录马跳的过程,即[步号,棋盘格编号]),左上角为第一步起点;

2):求总共有多少解;

*注:国际象棋的棋子是在格子中间的。  题目如下图

问题分析:由于国际象棋的棋子是在格子中间而不是线的交点处(这一点与中国象棋不同),所以我们可以将国际象棋棋盘看做是一个5行5列的二维数组,数组的每个元素代表棋盘上的一个格子(中国象棋里数组的一个元素代表一个交点)。数组从左往右、从上往下依次编号为1至25,代码如下

int a[5][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15},{16,17,18,19,20},{21,22,23,24,25}};    //将棋盘看成一个5行5列的二维数组a[5][5],从左上角开始编号为1,一直到右下角编号为25

同时题目要求我们每个格子只能经过一次,所以我们需要再定义一个5行5列的标记数组对应棋盘的格子,通过标记数组的值来判断对应的棋盘格是否已经走过。


int a0[5][5]={0};   //a0[][]是标记数组,对应棋盘的每一个格子,初始值为0,用来判断每个格子是否已经走过,如果已经走过,则对应的值为1

同时我们还需要定义一个整形变量来记录步号,一个整形变量来记录总的解数,一个整形数组来记录每一步的棋盘格编号

int step[26]={0},answer_num;   //answer_num是总的解数    一维数组step[]记录的是马走每一步经过的棋盘编号,因为步数是从1开始,到25结束,所以数组的长度为26,这样最后一个数的下标为25

int step_num=0,flag=1;    //step_num表示第几步        flag是答案输出标记

这样以来所有的准备工作就做好了,全部代码如下

#include<stdio.h>

int step[26]={0},answer_num;   //answer_num是总的解数    一维数组step[]记录的是马走每一步经过的棋盘编号,因为步数是从1开始,到25结束,所以数组的长度为26,这样最后一个数的下标为25

int step_num=0,flag=1;    //step_num表示第几步        flag是答案输出标记

int a[5][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15},{16,17,18,19,20},{21,22,23,24,25}};    //将棋盘看成一个5行5列的二维数组a[5][5],从左上角开始编号为1,一直到右下角编号为25

int a0[5][5]={0};   //a0[][]是标记数组,对应棋盘的每一个格子,初始值为0,用来判断每个格子是否已经走过,如果已经走过,则对应的值为1


//check()是判断格子是否合法的函数,返回一个整数,参数是格子在二维数组a[5][5]中的下标
int check(int x,int y){
    int result;
    if(x<0||x>=5||y<0||y>=5||a0[x][y]==1)   //不合法的情况有两种,要么格子在二维数组中的下标越界,要么这一格已经走过
        result=0;   //不合法则返回0
    else
        result=1;   //合法则返回1
    return result;
}

//search()是求解从编号为1的格子开始把棋盘全部格子走一遍的步骤的函数,有两个参数,分别是格子在二位数组a[5][5]中的横、纵坐标,取值范围均为0--4
void search(int x,int y){
    int i;
    if(check(x,y)==1)   //当格子合法时,才继续下列操作,否则什么也不做
	{    

        step[++step_num]=a[x][y];   //将这一格的编号记录在step[]数组中,同时步数step_num+1

        if(step_num==25)  //只要步数到达25步,说明已经求得了一种解
		{
            answer_num++;   //总解数answer_num+1

            if(flag==1)     //当flag==1时,输出一种解
			{
               printf("one answer:\n");
               for(i=1;i<=25;i++)
               printf(" [%d,%d]\n",i,step[i]);
            }
            flag=0;   //当已经输出一种解后令flag的值为0,不再输出后面的解
        }

        a0[x][y]=1;   //同时将对应位置的a0[][]数组的值置为1,表示这一格已经走过

        //遍历其他8个方向,寻找其他可能的解
        search(x-2,y-1);
        search(x-1,y+2);
        search(x-1,y-2);
        search(x+2,y+1);
        search(x+2,y-1);
        search(x+1,y-2);
        search(x-2,y+1);
        search(x+1,y+2);

		//由于要求出所有的解法,所以当step_num等于25时退出递归,同时把对应位置的a0[][]数组的值置为0,并且退回到24步,去寻找其他第25步的可能。如果没有其他第25步的可能,则退回到第23步,寻找其他第24步的可能,以此类推下去,直到找到所有可能的解法
        step_num--;
        a0[x][y]=0;

    }
}

int main(){
   search(0,0);    //棋子从棋盘格编号为1的位置开始跳马,而棋盘格编号为1的格子在二维数组中的下标为0 0

   printf("the total answer number is:%d\n",answer_num);	
     return 0;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值