2 u013086938 u013086938 于 2016.02.17 20:45 提问

求助一道二维数组交换特定元素位置的算法题,谢谢大家!

刚试验了一下出了新问题- -
比如,一开始是左边的数组,我想“把2个0去掉,然后0上面的2就掉下来了”,形成右边的新数组
图片说明
然后我用了循环遍历,比如只看第二列,我的做法是“从下往上找,遇到0,就和0上面的数字交换”,结果成了下面这个样子了- -
图片说明
我有个改进想法是“还是从下往上找,遇到0之后判断上面的是不是0,如果是0,再继续向上再找,直到不是0,然后把这个数赋值给一开始那个0的位置”,但是折腾半天没写出来...
您能帮忙看下这个问题怎么写吗?谢谢~

11个回答

caozhy
caozhy   Ds   Rxr 2016.02.17 22:33

请把你的代码贴出来,并且把问题说清楚,否则没法回答你的问题。“刚试验了一下出了新问题- -”请把你的旧问题也贴出来。

u013086938
u013086938 问题我贴在楼下了,麻烦您帮忙看一下,谢谢~
接近 2 年之前 回复
caozhy
caozhy   Ds   Rxr 2016.02.18 05:50
 using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string data = @"
4 2 3 3 2
4 0 1 1 2
3 2 3 2 4
2 0 1 3 2
2 3 3 2 4
";
            string[] lines = data.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            int[,] map = new int[lines.GetLength(0), lines[0].Split(' ').GetLength(0)];
            for (int i = 0; i < map.GetLength(0); i++)
            {
                string[] line = lines[i].Split(' ');
                for (int j = 0; j < map.GetLength(1); j++)
                {
                    map[i, j] = int.Parse(line[j]);
                }
            }

            int n = 0;
            for (int i = 0; i < map.GetLength(0); i++)
            {
                if (map[i, 1] == 0)
                {
                    int temp = map[n, 1];
                    map[n, 1] = map[i, 1];
                    map[i, 1] = temp;
                    n++;
                }
            }

            for (int i = 0; i < map.GetLength(0); i++)
            {
                for (int j = 0; j < map.GetLength(1); j++)
                {
                    Console.Write(map[i, j] + " ");
                }
                Console.WriteLine();
            }
        }
    }
}

caozhy
caozhy   Ds   Rxr 2016.02.18 05:51

4 0 3 3 2
4 0 1 1 2
3 2 3 2 4
2 2 1 3 2
2 3 3 2 4
Press any key to continue . . .

caozhy
caozhy   Ds   Rxr 2016.02.18 05:54
             int n = 0;
            for (int i = 0; i < map.GetLength(0); i++)
            {
                if (map[i, 1] == 0)
                {
                    map[i, 1] = map[n, 1];
                    map[n++, 1] = 0;
                }
            }

代码可以再简化那么一点点

xianfajushi
xianfajushi   2016.02.18 09:15

这是设计消除游戏算法?还是俄罗斯方块?如果是俄罗斯方块其实判断和算法更简单,消除则比方块要复杂些。
按列往方向找遇非0则交换并记住交换后0的位置,第一次交换后会遇到2次0后才遇到非0则与记录的第一个0位交换,这个判断代码应该不难,思路分析好了写代码就不难了。
int a=0,c=0,d=0;
do
{
if(b[c,1]==0)d=c;else {b[d,1]=b[c,1];d=c;}
}whlie(++c<数组维度数);
假设从下往上,且序从0始,则当c为1,b[1,1]==0时d=1,c为2,b[2,1]!=0时交换并记录d=2,继续往上找直遇到非0交换。
按理写代码你自己测试去,我的构思是可以把这个列处理独立写一个函数。

xianfajushi
xianfajushi 写错了是d=-1;
接近 2 年之前 回复
xianfajushi
xianfajushi 按理推算吧b=-1更合理if(b<0)b=c;这样修改一下
接近 2 年之前 回复
xianfajushi
xianfajushi 要加花括号否则程序不知道是哪个判断if(b[c,1]==0){if(d==0)d=c;}else {b[d,1]=b[c,1];d=c;}
接近 2 年之前 回复
xianfajushi
xianfajushi 更正一下if(b[c,1]==0)if(d==0)d=c;else {b[d,1]=b[c,1];d=c;}
接近 2 年之前 回复
xianfajushi
xianfajushi   2016.02.18 10:02

