人狼羊菜2018年对象版本

新建Transport类,因方法和属性都有对应的详细说明,故不再赘述。

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/// <summary>
/// 运输类
/// </summary>
public class Transport
{
/// <summary>
/// 运输对象名称
/// </summary>
public string ObjectName { get; set; }

/// <summary>
/// 运输方向描述
/// </summary>
public string DirectionDescription { get; set; }

/// <summary>
/// 校验初始状态的函数
/// </summary>
Func<int, bool> ValidInitStateFuc { get; set; }

/// <summary>
/// 校验结束状态的函数
/// </summary>
Func<int, bool> ValidEndStateFuc { get; set; }

/// <summary>
/// 单次运输函数
/// </summary>
Func<int, int> MoveFunc { get; set; }

public Transport(string objectName, Func<int, bool> validInitState, Func<int, bool> validEndState,
Func<int, int> moveFunc)
{
this.ObjectName = objectName;
this.ValidInitStateFuc = validInitState;
this.ValidEndStateFuc = validEndState;
this.MoveFunc = moveFunc;
}

/// <summary>
/// 运输方法
/// </summary>
/// <param name="state">初始状态</param>
/// <returns>运输之后的状态</returns>
public int Transfer(int state)
{
if (ValidInitStateFuc(state))
{
int result = MoveFunc(state);
if (ValidEndStateFuc(result))
{
DirectionDescription = result > 8 ? "从A岸到了B岸。" : "从B岸到了A岸。";
Console.WriteLine(ObjectName + DirectionDescription);
return result;
}
}

return state;
}
}

调用方法如下

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
static void Main(string[] args)
{
Console.WriteLine("transports 开始");

//判断是否合法状态
bool ValidEndState(int state) => state != 3 && !(state >= 6 && state <= 9) && state != 12;

//判断人是否和羊在一起
bool IsPeopleWithSheep(int state) => state / 2 % 2 == 0 && state < 8 || state / 2 % 2 == 1 && state >= 8;

//判断人是否和狼在一起
bool IsPeopleWithWolf(int state) => !(state >= 4 && state <= 11);

//判断人是否和菜在一起
bool IsPeopleWithGreens(int state) => state % 2 == 0 && state < 8 || state % 2 == 1 && state >= 8;

//运输人和青菜
int TransferPeopleWithGreens(int i) => i ^ 9;

//运输人和羊
int TransferPeopleWithSheep(int i) => i ^ 10;

//运输人和狼
int TransPeopleWithWolf(int i) => i ^ 12;

//运输人和狼
int TransPeople(int i) => i ^ 8;
Transport transport1 = new Transport("人和菜", IsPeopleWithGreens, ValidEndState, TransferPeopleWithGreens);
Transport transport2 = new Transport("人和羊", IsPeopleWithSheep, ValidEndState, TransferPeopleWithSheep);
Transport transport3 = new Transport("人和狼", IsPeopleWithWolf, ValidEndState, TransPeopleWithWolf);
Transport transport4 = new Transport("人", state => true, ValidEndState, TransPeople);
List<Transport> transports = new List<Transport> {transport1, transport2, transport3, transport4};
int tempState = 0;
int EndState = 15;
while (tempState != EndState)
{
foreach (var actionItem in transports)
{
tempState = actionItem.Transfer(tempState);
}
}

Console.WriteLine("transports 结束");
Console.ReadKey();
}

运行结果如下

1
2
3
4
5
6
7
8
9
transports 开始
人和羊从A岸到了B岸。
人从B岸到了A岸。
人和菜从A岸到了B岸。
人和羊从B岸到了A岸。
人和狼从A岸到了B岸。
人从B岸到了A岸。
人和羊从A岸到了B岸。
transports 结束

参考资料

人狼羊菜2018年过程版本

分析

假设开始人狼羊菜都是在A岸,目的是将人狼羊菜运输到B岸。
人,狼,羊,菜在A岸的标识为0,在B岸的标识位为1。经过枚举可以得出16种状态中不符合的有6种。
如图所示

人狼羊菜状态图

根据以上描述的状态模式,可以将问题转化为

  • 判断运输的终止状态是否合法
  • 判断人和羊是否在一侧
  • 判断人和菜是否在一侧
  • 判断人和狼是否在一侧
  • 执行人独自过河的动作
  • 执行人和羊一起过河的动作
  • 执行人和狼一起过河的动作
  • 执行人和菜一起过河的动作

新建MoveClass类

1
2
3
4
5
6
7
/// <summary>
/// 人狼羊菜运输类
/// </summary>
public class MoveClass
{

}

依次对应的函数如下

