JAVA学习笔记(2):求解和为15的棋盘游戏

1.问题描述

把1,2,3,4,5,6,7,8,9这九个数字填入3*3的九宫格中,要求实现每行,每列和每个对角线上的数字之和为15。


2.解决思路
2.1 画出九宫格
设计方法mb_outputGridRowBoard画出九宫格,思路大致为
先输出:+—–+
再输出:|数字|数字|数字|
通过输出三次可以形成如下所示的输出图案:
+ - - - - - +
|数字|数字|数字|
+ - - - - - +
|数字|数字|数字|
+ - - - - - +
|数字|数字|数字|

2.2 对填入九宫格中的数据进行判断
设计方法mb_checkAll(),这个方法中又调用 mb_checkRow(),mb_checkCow( ),mb_checkDiag()分别用于判断每行,每列和每个对角线上的数字之和是否为15,如果都是,则返回true,如果不是则返回false。

2.3 如何实现填入九宫格的数据满足要求
在这里我主要通过对数列{1,2,3,4,5,6,7,8,9}求全排列,每一次的排列我将其填入九宫格中,通过方法mb_fullPermutation()实现,这是一个全排列的递归函数。其中交换的部分,由于java中不存在指针的功能,所以在数据交换上面,我把数列设置为了静态变量,这样实现交换。


3.代码部分

/************************
问题描述:
把1-9填入3*3的棋盘中,保证各行,
各列,对角线上的数字之和为15!
*************************/
public class J_Grid15
{
    int [] [] m_board;
    static int source [] = {1,2,3,4,5,6,7,8,9};
    static int count = 1;
    J_Grid15()
    {
        m_board = new int [3] [3];
    }

    //输出棋盘的格线行
    private void mb_outputGridRowBoard()
    {
        int i;
        System.out.print("+");
        for(i = 0;i < 5;i++)
        {
            System.out.print("-");
        }
        System.out.println("+");
    }

    //输出棋盘的数据行(第i行,i = 0 1 2)
    private void mb_outputGridRowBoard(int i)
    {
        int j;
        for(j = 0;j < m_board[i].length;j++)
        {
            System.out.print("|"+m_board[i][j]);
        }
        System.out.println("|");
    }

    //输出棋盘
    public void mb_outputGrid()
    {
        int i;
        mb_outputGridRowBoard();
        for(i = 0;i < m_board.length;i++)
        {
            mb_outputGridRowBoard(i);
            mb_outputGridRowBoard();
        }
    }

    //初始化数据
    private void mb_dataInit()
    {
        int i,j,k = 1;
        for(i = 0;i < 3;i++)
            for(j = 0;j < 3;j++)
                m_board[i][j] = k++;
    }

    //检查行和是否满足15
    private boolean mb_checkRow()
    {
        for(int i = 0;i < 3;i++)
        {
            if(m_board[i][0]+m_board[i][1]+m_board[i][2] != 15)
                return false;
        }
        return true;
    }
    //检查列和是否满足15
    private boolean mb_checkCow()
    {
        for(int i = 0;i < 3;i++)
        {
            if(m_board[0][i]+m_board[1][i]+m_board[2][i] != 15)
                return false;
        }
        return true;
    }
    //检查对角线和是否满足15
    private boolean mb_checkDiag()
    {
        if(m_board[0][0] + m_board[1][1] + m_board[2][2] != 15)
            return false;
        if(m_board[0][2] + m_board[1][1] + m_board[2][0] != 15)
            return false;
        return true;
    }
    //检查行、列与对角线之和是否满足15
    private boolean mb_checkAll()
    {
        if(!mb_checkRow())
            return false;
        if(!mb_checkCow())
            return false;
        if(!mb_checkDiag())
            return false;
        return true;
    }

    //数据交换
    private void mb_Swap(int lhs, int rhs)
    {
        int t = source[lhs];  
        source[lhs] = source[rhs];  
        source[rhs] = t; 
    }
    //数据求解并输出,原理:对数列进行全排列填入九宫格中进行判断
    private void mb_fullPermutation(int source[],int begin,int end)
    {
        int i = 0,k = 0;

        if(begin >= end)  //找到一个全排列
        {
            for(int j = 0;j < 3;j++)
            {
                m_board[j][0] = source[k+0];
                m_board[j][1] = source[k+1];
                m_board[j][2] = source[k+2];
                k = k + 3;
            }
            if(mb_checkAll())
            {
                System.out.println("第" + count + "种情况:");
                count++;
                mb_outputGrid();
            }
        }

        else
        {
            for(i = begin;i < end;i++)
            {
                if(begin != i)
                {
                    mb_Swap(begin, i);
                }
                 // 递归排列剩余的从begin+1到end的元素  
                mb_fullPermutation(source, begin + 1, end);  

                if (begin != i)  
                {  
                    mb_Swap(begin, i); // 回溯时还原  
                }   
            }
        }  
    }


    public static void main(String[] args) {
        J_Grid15 a = new J_Grid15();
        a.mb_fullPermutation(source,0,9);
        System.exit(0);
    }
}


4.结果

第1种情况:
+—–+
|2|7|6|
+—–+
|9|5|1|
+—–+
|4|3|8|
+—–+
第2种情况:
+—–+
|2|9|4|
+—–+
|7|5|3|
+—–+
|6|1|8|
+—–+
第3种情况:
+—–+
|4|3|8|
+—–+
|9|5|1|
+—–+
|2|7|6|
+—–+
第4种情况:
+—–+
|4|9|2|
+—–+
|3|5|7|
+—–+
|8|1|6|
+—–+
第5种情况:
+—–+
|6|1|8|
+—–+
|7|5|3|
+—–+
|2|9|4|
+—–+
第6种情况:
+—–+
|6|7|2|
+—–+
|1|5|9|
+—–+
|8|3|4|
+—–+
第7种情况:
+—–+
|8|3|4|
+—–+
|1|5|9|
+—–+
|6|7|2|
+—–+
第8种情况:
+—–+
|8|1|6|
+—–+
|3|5|7|
+—–+
|4|9|2|
+—–+

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值