📜  传教士和食人者(1)

📅  最后修改于: 2023-12-03 15:06:41.976000             🧑  作者: Mango

传教士和食人者

简介

传教士和食人者(Missionaries and Cannibals)是一种经典的智力游戏,需要玩家运用逻辑思维解决问题。该游戏的玩法是将三个传教士和三个食人者通过一条小船运到对岸,但是小船只能坐两个人,而且传教士人数不能少于食人者人数,否则传教士将会被食人者吃掉。

游戏规则
  1. 有一艘小船和两个岸边。
  2. 在一个岸边有三个传教士和三个食人者。他们都想要过河,但小船只能坐两个人,而且传教士人数不能少于食人者人数,否则传教士会被吃掉。
  3. 玩家可以点击人物或小船来移动它们。
  4. 当小船到达另一岸时,玩家获胜。
游戏截图

传教士和食人者

源代码

以下是使用 Python 写的传教士和食人者游戏源代码:

# 写得不好,请不要在意

import copy

class Node:
    def __init__(self, m, c, b):
        self.m = m  # 左岸传教士数量
        self.c = c  # 左岸食人者数量
        self.b = b  # 0 表示船在左岸,1 表示船在右岸
        self.parent = None  # 父节点

    def is_valid(self):
        if self.m < 0 or self.c < 0 or self.m > 3 or self.c > 3:
            return False
        if self.m > 0 and self.m < self.c:
            return False
        if self.m < 3 and self.m + self.c > 3:
            return False
        return True

    def is_final(self):
        if self.m == 0 and self.c == 0 and self.b == 1:
            return True
        return False

    def successors(self):
        children = []
        if self.b == 0:  # 船在左岸
            # 移动一个传教士
            n = Node(self.m - 1, self.c, 1)
            if n.is_valid():
                n.parent = self
                children.append(n)
            # 移动一个食人者
            n = Node(self.m, self.c - 1, 1)
            if n.is_valid():
                n.parent = self
                children.append(n)
            # 移动一个传教士和一个食人者
            n = Node(self.m - 1, self.c - 1, 1)
            if n.is_valid():
                n.parent = self
                children.append(n)
            # 移动两个传教士
            n = Node(self.m - 2, self.c, 1)
            if n.is_valid():
                n.parent = self
                children.append(n)
            # 移动两个食人者
            n = Node(self.m, self.c - 2, 1)
            if n.is_valid():
                n.parent = self
                children.append(n)
        else:  # 船在右岸
            # 移动一个传教士
            n = Node(self.m + 1, self.c, 0)
            if n.is_valid():
                n.parent = self
                children.append(n)
            # 移动一个食人者
            n = Node(self.m, self.c + 1, 0)
            if n.is_valid():
                n.parent = self
                children.append(n)
            # 移动一个传教士和一个食人者
            n = Node(self.m + 1, self.c + 1, 0)
            if n.is_valid():
                n.parent = self
                children.append(n)
            # 移动两个传教士
            n = Node(self.m + 2, self.c, 0)
            if n.is_valid():
                n.parent = self
                children.append(n)
            # 移动两个食人者
            n = Node(self.m, self.c + 2, 0)
            if n.is_valid():
                n.parent = self
                children.append(n)
        return children

def print_solution(node):
    n = node
    path = []
    while n is not None:
        path.append(n)
        n = n.parent
    path.reverse()
    for node in path:
        print("M" + str(node.m) + "C" + str(node.c), end='')
        if node.b == 0:
            print(" -> ", end='')
        else:
            print(" <- ", end='')
    print("")

def bfs():
    init = Node(3, 3, 0)
    if init.is_final():
        print_solution(init)
        return
    queue = []
    queue.append(init)
    visited = set()
    visited.add((init.m, init.c, init.b))
    while queue:
        n = queue.pop(0)
        for child in n.successors():
            if (child.m, child.c, child.b) not in visited:
                if child.is_final():
                    print_solution(child)
                    return
                queue.append(child)
                visited.add((child.m, child.c, child.b))

bfs()
其他实现

除了 Python,传教士和食人者还可以使用其他编程语言来实现。例如,下面是使用 JavaScript 写的传教士和食人者游戏:http://codepen.io/cybercase/pen/odBpJW