八数码难题的实现

   

 

八数码难题的实现

 

 

 

 

一、            八数码难题简介


       
八方块移动游戏要求从一个含8个数字(用1-8表示)的方块以及一个空格方块(用0表示)的3x3矩阵的起始状态开始,不断移动该空格方块以使其和相邻的方块互换,直至达到所定义的目标状态。空格方块在中间位置时有上、下、左、右4个方向可移动,在四个角落上有2个方向可移动,在其他位置上有3个方向可移动。例如,假设一个3x3矩阵的初始状态为:

   8 0 3

   2 1 4

   7 6 5

目标状态为:

   1 2 3

   8 0 4

   7 6 5

则一个合法的移动路径为:

   8 0 3    8 1 3    8 1 3    0 1 3    1 0 3    1 2 3

   2 1 4 => 2 0 4 => 0 2 4 => 8 2 4 => 8 2 4 => 8 0 4

   7 6 5    7 6 5    7 6 5    7 6 5    7 6 5    7 6 5

另外,在所有可能的从初始状态到目标状态的移动路径中,步数最少的路径被称为最短路径;在上面的例子中,最短路径为5。如果不存在从初试状态到目标状态的任何路径,则称该组状态无解。

 

 

二、           解题步骤:

1、 问题表示:

问题表示的核心是如何存储搜索过程中得到的状态。本人是这样存储的:对每个状态用一个9位数存储,例如:

把初始状态:

8 0 3

2 1 4

7 6 5

存储为一个9为数:803214765

2、  解题算法:

本人用了广度优先搜索这种策略进行搜索,且其搜索深度限制在1000内,其代码实现如下:

using System;

using System.Collections.Generic;

using System.Text;

using System.Windows.Forms;

namespace 八数码难题

{

    class MagicFind     //MagicFind这个类是用广度优先搜索方法找到八数码问题的最佳解

    {

        public System.Collections.ArrayList arraylist;

        public int[] a;//用于存储临时状态

        public int v;//记录初始状态的值

        static int[,] dir;//状态转移的4个方向

         int time;//限定搜索深度

         int max;

        const int V = 123804765; //目的状态

 

        public MagicFind() {

            arraylist = new System.Collections.ArrayList();

            a = new int[9];

            a = new int[9] { 2,8,3,1,0,4,7,6,5};

            v = 283104765;

            dir = new int[4, 2] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };

        }

 

        public bool find()  //广度优先搜索

        {

            System.Collections.ArrayList p, q;//p是搜索状态记录,q是搜索路径记录

            int j = 0, k = 1; p = new System.Collections.ArrayList(); q = new System.Collections.ArrayList();

            p.Clear(); q.Clear();

 

            p.Add(v); q.Add(-1);

            while (j < k)

            {

                int zero = toArray((int)p[j]);

                int i;

                for (i = 0; i < 4; i++)

                {                   

                    int x = zero / 3; int y = zero % 3;

                    if (x + dir[i,0] < 0 || x + dir[i,0] > 2 || y + dir[i,1] < 0 || y + dir[i,1] > 2) continue;

                    x = x + dir[i,0]; y = y + dir[i,1];

                    exchange(zero, x * 3 + y);

                    int sum = toValue(a);

                    int r;

                    exchange(zero, x * 3 + y);

                    for (r = 0; r < k; r++) if ((int)p[r] == sum) break;

                    if (r < k) continue;

                    p.Add(sum); q.Add(j);

                    if (sum == V) {  break; }

                    k++;

                }

                if (i < 4 || j == 1000) break;

                j++;

            }

            if (j < k && j < 1000)

            {

                while ((int)q[k] != -1)

                {

                    arraylist.Add(p[k]);

                    k = (int)q[k];

                }

                return true;

            }

            return false;

        }

 

        int toValue(int[] a)    //把数组a变成一个9位的数值

        {

            int sum = 0;

            for (int i = 0; i < 9; i++) sum = sum * 10 + a[i];

            return sum;

        }

        int toArray(int value)  //把数值value转换成一个数值a[9]

        {

            int zero = -1;

            for (int i = 8; i >= 0; i--)

            {

                a[i] = value % 10;

                value /= 10;

                if (a[i] == 0) zero = i;

            }

            return zero;

        }

        void exchange(int i, int j)

        {

            int temp = a[i];

            a[i] = a[j];

            a[j] = temp;

        }

    };

   

}

 

3、  效果图:

1 初始界面

2 自动演示

 

3 游戏结束

4、  软件功能介绍:

本软件分两大功能:用户完成游戏和游戏自动演示。还提供了对游戏初始状态进行随机生成的功能,而且随机生成的初始状态满足在1000步内有解。软件界面上的”开始游戏”按钮表示用户进入游戏,这时用户便可移动数字方块(只需单击你所要移动的数字方块,它便会移到空位);”随机初始化”按钮完成对游戏初始状态的随机生成;”自动演示”按钮完成游戏的自动演示功能。

(要软件源代码的请联系我)

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值