尽量使用扩展性高的代码,图案如下:
解决这个问题,我们可以想象成一个物体在正方形中移动
移动的方式有:
1、向一个方向一直移动直到碰到边缘或者碰到其他物体;
2、向一个方向移动一次就够了;
3、移动方向的优先级,比如优先往上移动,再向左移动;
4、探测方式移动,如果碰到其他物体就继续向同方向探测,直到有空位;
5、旋转试移动,优先级高的方向移动成功后就放弃优先级低的移动方向。
/*
01--02--03--04--05--06--07--08
|
28--29--30--31--32--33--34 09
| | |
27 48--49--50--51--52 35 10
| | | | |
26 47 60--61--62 53 36 11
| | | | | | |
25 46 59 64--63 54 37 12
| | | | | |
24 45 58--57--56--55 38 13
| | | |
23 44--43--42--41--40--39 14
| |
22--21--20--19--18--17--16--15
//
01--02 06--07 15--16 28--29
/ / / / / / /
03 05 08 14 17 27 30 43
| / / / / / / / |
04 09 13 18 26 31 42 44
/ / / / / / /
10 12 19 25 32 41 45 54
| / / / / / / / |
11 20 24 33 40 46 53 55
/ / / / / / /
21 23 34 39 47 52 56 61
| / / / / / / / |
22 35 38 48 51 57 60 62
/ / / / / / /
36--37 49--50 58--59 63--64
//
01--02 04 07 11 16 22 29
/> / / / / / /
03 05 08 12 17 23 30 37
/> / / / / / /
06 09 13 18 24 31 38 44
/> / / / / / /
10 14 19 25 32 39 45 50
/> / / / / / /
15 20 26 33 40 46 51 55
/> / / / / / /
21 27 34 41 47 52 56 59
/> / / / / / /
28 35 42 48 53 57 60 62
/> /> /> /> /> /> /
36 43 49 54 58 61 63--64
//
01 09 23 35 45 53 59 63
/ / / / / / />
16 02 10 24 36 46 54 60
/ / / / / / />
29 17 03 11 25 37 47 55
/ / / / / / />
40 30 18 04 12 26 38 48
/ / / / / / />
49 41 31 19 05 13 27 39
/ / / / / / />
56 50 42 32 20 06 14 28
/ / / / / / />
61 57 51 43 33 21 07 15
/> /> /> /> /> /> />
64 62 58 52 44 34 22 08
//
64--63--62--61--60--59--58--57
|
37--38--39--40--41--42--43 56
| | |
36--35--34--33--32--31 44 55
| | |
17--18--19--20--21 30 45 54
| | | | |
16--15--14--13 22 29 46 53
| | | | |
05--06--07 12 23 28 47 52
| | | | | | |
04--03 08 11 24 27 48 51
| | | | | | |
01--02 09--10 25--26 49--50
//
01--02--03--04--05--06--07--08
|
16--15--14--13--12--11--10--09
|
17--18--19--20--21--22--23--24
|
32--31--30--29--28--27--26--25
|
33--34--35--36--37--38--39--40
|
48--47--46--45--44--43--42--41
|
49--50--51--52--53--54--55--56
|
64--63--62--61--60--59--58--57
*/
解决这个问题,我们可以想象成一个物体在正方形中移动
移动的方式有:
1、向一个方向一直移动直到碰到边缘或者碰到其他物体;
2、向一个方向移动一次就够了;
3、移动方向的优先级,比如优先往上移动,再向左移动;
4、探测方式移动,如果碰到其他物体就继续向同方向探测,直到有空位;
5、旋转试移动,优先级高的方向移动成功后就放弃优先级低的移动方向。
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Text.RegularExpressions;
- namespace BoxGame
- {
- class Program
- {
- /// <summary>
- /// 方向
- /// </summary>
- public enum Direction
- {
- North,
- South,
- West,
- East,
- Southwest,
- Southeast,
- Northeast,
- Northwest
- }
- /// <summary>
- /// 移动指令
- /// </summary>
- public class MoveDictate
- {
- /// <summary>
- /// 移动方向表,按优先排列顺序
- /// </summary>
- public List<Direction> directions = new List<Direction>();
- /// <summary>
- /// 是否跳出指令
- /// </summary>
- public bool isBreak;
- /// <summary>
- /// 是否为分析模式
- /// </summary>
- public bool isTry;
- /// <summary>
- /// 是否旋转模式
- /// </summary>
- public bool isEddy;
- /// <summary>
- /// 分析坐标
- /// </summary>
- public Point point;
- /// <summary>
- /// 最多界限
- /// </summary>
- public int max = int.MaxValue;
- /// <summary>
- /// 解析字符串
- /// </summary>
- /// <param name="s">字符串</param>
- /// <returns>返回移动指令</returns>
- public static MoveDictate Parse(string s)
- {
- MoveDictate result = new MoveDictate();
- result.isBreak = s.IndexOf('跳') >= 0;
- result.isTry = s.IndexOf('探') >= 0;
- result.isEddy = s.IndexOf('旋') >= 0;
- Match m = Regex.Match(s, @"/[(?<x>.*?),(?<y>.*?)/]");
- if (m.Success)
- {
- int x = result.point.X;
- int y = result.point.Y;
- int.TryParse(m.Result("${x}"), out x);
- int.TryParse(m.Result("${y}"), out y);
- result.point = new Point(x, y);
- }
- foreach (char c in s)
- {
- int i = "↑↓←→↖↗↙↘".IndexOf(c);
- if (i >= 0)
- result.directions.Add((Direction)i);
- }
- return result;
- }
- }
- /// <summary>
- /// 盒子游戏
- /// </summary>
- public class BoxGame
- {
- /// <summary>
- /// 边大小
- /// </summary>
- int size;
- /// <summary>
- /// 指令序号
- /// </summary>
- int dictate;
- /// <summary>
- /// 是否逆向填写
- /// </summary>
- bool isReverse;
- /// <summary>
- /// 当前坐标
- /// </summary>
- Point current = new Point(0, 0);
- /// <summary>
- /// 数字矩形
- /// </summary>
- int[,] numbers;
- /// <summary>
- /// 方向偏移
- /// </summary>
- Point[] offsets = new Point[]{
- new Point(0, -1),
- new Point(0, +1),
- new Point(-1, 0),
- new Point(+1, 0),
- new Point(-1, -1),
- new Point(+1, -1),
- new Point(-1, +1),
- new Point(+1, +1)};
- /// <summary>
- /// 移动指令集
- /// </summary>
- List<MoveDictate> moveDictates = new List<MoveDictate>();
- /// <summary>
- /// 移动
- /// </summary>
- /// <param name="dest">目标点</param>
- /// <returns>返回移动是否成功</returns>
- bool Move(MoveDictate moveDictate, ref Point dest)
- {
- bool isBrack = false;
- do
- {
- isBrack = true;
- for (int i = 0; i < moveDictate.directions.Count; i++)
- {
- if (moveDictate.isEddy && i > moveDictate.max) break;
- int d = (int)moveDictate.directions[i];
- Point temp = moveDictate.isTry ? moveDictate.point : dest;
- temp.Offset(offsets[d].X, offsets[d].Y);
- if (Rectangle.FromLTRB(0, 0, size, size).Contains(temp))
- {
- if (numbers[temp.X, temp.Y] == 0)
- {
- dest = temp;
- if (moveDictate.isEddy) moveDictate.max = i;
- return true;
- }
- if (moveDictate.isTry)
- {
- moveDictate.point = temp;
- isBrack = false;
- break;
- }
- }
- }
- } while (!isBrack);
- return false;
- }
- /// <summary>
- /// 播放
- /// </summary>
- /// <param name="size">宽度</param>
- /// <param name="dictates">指令字符串</param>
- public void Play(int size, string s)
- {
- this.size = size;
- s = s.Replace("边", (size - 1).ToString());
- isReverse = s.IndexOf('逆') >= 0;
- MatchCollection mc = Regex.Matches(s, @"/{(?<dictate>.*?)/}");
- foreach (Match match in mc)
- moveDictates.Add(MoveDictate.Parse(match.Result("${dictate}")));
- Match m = Regex.Match(Regex.Replace(s, @"/{.*?/}", ""), @"/[(?<x>.*?),(?<y>.*?)/]");
- if (m.Success)
- {
- int x = current.X;
- int y = current.Y;
- int.TryParse(m.Result("${x}"), out x);
- int.TryParse(m.Result("${y}"), out y);
- current = new Point(x, y);
- }
- numbers = new int[size, size];
- numbers[current.X, current.Y] = isReverse ? size * size : 1;
- for (int i = 2; i <= size * size; i++)
- {
- Point next = current;
- for (int j = 0; j < moveDictates.Count; j++)
- {
- if (Move(moveDictates[dictate], ref next))
- {
- if (moveDictates[dictate].isBreak)
- {
- if (moveDictates[dictate].isEddy)
- moveDictates[dictate].max = int.MaxValue;
- dictate = (dictate + 1) % moveDictates.Count;
- }
- current = next;
- break;
- }
- else
- {
- if (moveDictates[dictate].isEddy)
- moveDictates[dictate].max = int.MaxValue;
- dictate = (dictate + 1) % moveDictates.Count;
- }
- }
- numbers[current.X, current.Y] = isReverse ? size * size - i + 1 : i;
- }
- for (int j = 0; j < size; j++)
- {
- for (int i = 0; i < size; i++)
- Console.Write("{0}{1:D2}", i > 0 ? " " : "", numbers[i, j]);
- Console.WriteLine();
- Console.WriteLine();
- }
- }
- }
- static void Main(string[] args)
- {
- int n = 8;
- new BoxGame().Play(n, "{→↓}{←↑}"); // 1号图
- Console.WriteLine("-------");
- new BoxGame().Play(n, "{→跳}{↙}{↓跳}{↗}"); // 2号图
- Console.WriteLine("-------");
- new BoxGame().Play(n, "{↙}{[0,0]→↓探跳}"); // 3号图
- Console.WriteLine("-------");
- new BoxGame().Play(n, "{↘}{[0,0]→探跳}{↘}{[0,0]↓探跳}"); // 4号图
- Console.WriteLine("-------");
- new BoxGame().Play(n, "[0,边]{→跳}{←↑旋}{↑跳}{↓→旋}"); // 5号图
- Console.WriteLine("-------");
- new BoxGame().Play(n, "{→←↓}"); // 6号图
- Console.ReadKey();
- }
- }
- }