[M3] pushbox.c [推箱子程序]
/* -----------------------------------------------------------------------
原始聲明
---------------------------------------------------------
orign program name: worker.c
Chinese name: 推箱子
this program is a GNU free software
first written by period.bbs@smth.org
and cityhunter.bbs@smth.org, Nov 11, 1998(?)
rewitten by zhch.bbs@bbs.nju.edu.cn, Nov 27, 2000
new: so/pushbox.c
rewriten by hightman.bbs@bbs.hightman.net Aug 28, 2002
------------------------------------------------------------------------- */
#include "bbs.h"
#ifdef HAVE_TTY_GAME
#define MAP_DATA_PATH "game/pushbox.map"
#define MAX_MAP_NUM 50
#define MAX_MAP_WIDTH 20
#define MAX_MAP_HEIGHT 16
#define KEY_BACKSPACE 8
#define MAX_MOVE_TIMES 1000
#define move2(y, x) move(y+3, x*2+2)
static int map_data[MAX_MAP_NUM][MAX_MAP_HEIGHT][MAX_MAP_WIDTH];
static int map_now[MAX_MAP_HEIGHT][MAX_MAP_WIDTH];
static int map_total = 1;
static char *xstring[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"
, "L", "M", "N", "O", "P", "Q", "R", "S", "T", NULL};
static char *ystring[] = {"01", "02", "03", "04", "05", "06", "07", "08", "09",
"10", "11", "12", "13", "14", "15", "16", NULL};
static int stage;
static int now_y, now_x;
struct history {
int max;
char y0[MAX_MOVE_TIMES * 2];
char x0[MAX_MOVE_TIMES * 2];
char y1[MAX_MOVE_TIMES * 2];
char x1[MAX_MOVE_TIMES * 2];
} my_history;
static char *
map_char(n)
int n;
{
if(n&8) return "■";
if(n&4) return "□";
if(n&2) return "⊙";
if(n&1) return "﹒";
return " ";
}
static int
map_init() {
FILE *fp;
int map_y = 0, map_x = 0;
char buf[80];
fp = fopen(MAP_DATA_PATH, "r");
if (fp == NULL) return 0;
map_x = 0;
while (fgets(buf, 80, fp))
{
if (!str_ncmp(buf, "--", 2))
{
map_y = 0;
map_total++;
}
if (map_total > MAX_MAP_NUM) break;
for (map_x = 0; map_x < MAX_MAP_HEIGHT; map_x++)
{
if (!str_ncmp(buf + map_x*2, map_char(1), 2))
map_data[map_total-1][map_y][map_x] = 1;
else if (!str_ncmp(buf + map_x*2, map_char(2), 2))
map_data[map_total-1][map_y][map_x] = 2;
else if (!str_ncmp(buf + map_x*2, map_char(4), 2))
map_data[map_total-1][map_y][map_x] = 4;
else if (!str_ncmp(buf + map_x*2, map_char(8), 2))
map_data[map_total-1][map_y][map_x] = 8;
else
map_data[map_total-1][map_y][map_x] = 0;
}
if (map_y < MAX_MAP_HEIGHT) map_y++;
}
fclose(fp);
return 1;
}
static int
map_show() {
int m, n;
move(2, 0);
clrtobot();
outs(" ");
for (m = 0; m <MAX_MAP_WIDTH; m++)
prints("%-2s", xstring[m]);
for (n = 0; n < MAX_MAP_HEIGHT; n++)
{
outs("\n");
prints("%2s", ystring[n]);
for (m = 0; m < MAX_MAP_WIDTH; m++)
{
if (map_now[n][m] == 5)
prints("\033[1;32m%s\033[0m", map_char(map_now[n][m]));
else
outs(map_char(map_now[n][m]));
}
}
move(MAX_MAP_HEIGHT + 2, 0);
prints("歡迎光臨 %s - 推箱子游戲", str_site);
outs("\n\033[0;34;46m 按鍵說明 \033[47m \033[31m(↑↓←→)\033[30m移動 \033
[31m(^C ^D)\033[30m退出 \033[31m(BackSpace)\033[30m悔推 \033[31m(Tab)\033[30m重
開 \033[31m(^L)\033[30m刷新屏幕\033[m");
move2(now_y, now_x);
}
static int
map_show_line(y)
int y;
{
int i;
move2(y, 0);
clrtoeol();
for (i = 0; i < MAX_MAP_WIDTH; i++)
{
if (map_now[y][i] == 5)
prints("\033[1;32m%s\033[0m", map_char(map_now[y][i]));
else
outs(map_char(map_now[y][i]));
}
}
static int
check_if_win()
{
int m, n;
for (n=0; n < MAX_MAP_HEIGHT; n++)
{
for (m = 0; m < MAX_MAP_WIDTH; m++)
{
if (map_now[n][m]==1 || map_now[n][m]==3) return 0;
}
}
return 1;
}
static int
find_y_x(int *y, int *x) {
int m, n;
for (n=0; n < MAX_MAP_HEIGHT; n++)
{
for (m=0; m < MAX_MAP_WIDTH; m++)
{
if (map_now[n][m] & 2) {
*x = m;
*y = n;
return 1;
}
}
}
return 0;
}
static void
map_move(int y0, int x0, int y1, int x1)
{
int b0, f0, b1;
b0 = map_now[y0][x0] & 1;
f0 = map_now[y0][x0] & 6;
b1 = map_now[y1][x1] & 1;
map_now[y1][x1] = f0 | b1;
map_now[y0][x0] = b0;
map_show_line(y0);
map_show_line(y1);
move(1, 0);
clrtoeol();
prints("第 \033[1;32m%d\033[m 關 第 \033[1;31m%d\033[m 步 From: (%s,%s) To:
(%s,%s) 您已獲得獎金: %d",
stage, my_history.max, xstring[x0], ystring[y0], xstring[x1], ystring[y1]);
}
static int
select_stage()
{
char stage_str[4];
int stage;
ll_new();
for (stage = 0; stage < map_total; stage++)
{
sprintf(stage_str, "%d", stage);
ll_add(stage_str);
}
if (!vget(1, 0, "請問要玩第几關? (輸入空格鍵列出所有關號)", stage_str, 4, G
ET_LIST)) {
vmsg("錯誤的關號!");
return -1;
}
stage = atoi(stage_str);
return stage;
}
int
p_pushbox()
{
int c, m, n, i, dx, dy;
if (map_init() == 0)
{
vmsg("載入地圖數據時發重錯誤,請洽談sysop");
return 0;
}
stage = 0;
utmp_mode(M_PUSH);
clear();
vs_bar("推 箱 子");
move(1, 0);
outs("歡迎光臨 \033[1;32m推箱子\033[m 游戲\n\n規則很簡單: 只需把所有的 '□'
都推到 '﹒' 上面去(會變成\033[1;32m綠色\033[m)就過關了。\n\n站長提醒:玩起來難
度可是相當大的,不要輕視喔~\n");
stage = select_stage();
if (stage < 0) return;
start:
clear();
vs_bar("推 箱 子");
move(1, 0);
prints("第 \033[1;32m%d\033[m 關", stage);
start2:
for (n=0; n < MAX_MAP_HEIGHT; n++)
{
for(m=0; m < MAX_MAP_WIDTH; m++)
map_now[n][m] = map_data[stage][n][m];
}
if (!find_y_x(&now_y, &now_x))
{
vmsg("這張地圖似乎不對勁!");
return -1;
}
map_show();
bzero(&my_history, sizeof(my_history));
while (1)
{
c = vkey();
if (my_history.max > MAX_MOVE_TIMES)
{
char buf[256];
sprintf(buf, "您用了 %d 步還沒有成功!Game Over!~", MAX_MOVE_TIMES);
vmsg(buf);
}
dx = dy = 0;
switch (c)
{
case KEY_BACKSPACE :
case KEY_DEL :
if (my_history.max > 0) {
my_history.max--;
i = my_history.max;
map_move(my_history.y1[i], my_history.x1[i], my_history.y0[i], my_h
istory.x0[i]);
find_y_x(&now_y, &now_x);
move2(now_y, now_x);
}
break;
case KEY_UP :
dy = -1;
break;
case KEY_DOWN :
dy = 1;
break;
case KEY_LEFT :
dx = -1;
break;
case KEY_RIGHT :
dx = 1;
break;
case KEY_TAB :
goto start2;
break;
case Ctrl('D') :
case Ctrl('C') :
goto over;
break;
case Ctrl('L') :
map_show();
break;
}
if (dx == 0 && dy == 0) continue;
m = map_now[now_y + dy][now_x + dx];
n = map_now[now_y + dy*2][now_x + dx*2];
if ((m & 4) && (n < 2)) {
map_move(now_y+dy, now_x+dx, now_y+dy*2, now_x+dx*2);
i = my_history.max;
my_history.y0[i] = now_y+dy;
my_history.x0[i] = now_x+dx;
my_history.y1[i] = now_y+dy*2;
my_history.x1[i] = now_x+dx*2;
my_history.max++;
}
else if (m < 2) {
map_move(now_y, now_x, now_y+dy, now_x+dx);
i = my_history.max;
my_history.y0[i] = now_y;
my_history.x0[i] = now_x;
my_history.y1[i] = now_y+dy;
my_history.x1[i] = now_x+dx;
my_history.max++;
}
if (check_if_win()) {
break;
}
find_y_x(&now_y, &now_x);
move2(now_y, now_x);
}
vmsg("祝賀您!成功過關 ... ");
stage++;
goto start;
over:
return;
}
--
※ Origin: 明月水軒 <bbs.hightman.net>
◆ From: 10.12.123.160
Maple 近期熱門文章
PTT數位生活區 即時熱門文章