1
2
3
4
5
6
7
8
9
/// <summary>
/// 状态合法
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public bool IsVaild(int state)
{
return state != 3 && !(state >= 6 && state <= 9) && state != 12;
}
1
2
3
4
5
6
7
8
9
/// <summary>
/// 人和羊在一起返回真
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public bool IsPeopleWithSheep(int state)
{
return ((state / 2) % 2 == 0 && state < 8) || ((state / 2) % 2 == 1 && state >= 8);
}
1
2
3
4
5
6
7
8
9
/// <summary>
/// 人和菜在一起返回真
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public bool IsPeopleWithGreens(int state)
{
return state % 2 == 0 && state < 8 || state % 2 == 1 && state >= 8;
}
1
2
3
4
5
6
7
8
9
/// <summary>
/// 人和狼在一起返回真
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public bool IsPeopleWithWolf(int state)
{
return !(state >= 4 && state <= 11);
}
1
2
3
4
5
6
7
8
9
/// <summary>
/// 只身一人过河
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public int MovePerson(int state)
{
return state ^ 8;
}
1
2
3
4
5
6
7
8
9
/// <summary>
/// 人带羊过河
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public int MovePersonWithSheep(int state)
{
return state ^ 10;
}
1
2
3
4
5
6
7
8
9
/// <summary>
/// 人带狼过河
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public int MovePersonWithWolf(int state)
{
return state ^ 12;
}
1
2
3
4
5
6
7
8
9
/// <summary>
/// 人带菜过河
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public int MovePersonWithGreens(int state)
{
return state ^ 9;
}

主要的逻辑函数

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public void Move()
{
int state = 0, tempState;
int EndState = 15;
while (state != EndState)
{
tempState = MovePerson(state);
if (IsVaild(tempState))
{
state = tempState;
Console.WriteLine(state > 8 ? "人独自一人从A岸到达B岸" : "人独自一人从B岸到达A岸");
}

if (IsPeopleWithSheep(state))
{
tempState = MovePersonWithSheep(state);
if (IsVaild(tempState))
{
state = tempState;
Console.WriteLine(state > 8 ? "人带羊从A岸到达B岸" : "人带羊从B岸到达A岸");
}
}

if (IsPeopleWithWolf(state))
{
tempState = MovePersonWithWolf(state);
if (IsVaild(tempState))
{
state = tempState;
Console.WriteLine(state > 8 ? "人带狼从A岸到达B岸" : "人带狼从B岸到达A岸");
}
}

if (IsPeopleWithGreens(state))
{
tempState = MovePersonWithGreens(state);
if (IsVaild(tempState))
{
state = tempState;
Console.WriteLine(state > 8 ? "人带菜从A岸到达B岸" : "人带菜从B岸到达A岸");
}
}
}
}

执行以上逻辑函数

1
2
3
4
Console.WriteLine("MoveClass 开始");
new MoveClass().Move();
Console.WriteLine("MoveClass 结束");
Console.ReadKey();

最终运行结果如下:

1
2
3
4
5
6
7
8
9
MoveClass 开始
人带羊从A岸到达B
人独自一人从B岸到达A
人带狼从A岸到达B
人带羊从B岸到达A
人带菜从A岸到达B
人独自一人从B岸到达A
人带羊从A岸到达B
MoveClass 结束

参考资料

人狼羊菜2012年版本

这是我初接触编程时编写的Java代码,待有足够时间会重构该代码。

实现代码

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
假设开始人狼羊菜都是在A岸,目的是将人狼羊菜运输到B岸。
*/
public class Thing {
public static void main(String[] args) {
int i = 0, x, k = 0;
while (i != 15) {
k = 0;
if (((i % 2 == 0) && i < 8) || (i % 2 == 1 && i >= 8)) {
x = i ^ 9;
if (x != 3 && !(x >= 6 && x <= 9) && x != 12) {
i = x;
k++;
if(i>8)
System.out.println("人带菜从A岸到达B岸");
else
System.out.println("人带菜从B岸到达A岸");
}
}
if (((i / 2) % 2 == 0 && i < 8) || ((i / 2) % 2 == 1 && i >= 8)) {
x = i ^ 10;
if (x != 3 && !(x >= 6 && x <= 9) && x != 12) {
i = x;
k++;
if(i>8)
System.out.println("人带羊从A岸到达B岸");
else
System.out.println("人带羊从B岸到达A岸");
}
}
if (!(i >= 4 && i <= 11)) {
x = i ^ 12;
if (x != 3 && !(x >= 6 && x <= 9) && x != 12) {
i = x;
k++;
if(i>8)
System.out.println("人带狼从A岸到达B岸");
else
System.out.println("人带狼从B岸到达A岸");
}

}
x = i ^ 8;
if (x != 3 && !(x >= 6 && x <= 9) && x != 12) {
i = x;
k++;
if(i>8)
System.out.println("人独自一人从A岸到达B岸");
else
System.out.println("人独自一人从B岸到达A岸");
}
}
}
}

运行结果如下:

人带羊从A岸到达B岸
人独自一人从B岸到达A岸
人带菜从A岸到达B岸
人带羊从B岸到达A岸
人带狼从A岸到达B岸
人独自一人从B岸到达A岸
人带羊从A岸到达B岸

总结

该代码混乱不堪,类命名,变量命名都不符合编码规范,写出来的代码比反编译之后的更难阅读,抽时间会给出重构后的版本。

参考资料