1、游戏名: 气象小镇
2、游戏简介:
这是一款介绍气象科普知识的rpg游戏!
游戏中,主角扮演一个小镇的代理镇长,通过与小镇居民对话,从而获知气象灾害对小镇居民造成的困扰,进而帮助小镇居民解决问题。游戏中,时间分为
春、夏、秋、冬四个季节。每个季节都有对应的气象灾害发生,列如春天的暴雨、
大雾。夏天的地震、干旱、森林火灾。秋天的寒露风。冬天的寒潮、雪灾。这些气象灾害都出现在游戏中,游戏分为7个关卡,每个关卡对应一个气象灾害,解决了某个时期的气象灾害,自然进入下个时期的自然灾害!
游戏地图中还有很多名为“气象研究者”的npc,与其对话,“气象研究者”会问你关于气象知识的问题,帮助你获取气象灾害有关的知识!
本游戏历时4个月,由作者单独完成!
3、游戏制作软件:RPG Maker XP
4、游戏中所用的脚本:游戏中所运用到的脚本大多数是软件自带的脚本!
自己编写的脚本如下:
def command_127
value = operate_value(@parameters[1], @parameters[2], @parameters[3])
$game_party.gain_weapon(@parameters[0], value)
if $game_switches[$不显示武器窗口]==false
carol3_66RPG_item = $data_weapons[@parameters[0]]
carol3_66RPG = Window_Base.new((640-300)/2,128,300,100)
carol3_66RPG.contents = Bitmap.new(carol3_66RPG.width - 32, carol3_66RPG.height - 32) if value >= 0
carol3_66RPG.contents.draw_text(0,0,240,32,"获得武器:")
#——声效,可以自己改
Audio.se_play("Audio/SE/"+"006-System06",80,100)
else
carol3_66RPG.contents.draw_text(0,0,240,32,"失去武器:")
#——声效,可以自己改
Audio.se_play("Audio/SE/"+"005-System05",80,100)
end
carol3_66RPG_bitmap = RPG::Cache.icon(carol3_66RPG_item.icon_name)
carol3_66RPG.contents.blt(0, 32, carol3_66RPG_bitmap, Rect.new(0, 0, 24, 24), 255) carol3_66RPG.contents.draw_text(0 + 28, 32, 212, 32, carol3_66RPG_item.name, 0) carol3_66RPG.contents.draw_text(0, 32, 268, 32, "×"+value.abs.to_s, 2)
carol3_66RPG.opacity = 160
for i in 0..30
Graphics.update
end
for i in 0..10
carol3_66RPG.opacity -= 30
carol3_66RPG.contents_opacity -= 30
Graphics.update
end
carol3_66RPG.dispose
end
return true
end
解析:本脚本用RUBY语言编写的。本游戏自己用到的脚本就这一个!RPG Maker XP这软件如果对事件“玩”的炉火纯青,完全不必用到脚本。(RPG Maker XP这软件可以少用甚至不用脚本也能编写出好游戏!)
5、游戏中的开场素材是由作者用Photo shop这软件编辑的!
图标素材是由相机拍的实物图,然后由Photo shop进行后期的边框处理而完成的。
游戏切换画面的过场图片是由作者用Photo shop在图片上加上文字,进行后期处理而来。
6、游戏事件的编辑: 本游戏最主要的是游戏的事件编辑,大量的事件编辑必须遵行一定的逻辑顺序。列如编写一个简单的“采蘑菇”的小游戏:
首先:点击地形,设置事件,“角色图片”中选择蘑菇的4*4图片,“事件开始条件”中选择“与主角接触”、“移动规则”选择“固定”,点击空白处,选择“独立开关A打开”,点击“新建事件页”创建一个新的事件页,在新建的事件页中有“事件出现条件栏”选择“独立开关A为ON”,”角色图片“中选择蘑菇被摘后根茎的图片”,点击空白处,选择“更改文章选项”修改为“显示位置 中 窗口显示 显示”,选择“显示文章”输入:\c[3]获得小蘑菇\c[0].
这样,一个简单的采蘑菇事件就设置好了!
本游戏是由上千个这种小事件一个个按照一定逻辑循序串联在一起的。
第二篇:《猜图游戏》解题报告
作者声明:
此题所附程序,深搜是正确的,会输出所有解。简单推理程序有误。
《猜图游戏》解题报告
By sx349
【摘要】
核心算法思想:深搜/数学推理
主要数据结构:
其他辅助知识:
时间复杂度:O(2)(深搜,显然在强剪枝下常数极小)
/O(2N)(推理,常数也很小)
空间复杂度:O(2NN)(常数极小)
【题目大意】
给定一系列规则和一系列数据,根据规则通过简单推理还原图像。
(“简单推理”的定义为,仅考虑某一行(列)的信息以及该行(列)中已知的方块的颜色,推理出该行(列)中更多方块的颜色。)
【算法分析】
尽管一开始就看到了简单推理这句话,但是一开始并没有想到有效利用这一条件的方法,于是先考虑到用深搜的做法,配合强剪枝来解决。
显然,深搜也有好几种做法,可以先搜索行,也可以先搜索列:(以搜索行为例) 假设我们搜索到第I行:
对每一列维护一个表,搜索到第I行的第J个格子,将这一个各自的状态加入这个表,并且对这个列的表与这个列的状态进行比对。这是一个很普遍的剪枝,显然,这个剪枝的关键在于如何维护这个表。
因为这个表中有三种状态:填0(代表白格),填1(代表黑格),以及填-1(代表未确定)。在一开始考虑的时候,我先把所有已经确定的行和列都填好,因此就必须把-1和0区别开来,但是为了接替方便,最后还是将这些已经确定的行作为搜索时的小剪枝,而避免了-1和0的区分,因此,表的状态就只要用一个布尔数组来判断一下就行了。
但是布尔数组每次的判断还是要O(N)的复杂度,在深搜的过程中如果每一步都判断,那么就必然会超时。因此需要有更好的方法维护这个表。
显然,每一列所要求的数字排列是有序的,那么,对于每一列我们都可以用两个数字M,N来表示当前该列的状态,即已经判断了该列的前M个数,并且第M+1个数已经检查了N格(显然N是小于第M+1个数的)。如果当前我们判断这一格是白格,那么判断之前的状态中N是否等于第M+1个数,如果等于,则M加上1,N归零,否则如果小于,则显然不可行,回溯;如果当前我们判断这一个是黑格,那么判断之前的状态中N+1是否超过第M+1个数,如果超过,那么不可行,如果不超过,那么N加上1;当判断完整张表之后,相当于N2
在整张表之下全部添加一列白格,在对每一列进行判断。这样每次的判断复杂度就只有O(1)了。
那么如何来搜索某一行的状态呢?
我们用J,K两个数来表示我们搜索到这一行中的第J-1个空当,且这个空当的长为K。当然,在这里也可以搜索黑格,但是搜索空当的优势在于我们可以在每一行之前和之后都添加一个白格,这样就可以确定空当的开始和结束,而黑格就无法这样做了。搜索空当之后,将空当中的每一个白格都进行一次判断,然后对这个空档之后的一段黑格再逐个进行判断。但是我们又面临了这样一个问题:如何在退出当前层回溯时恢复数据呢?因为层数过深(理论最高900层),所以无论是值参还是局部变量都会成为累赘(毕竟系统栈不深)。因此,我又另开了一个数组,来记录每一步的推理结果。
至此,深搜的算法已经大体完成,基本上20*20的数据可以秒杀并且输出所有解,暂时因为没有30*30的数据来进行极限测试,但是由于题述中说是保证唯一解,因此应该能够在时限内得到这一组解。
经过与张若愚的讨论和借鉴,我又重新开始研究了简单推理的办法。(还是以行为例) 显然,正如我上面所提到过的,有些行和列是可以直接确定下来的。那么,这些行和列已经确定的格子就相当于我们的初始数据。建立一个队列,将这些已经确定的格子加入这个队列,然后进行如下的操作。
首先是预处理,对于每一行(或列),我们可以算出所有它可能有的排列。假设我们已经根据第I行的数字,得到了第I行的所有排列,将它们列成一张表。
从队列中取出某个确定的格子,将它所在的行(或列,取决于这个格子之前是由行的分析判定还是由列的分析判定的),这样,除了我们已经确定的几个格子之外,有可能在所有的排列中,某一格始终为白格(或黑格),那么马上就可以判定这一格是白格,然后将这一判断入队,重复这一过程。
显然,这完全符合上述“简单推理”的定义:仅考虑某一行(列)的信息以及该行(列)中已知的方块的颜色,推理出该行(列)中更多方块的颜色。而且,如果是做为手工笔算小数据的方法,显然是很好的(尤其是这种描述很符合思维习惯)。但是,如何在电脑上实现这一过程呢?
我们再次建表,不过,这一次不是建一张,而是对每一行都建两张表,其中横里是这一行的每一个格子位置,竖里是这一行的每一种排列方式。对于横里和竖里的开头都建一个Head。 其中,前一张表中的每一个结点(除了Head之外),都是判断中的当前行的可能排列中黑格的位置,后一张表则为白格的位置。这样,我们就可以很轻松的判断某一个是否在所有排列中保持同样的性质了:如果黑格表中某一列的Head直接指向NIL,则这一列必然都是代表白格,反之,白格表中同样的情况下,这一列必然都是代表黑格。而删除的时候,也只用从确定列的Head开始,每往下走到一个就删除一个。
在做这两张表的时候,要注意其同步性,在删除时要同步删除,否则可能会导致两边出现误差的情况。而且从上述的描述中也可开出来,这张表的建法应该是双向十字链表,不仅能够节约空间,而且删除操作也极为方便(尽管编程复杂度可能较高,但是放弃链表而采用数组模拟链表会导致内存直接爆掉,因为总的内存开到最大基本上无法预估)。
【心得体会】
这道题是我最先开始研究的一道题,也许是因为我曾经玩过这个游戏的缘故吧。张若愚神牛给了我莫大的帮助,包括测试数据(在一开始我的程序还跑不出正确答案的时候)以及帮助我解决了推理的做法,当然也包括顺便地把我手机中与此相同的一款游戏打通全关(但是还
是没有30*30的数据,而且很多都是多解)。这道题也应该是我有史以来编的最长的程序了,但是这其中经过了很漫长的调试,才最终得到了不错的结果。相信有了这一次的经验和起步,对我未来编写这种复杂程序将会有更大的帮助吧。
【附录】
【题目描述】
有一个游戏是这样的。有一幅由黑白小方块组成的矩形图画。已知该图画的每一行(列)中连续出现的黑色方块的数目,要求你根据这些信息推理出该图画中的每一个小方块的颜色。例如在以下的图的例子中,第一行的数字是2 1 1,表示在第一行中连续出现的黑色方块有三组,从左到右依此是两个、一个、一个黑色方块。
可以保证的是在符合这些条件的情况下,答案的图画是唯一确定的。这里,为了对问题作一些简化,有另一个条件,就是结果的图画一定可以从零开始通过若干次的“简单推理”的步骤来得到。“简单推理”的定义为,仅考虑某一行(列)的信息以及该行(列)中已知的方块的颜色,推理出该行(列)中更多方块的颜色。
下面是两个简单推理的例子。(图中白色方块表示未知的方块,中间有点的方块以及全黑的方块分别表示推理出一定是白色或黑色的方块)。
例1:从
可以推理出
例2:从
可以推理出
【输入】
输入数据的第一行包含两个整数X Y,分别是图画的行数和列数(1 ≤ X, Y ≤ 30)。 接下来的X行分别描述了从上到下每一行中的黑方块的信息。每一行的格式为Si Xi,1 Xi,2 ... Xi,Si。其中Si为第i行中连续的黑方块的组数。Xi,1 Xi,2 ... Xi,Si分别为每一组中黑方块的数目。再接下来的Y行分别描述了从左到右每一列中的黑方块的信息。每一行的格式为Ti Yi,1 Yi,2 ... Yi,Ti。其中Ti为第i列中连续的黑方块的组数。Yi,1 Yi,2 ... Yi,Ti分别为每一组中黑方块的数目。
【输出】
输出推理出的图画。即,输出X行,每行输出2Y列。其中,用连续的两个#号表示黑方块,用连续的两个点表示白方块。
【样例输入输出】
【源程序清单】
深搜:
{$m 1000000}
const maxn=31;
maxm=31;
type point=^node;
node=record
ch:array[0..1]of point;
f:point;
end;
var a,b,b1:array[0..maxn]of point; c,d,s:array[0..maxm]of longint; f:array[0..maxm]of boolean;
t,u:array[0..maxm,0..maxn]of longint; ans:array[0..maxn,0..maxm]of boolean; n,m:longint;
tt:longint;
procedure build(flag,t,k,res:longint); var i,j,u:longint;
p,q:point;
begin
if t=c[0]+1 then
begin
fillchar(f,sizeof(f),0);
for i:=1 to c[0] do
for j:=d[i] to d[i]+c[i]-1 do f[j]:=true;
p:=a[flag];
for i:=1 to m do
begin
u:=ord(f[i]);
if p^.ch[u]=nil then
begin
new(q);
q^.ch[0]:=nil;
q^.ch[1]:=nil;
q^.f:=p;
p^.ch[u]:=q;
end;
p:=p^.ch[u];
end;
exit;
end;
for i:=k to m-res+2 do
begin
d[t]:=i;
build(flag,t+1,i+c[t]+1,res-c[t]-1); end;
end;
procedure init;
var i,j,k,l:longint;
begin
readln(n,m);
for i:=1 to m do
begin
new(a[i]);
a[i]^.ch[0]:=nil;
a[i]^.ch[1]:=nil;
end;
for i:=1 to n do
begin
read(c[0]);
l:=0;
for j:=1 to c[0] do
begin
read(c[j]);
inc(l,c[j]+1);
end;
build(i,1,1,l);
end;
for i:=1 to m do
begin
read(t[i,0]);
for j:=1 to t[i,0] do
begin
read(t[i,j]);
inc(s[i],t[i,j]+1);
end;
end;
end;
procedure print;
var i,j:longint;
begin
inc(tt);
writeln('No.',tt,':');
fillchar(ans,sizeof(ans),0); for i:=1 to n do
b1[i]:=b[i];
for i:=m downto 1 do
for j:=1 to n do
begin
ans[j,i]:=b[j]=b[j]^.f^.ch[1]; b[j]:=b[j]^.f;
end;
for i:=1 to n do
begin
for j:=1 to m do
if ans[i,j] then
write('#')
else
write('.');
writeln;
end;
writeln;
for i:=1 to n do
b[i]:=b1[i];
end;
procedure search(flag,x,k,res:longint); var i,j:longint;
able:boolean;
begin
if flag=m+1 then
begin
print;
exit;
// close(input); close(output); // halt;
end;
if x=t[flag,0]+1 then
begin
fillchar(f,sizeof(f),0);
for i:=1 to t[flag,0] do
for j:=u[flag,i] to u[flag,i]+t[flag,i]-1 do f[j]:=true;
able:=true;
for i:=1 to n do
begin
if b[i]^.ch[ord(f[i])]=nil then
begin
able:=false;
break;
end;
b[i]:=b[i]^.ch[ord(f[i])];
end;
if not able then
for i:=1 to i-1 do
b[i]:=b[i]^.f
else
begin
search(flag+1,1,1,s[flag+1]);
for i:=1 to n do
b[i]:=b[i]^.f;
end;
exit;
end;
for i:=k to n-res+2 do
begin
u[flag,x]:=i;
search(flag,x+1,i+t[flag,x]+1,res-t[flag,x]-1); end;
end;
procedure work;
var i:longint;
begin
for i:=1 to n do
b[i]:=a[i];
search(1,1,1,s[1]);
end;
begin
//assign(input,'1.txt'); reset(input);
//assign(output,'2.txt'); rewrite(output); init;
work;
close(input);
close(output);
end.
推理:
const maxstate=10001;
type node=record
l,r,u,d:longint;
end;
point=record
x,y,f:longint;
end;
state=array[0..maxstate,0..31]of node;
var a:array[0..1,0..31,0..1]of state; b,c:array[0..31]of longint;
q:array[0..901]of point;
f:array[0..31,0..31]of boolean; t:array[0..31]of boolean;
n,m,tt:longint;
l,r:longint;
map:array[0..30,0..30]of longint; max:longint;
procedure add0(var s:state);
var i,k,l:longint;
begin
inc(s[0,0].d);
k:=s[0,0].d;
if k>max then max:=k;
l:=0;
for i:=1 to tt do
if t[i] then
begin
s[k,i].l:=l;
s[k,l].r:=i;
l:=i;
s[s[maxstate,i].d,i].d:=k; s[k,i].u:=s[maxstate,i].d; s[maxstate,i].d:=k;
end;
end;
procedure add1(var s:state);
var i,k,l:longint;
begin
inc(s[0,0].d);
k:=s[0,0].d;
if k>max then max:=k;
l:=0;
for i:=1 to tt do
if not t[i] then
begin
s[k,i].l:=l;
s[k,l].r:=i;
l:=i;
s[s[maxstate,i].d,i].d:=k;
s[k,i].u:=s[maxstate,i].d;
s[maxstate,i].d:=k;
end;
end;
procedure build(flag,row,now,start,rest:longint); var i,j,k,l:longint;
begin
if now=c[0]+1 then
begin
fillchar(t,sizeof(t),0);
for i:=1 to c[0] do
for j:=b[i] to b[i]+c[i]-1 do
t[j]:=true;
if (b[1]=4)and(b[2]=7)and(b[3]=9) then begin
flag:=flag;
end;
add0(a[flag,row,0]);
add1(a[flag,row,1]);
exit;
end;
for i:=start to rest do
begin
b[now]:=i;
build(flag,row,now+1,i+c[now]+1,rest+c[now]+1); end;
end;
procedure init;
var i,j,t:longint;
begin
readln(n,m);
tt:=m;
for i:=1 to n do
begin
t:=0;
read(c[0]);
for j:=1 to c[0] do
begin
read(c[j]);
inc(t,c[j]+1);
end;
build(0,i,1,1,m-t+2);
end;
tt:=n;
for i:=1 to m do
begin
t:=0;
read(c[0]);
for j:=1 to c[0] do
begin
read(c[j]);
inc(t,c[j]+1);
end;
build(1,i,1,1,n-t+2);
end;
readln;
end;
procedure addpoint(x,y,flag:longint);
begin
if f[x,y] then exit;
inc(r);
q[r].x:=x;
q[r].y:=y;
q[r].f:=flag;
f[x,y]:=true;
end;
procedure disposeline(var s:state; t,x,flag,mark:longint); var i:longint;
begin
i:=s[t,0].r;
while i<>0 do
begin
s[s[t,i].u,i].d:=s[t,i].d;
s[s[t,i].d,i].u:=s[t,i].u;
if s[0,i].d=0 then
if mark=0 then
addpoint(x,i,flag)
else
addpoint(i,x,flag);
i:=s[t,i].r;
end;
end;
procedure deletestate(var s:state; t,x,flag,mark:longint); var i:longint;
begin
i:=s[0,t].d;
while i<>0 do
begin
disposeline(a[mark,x,flag],i,x,1-flag,mark); disposeline(a[mark,x,1-flag],i,x,flag,mark); i:=s[i,t].d;
end;
end;
procedure work;
var i,j:longint;
begin
l:=1; r:=0;
for i:=1 to n do
for j:=1 to m do
begin
if a[0,i,0][0,j].d=0 then addpoint(i,j,1); if a[0,i,1][0,j].d=0 then addpoint(i,j,0); if a[1,j,0][0,i].d=0 then addpoint(i,j,1); if a[1,j,1][0,i].d=0 then addpoint(i,j,0); end;
while l<=r do
begin
map[q[l].x,q[l].y]:=q[l].f;
deletestate(a[0,q[l].x,1-q[l].f],q[l].y,q[l].x,1-q[l].f,0); deletestate(a[1,q[l].y,1-q[l].f],q[l].x,q[l].y,1-q[l].f,1);
inc(l);
end;
end;
procedure print;
var i,j:longint;
begin
for i:=1 to n do
begin
for j:=1 to m do
if map[i,j]=1 then
write('..')
else
write('##');
writeln;
end;
end;
begin
//assign(input,'1.txt'); reset(input); //assign(output,'3.txt'); rewrite(output); init;
work;
print;
writeln(max);
close(output);
end.