背景:
阅读文章

汉诺塔游戏

[日期:2007-05-11] 来源:  作者: [字体: ]

标  题: 写的一个小游戏
发信站: 一塌糊涂 BBS (Sat Sep 15 18:04:53 2001)

// hanoi.c
// 汉诺塔是一种古老的数学游戏,有三个底座(base),一开始
// 所有的盘子都按从小到大的顺序从上到下的放在第一个底座
// (base/A)里。其要求是把第一个底座中的盘子利用第二个底
// 座(base/B)全部移到第三个底座中。其中小的盘子只能放在


// 大的盘子上面,每次只能移动一个盘子。这个题目可以用递
// 归的方法求解(最少的完成步数 = 2 ^ 盘子数目 - 1)。

#include

#define MAX     my["max"]       // 总共盘子数
#define START   my["start"]     // 开始游戏者
#define BASE    my["base"]      // 底座的状态
#define STEP    my["step"]      // 已走的步数

inherit ITEM;
inherit F_SAVE;
inherit F_AUTOLOAD;

int do_help(string arg);

int query_autoload() { return 1; }
string query_save_file() { return __DIR__ "hanoi/" + query("start"); }

void create()
{
        set_name(HIY "汉诺塔" NOR, ({ "hanoi" }));
        set_weight(100);
       
        set("long", "这是一套古老数学游戏汉诺塔的模型。\n");
        set("unit", "套");
       
        set("base", ([
                "A" : ({ }),
                "B" : ({ }),
                "C" : ({ }),
        ]));
}

// 提供指令
void init()
{
        add_action("do_new", "new");            // 新游戏
        add_action("do_stop", "stop");          // 结束游戏
        add_action("do_record", "record");      // 保存游戏
        add_action("do_load", "load");          // 载入游戏
        add_action("do_move", "move");          // 移动盘子
        add_action("do_help", "help");          // 帮助信息
}