依据之上写的思路代码,最后调试修改:5*5数组
int c = 4, d = -1;
do
{
if (b[c, 1] == 0) if (d < 0) d = c;
else if (d >= 0) { b[d, 1] = b[c, 1]; b[c, 1] = 0; d = c; }
} while (--c >= 0);
就是正确的,就怕提问者不会或懒得调试修改,其实按思路调试修改是很容易的事,顺手就做了。

xianfajushi
xianfajushi 消除确是老少皆宜的休闲游戏,对其算法曾略思索过,先行检查是否全为0,遇0转列处理
接近 2 年之前 回复
xianfajushi
xianfajushi 消除确是老少皆宜的休闲游戏,对其算法曾略思索过,先行检查是否全为0,非0转列处理
接近 2 年之前 回复
xianfajushi
xianfajushi 加花括号
接近 2 年之前 回复
xianfajushi
xianfajushi { if (d < 0) d = c; }
接近 2 年之前 回复
qq_23660243
qq_23660243   2016.02.18 10:37

我表示没明白 题目是交换 为什么你里面要去掉? 到底是交换还是人为去掉特定?

u013086938
u013086938   2016.02.17 20:49

6×6大小...手误
就是说,如何把图中画圈位置上方的2下降到1的正上方?

zrf1335348191
zrf1335348191   2016.02.17 20:50

你是简单的进行两个数的交换??还是每一列的第一个和最后一个都要交换?

zrf1335348191
zrf1335348191 我试了下,没有问题,内外循环, 1,外层列数循环, 2,内层对每列的数做循环,然后将数保存起来,然后再对应赋给该列
接近 2 年之前 回复
zrf1335348191
zrf1335348191 这个不是排序你不能使用冒泡似的,就按我刚才跟你说的把不是0的取出来最后按序赋值,我明天测试下,然后再发给你
接近 2 年之前 回复
zrf1335348191
zrf1335348191 嗯嗯嗯,我现在不方便测试,你试试怎么样
接近 2 年之前 回复
u013086938
u013086938 谢谢~我试写一下
接近 2 年之前 回复
zrf1335348191
zrf1335348191 这样按列做循环,然后每列再按行做判断是否为0,是0就不用管,将非0数统计到一个数组里,然后再依次赋值
接近 2 年之前 回复
u013086938
u013086938 回复fangfang1021: 是的,就是这样
接近 2 年之前 回复
zrf1335348191
zrf1335348191 把数组里为0的消除,然后把该列非0的按序移到该列底部,把该列其余的置0,最后的结果消除后还是6*6数组??不知道我理解对了否?
接近 2 年之前 回复
u013086938
u013086938 就是说,相当于把整个数组中所有的0都去掉,0上方的数字掉下来。比喻的话,有点像消除游戏,3个0消除了,上面的数字掉下来
接近 2 年之前 回复
u013086938
u013086938   2016.02.17 23:35

@caozhy
问题是这样的:
像题目说的那样,我想把第一张图左边的数组里面第二列的2个0“拿掉”,然后让这2个0上面的数组2“下沉下来”,形成第一张图右边的这个数组。
然后,我在写的时候想法比较简单,于是用了“从下到上遍历,如果当前位置是0,那就和上面的那个位置的数字做交换“,来实现上面说的那样"让非零数字下沉下来"

我写的方法是这样的(有BUG,不会修改...)

            int topNum = 0;
            for (int iii = rowNum - 1; iii > 0; iii--)
            {
                for (int jjj = 0; jjj < colNum; jjj++)
                {
                    if (map[iii, jjj] == 0)//如果当前位置值是0
                    {
                        //map[iii, jjj] = 7;
                        if (map[iii - 1, jjj] != 0)//如果上面的数不等于0
                        {
                            map[iii, jjj] = map[iii - 1, jjj];//把上面的数给这里
                            map[iii - 1, jjj] = 0;//上面的数设为0
                        }
                        else//如果上面的数等于0,【再往上找】
                        {
                            while (map[iii, jjj] == 0)
                            {
                                if (map[iii - 1, jjj] != 0)
                                {
                                    map[iii + topNum, jjj] = map[iii - 1, jjj];
                                }
                                else
                                {
                                    iii--;
                                    topNum++;
                                }
                            }
                        }
                    }
                    Console.Write(map[iii, jjj] + " ");
                }
                Console.WriteLine();
            }

我被困在了“怎样向上找到下一个非零数字,然后把这个数沉下来”这里了

共11条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!