// 显示目前状态
string long()
{
        mapping my = query_entire_dbase();
        mapping info;
        string *msg, line, base, long;
        int i, j, max;

        if (! START)
                return my["long"];

        info = ([ ]);
        max = MAX * 2 + 4;
        foreach (base in keys(BASE))
        {
                msg = ({ });
                BASE[base] = sort_array(BASE[base], 1);
                for (i = 0; i < MAX; i++)
                {
                        j = i - (MAX - sizeof(BASE[base]));

                        if (j < 0)
                                line = repeat_string(" ", (max - 2) / 2) + WHT
"│" NOR +
                                       repeat_string(" ", (max - 2) / 2);
                        else
                        {
                                line = repeat_string(" ", (max - BASE[base][j]
* 2) / 2) +
                                       CYN + repeat_string("━", BASE[base][j]
) + NOR +
                                       repeat_string(" ", (max - BASE[base][j]
* 2) / 2);
                        }

                        msg += ({ line });
                }
                info[base] = msg;
        }
        set("info", info);
        long = WHT "现在" + ((! STEP) ? "第一步还没走"
                                      : "已经走了 " + STEP + " 步") + "。\n\n"
+ NOR;

        for (i = 0; i < MAX; i++)
        {
                long += sprintf("%s%s%s\n", info["A"][i], info["B"][i], info["
C"][i]);
        }
        return long;
}

int do_new(string arg)
{
        object me = this_player();
        mapping my = query_entire_dbase();
        int i, max;
       
        if (stringp(START))
                return notify_fail("游戏已经开始了,你得先停止它。\n");

        if (! arg) max = 3;
        else if (! sscanf(arg, "%d", max) || max > 9)
                return notify_fail("输入的格式错误。\n");
       
        START = me->query("id");
        MAX = max;
        STEP = 0;
        for (i = 0; i < max; i++)
        {
                BASE["A"] += ({ i + 1, });
        }
       
        write("游戏创建完毕,输入(help here)可以获得帮助。\n");
        write(long());
        return 1;
}

void end_game()
{
        delete("max");
        delete("start");
        delete("base");
        delete("step");
        set("base", ([
                "A" : ({ }),
                "B" : ({ }),
                "C" : ({ }),
        ]));
}

int do_move(string arg)
{
        object me = this_player();
        mapping my;
        string from, to;
       
        if (! arg || sscanf(arg, "%s to %s", from, to) != 2)
                return do_help("move");

        if (from == to)
                return notify_fail("你脑潮了?\n");

        my = query_entire_dbase();
       
        if (me->query("id") != START)
                return notify_fail("你可别乱动。\n");

        if (member_array(from, keys(BASE)) == -1 ||
            member_array(to, keys(BASE)) == -1)
                return notify_fail("底座只可能是" + implode(keys(BASE), "、")
+
                                   "其中之一。\n");

        if (! sizeof(BASE[from]))
                return notify_fail("底座" + from + "那里可没有盘子呀。\n");

        BASE[from] = sort_array(BASE[from], 1);
        BASE[to] = sort_array(BASE[to], 1);
       
        if (sizeof(BASE[to]) && sizeof(BASE[from]) && BASE[to][0] < BASE[from]
[0])
                return notify_fail("大的盘子不能放在小的盘子上面。\n");
       
        tell_object(me, WHT "你把底座" + from + "的" + chinese_number(BASE[fro
m][0]) +
                        "号盘子移动到了底座" + to + "上。\n" NOR);
       
        BASE[to] = ({ BASE[from][0] }) + BASE[to];
        BASE[from] -= ({ BASE[from][0] });
        STEP++;
        write(long());
       
        if (sizeof(BASE["C"]) == MAX)
        {
                write(WHT "\n恭喜你完成了游戏。\n" NOR);
                end_game();
        }
       
        return 1;
}

int do_stop(string arg)
{
        object me = this_player();
        mapping my;

        my = query_entire_dbase();
       
        if (! stringp(START))
                return notify_fail("还没开始呢,结束个啥?\n");

        if (me->query("id") != START)
                return notify_fail("只有游戏进行者才能结束这个游戏。\n");

        end_game();
        write(WHT "你结束了当前的游戏。\n" NOR);
        return 1;
}

int do_record(string arg)
{
        object me = this_player();
        mapping my;

        my = query_entire_dbase();
       
        if (! stringp(START))
                return notify_fail("还没开始呢,保存个啥?\n");

        if (me->query("id") != START)
                return notify_fail("只有游戏进行者才能保存游戏。\n");

        save();
        write(WHT "当前游戏保存完毕。\n" NOR);
        return 1;
}

int do_load(string arg)
{
        object me = this_player();
        mapping my;

        my = query_entire_dbase();
       
        if (stringp(START))
                return notify_fail("游戏已经开始了,你还是先把它停止吧。\n");


        if (file_size(__DIR__ "hanoi/" + me->query("id") + ".o") <= 0)
                return notify_fail("你并没有保存过游戏呀。\n");
               
        START = me->query("id");
        restore();
        write(WHT "上一次的游戏载入完毕。\n" NOR);
        write(long());
        return 1;
}

int do_help(string arg)
{
        switch (arg)
        {
        case "here":
                write(@HELP
在这里你可以使用以下这些和汉诺塔相关的命令:
    new          开始一局新游戏
    stop         结束这局游戏
    record       保存当前的游戏
    load         载入保存的游戏
    move         移动一个盘子
HELP );
                break;

        case "new":
                write(@HELP_NEW
指令格式 : new [盘子数目]

此指令让你开始一局新的汉诺塔游戏,当这套汉诺塔已经开始了游戏
时,你必须先把这个游戏关闭(stop)。建议你在关闭前保存(record)。
你可以指定游戏中初始盘子的数目,但最多不得超过 9个,一开始盘
子会全部被放到底座 A中,你需要把它们全部一个个移(move)到底座
C 中就是赢得胜利。注意:大的盘子不得放在小的盘子上面。

相关指令:stop, record, move
HELP_NEW );
                break;

        case "stop":
                write(@HELP_STOP
指令格式 : stop

停止这局游戏,你必须是这局游戏的进行者才能这么做。

HELP_STOP );
                break;

        case "record":
                write(@HELP_RECORD
指令格式 : record

此指令让你保存现在正在进行的游戏以备下次继续玩,你必须是这局
游戏的进行者才能这么做。保存以后可以用(load)在没有游戏正在进
行的情况下调入。注意:假如你这个 ID 以前已经保存过游戏,那么
会把以前的游戏档案覆盖掉。

相关指令:load
HELP_RECORD );
                break;

        case "load":
                write(@HELP_LOAD
指令格式 : load

载入一个你上次玩的游戏,得先停止(stop)目前的游戏再说。

相关指令:record, stop
HELP_LOAD);
                break;

        case "move":
                write(@HELP_MOVE
指令格式 : move  to

把底座 A、B、C 中最上面的一个盘子移动到另一个底座中去,大的
盘子不得放在小的盘子上面。当你把底座 A 的所有盘子都移到了底
座 C 中,就会获胜并结束这局游戏。
HELP_MOVE );
                break;

        default:
                return notify_fail("你要查看什么帮助?\n");
        }

        return 1;
}


尊重作者 转载请注明出处52mud.com

收藏 推荐 打印 | 录入:sbso | 阅读:
相关内容      
内容推送
52mud提供
一起回忆泥巴游戏QQ群68186072
52mud官方微信公众平台
热门评论