用C#用c 编写推箱子子游戏,需要用到哪些算法

C#入门学习推箱子游戏WPF技术实现
欢迎大家提出意见,一起讨论!
转载请标明是引用于 http://blog.csdn.net/chenyujing1234
需要源码请与我联系。
&编译平台:VS2008 + .Net Framework 3.5
&&&&&&& 语言: C#
使用工具:Expression Design 4
&&&&&&&&&&&&&&&&&&& Expression Blend& (它们的获得请参考我的另一文章
http://write.blog.csdn.net/postedit/7659256)
3、实现游戏用户界面
尽管程序员可以使用VS编写XAML代码的方式来构造用户界面,但是对于有设计爱好的用户来说,使用类似Photoshop一样的Expression套件能将
软件美工最大化。对于怪物与目标块的图形显示,示例使用了Expression Design来设计图形,然后将其导入到Expression Blend中进行布局处理。
3、1 使用Expression Design设计图案
Expression Design 是一个专业的图表和图形设计工具。该工具提供了矢量图形的绘制能力,强大之处可以像PhotoShop一样设计好用户界面或是所需要量的图形,
使用其导出功能导出为XAML资源或代码。Expression Design主界面如下:
Design&通常是与Blend紧密相关的。美工人员使用Design强大的设计功能来设计界面元素,导出给Blend进行编辑。最后通过VS设计程序代码。
在示例中,使用Design设计了一个Cell图案,在其中添加了多个图层,每一层放置各自不同的图案,比如箱子、怪物、墙体。
然后使用Design的导出功能将这些图案导出为资源字典,以便于程序引用这些图形。导出窗口如下:
然后在App.xaml中的资源字典的定义中使用&ResourceDictionary.MergedDictionaries&指定Cell.xaml作为整个应用程序级别的资源。
3、2 实现用户主界面
在开始布局游戏区域前,主界面上需要一个Banner来显示游戏名称,为游戏主界面添加背景图片以增加界面的效果。
游戏创建了两个用户控件来实现这样的特效,位于游戏项目的Controls文件夹下。
BackgroundControl.xaml用户控件实现非常简单,通过使用Expression Design来设计背景图片,然后导出为独立的Xaml文件。&
导出设置如下:
图形将被置于一个Canvas画布中,在MainWindow.xaml中通过引用这个控件来设置背景色。
Banner.xmal的实现与BackgroundControl.xaml的实现类似。
主界面的布局非常简单,主要分为四行:
(1) 第一行
主要放了一个Border、一个Rectangle、一个Viewbox(里面放Banner)
(2) 第二行
在一个Grid中加入一个Rectangle、显示关卡代码、关数、按钮
(3) 第三行
&&&&&&&&&& 只是一个间隔,没放东西
(4)& 第四行
如上,位于Viewbox的Grid, x:Name为grid_Game在游戏启动时动态创建行和列定义,并在行列中放置多个Button按钮来实现游戏的方块。
在MainWindow.xaml的声明中,为窗口关联了Loaded事件,当该事件触发时,将执行Window_Load代码。这段代码在游戏窗口打开时,开始游戏第一关。
Window_Loaded将调用在资源中实例化的Game类,在Window.Resource资源区,首先定义了Game类,代码如下:
&!-- 用于整个游戏的Game实例. --&
&Sokoban:Game x:Key=&sokobanGame&/&
在MainWindow.xaml.cs中相应地定义了一个Game属性,该属性使用在资源中指定的x:Key键值查找Game对象实例。Game属性的声明如下:
/// &summary&
/// 获取定义在Window资源中的Game对象的实例
/// &/summary&
/// &value&游戏实例.&/value&
return (Game)TryFindResource(&sokobanGame&);
Game属性的get获取器使用TryFindResource() 方法,传入指定的查找对象实例,并转换为Game对象。因为TryFindResource()方法返回object类型的实例。
搜索具有指定键的资源,如果找到,则返回该资源。
resourceKey:
要查找的资源的键标识符。
// 返回结果:
找到的资源;如果未找到具有所提供 key 的资源,则为 null。
public object TryFindResource(object resourceKey);
3、3& 程序启动时加载关卡
Window_Loaded&将使用Game对象加载游戏关卡,并初始化用户界面。
void Window_Loaded(object sender, RoutedEventArgs e)
//当Game的Level属性发生变更时,会触发PropertyChanged事件
Game.PropertyChanged += game_PropertyC
/* 加载并开始第一级游戏,Level属性变更,
* 触发Game.PropertyChanged */
Game.Start();
catch (Exception ex)
//异常处理消息。
MessageBox.Show(&加载游戏出现异常. & + ex.Message);
Game.Start将开始游戏的每一关,Start() 方法调用的LoadLevel()方法内部触发了Game.PropertyChanged事件。
只要游戏的状态发生变化,game_PropertyChanged事件处理代码便会执行,该事件中的代码将开始游戏界面的更新工作。
/// &summary&
/// 通过加载第一关来开始游戏
/// &/summary&
public void Start()
if (sokobanService != null)
//获取关卡数
LevelCount = sokobanService.LevelC
{ //得到关卡总数,通过获取关卡文件的个数来得到
string[] files = Directory.GetFiles(levelDirectory, &*.skbn&);
LevelCount = files.L
LoadLevel(0);//加载关卡
void game_PropertyChanged(object sender,
ponentModel.PropertyChangedEventArgs e)
//判断传入的属性名称
switch (e.PropertyName)
case &GameState&://如果为GameState变更
UpdateGameDisplay();//更新游戏的界面显示
在以上代码中,判断PropertyName是否为GameState,如果为GameState属性发生变更,则调用UpdateGameDisplay来更新游戏界面的显示。
&3、4&&更新游戏界面的显示
&UpdateGameDisplay方法将根据游戏的状态显示不同的信息,使玩家理解游戏当前所在的状态。
如果游戏处于开始运行状态,将调用Initialiselevel() 方法来初始化游戏的关卡。UpdateGameDisplay的实现如下:
/// &summary&
/// 设置游戏进度状态显示,
/// &/summary&
void UpdateGameDisplay()
switch (Game.GameState)
case GameState.Loading://如果游戏处于加载中
FeedbackControl1.Message = //在界面上显示响应消息
new FeedbackMessage { Message = &正在加载...& };
ContinuePromptVisible =
case GameState.GameOver://如果游戏结束状态
FeedbackControl1.Message =//显示结束信息
new FeedbackMessage { Message = &游戏结束& };
ContinuePromptVisible =
case GameState.Running: //如果游戏处于开始运行状态
ContinuePromptVisible =
FeedbackControl1.Message = new FeedbackMessage();
InitialiseLevel();//初始化游戏关卡界面
case GameState.LevelCompleted:
//如果玩家玩过关
FeedbackControl1.Message =
//显示玩过关的消息
new FeedbackMessage { Message = &恭喜您,成功过关!& };
MediaElement_LevelComplete.Position = TimeSpan.MinV
MediaElement_LevelComplete.Play();//播放声音
ContinuePromptVisible =
case GameState.GameCompleted://如果玩完了所有的关卡
FeedbackControl1.Message = new FeedbackMessage //显示最终信息
{ Message = &干得好. \n游戏完成! \n请在Codeproejct联系游戏作者& };
MediaElement_GameComplete.Position = TimeSpan.MinV
MediaElement_GameComplete.Play();//播放完成音乐
UpdateGameDisplay()方法通过判断Game类中定义的GameState来向UI界面显示游戏状态消息。
FeedbackControl1是一个自定义的用于游戏界面显示消息的用户控件,该控件主要用于在用户控件上显示一些消息。
&Controls:FeedbackControl Grid.Row=&3& x:Name=&FeedbackControl1& Margin=&10,10,10,10& Click=&FeedbackControl1_Click&/&
UpdateGameDisplay初始化关卡界面是在Running状态,即游戏开始运行后,开始初始化关卡,
这是通过 InitialiseLevel();初始化游戏关卡界面。
InitialiseLevel();方法将初始化学Grid的行列定义,并在行列中放置Button控件作为方块的容器。
由于在调用InitialiseLevel();前,LoadLevel()方法已经加载了关卡数据到Level类中,因此可以将Cell对象与指定的Button控件相关联。
/// &summary&
/// 使用游戏级别初始化Grid
/// &/summary&
void InitialiseLevel()
commandManager.Clear();//清除命令集合
//清除Grid子元素集合,以及行列定义集合
grid_Game.Children.Clear();
grid_Game.RowDefinitions.Clear();
grid_Game.ColumnDefinitions.Clear();
//根据关卡中的行数向Grid中添加行定义
for (int i = 0; i & Game.Level.RowC i++)
grid_Game.RowDefinitions.Add(new RowDefinition());
//根据关卡中的列数向Grid中添加列定义
for (int i = 0; i & Game.Level.ColumnC i++)
grid_Game.ColumnDefinitions.Add(new ColumnDefinition());
for (int row = 0; row & Game.Level.RowC row++)
//循环遍历行
for (int column = 0; column & Game.Level.ColumnC column++)
//循环遍历列
Cell cell = Game.Level[row, column];//得到行列中的Cell对象
cell.PropertyChanged += cell_PropertyC//关联属性变更事件
Button button = new Button();//实例化Button控件
button.Focusable = //该控件不允许获取焦点
//将Button的DataContext指定为cell对象,以便在XAML中控制
button.DataContext =
button.Padding = new Thickness(0, 0, 0, 0);//按钮无边框
button.Style = (Style)Resources[&Cell&];//指定按钮样式
button.Click += Cell_C//关联按钮单击事件
//通过附加属性设置按锯位于Grid的行和列
Grid.SetColumn(button, column);
Grid.SetRow(button, row);
grid_Game.Children.Add(button);//将按钮添加到Grid控件列表中
textBox_LevelCode.Text = Game.LevelC//显示关卡号
label_LevelNumber.Content =
//显示当前关卡和总关卡信息
Game.Level.LevelNumber + 1 + &/& + Game.LevelC
grid_Main.DataContext = Game.L//设置主界面的DataContext为关卡
mediaElement_Intro.Position = TimeSpan.MinV//播放介绍音乐
mediaElement_Intro.Play(); //播放音乐
grid_Game.Focus();
//游戏区域得到焦点
InitialiseLevel首先清除命令管理器中的命令列表,清除Grid中的行列定义及子内容。
然后根据游戏关卡的行数和列数创建行列定义,循环遍历行列。先获取在Game.Level 实例中加载的cell 对象。以便与稍后将要创建的Button控件相关联。
在获取了Cell并设置了Cell的PropertyChanged事件为cell_PropertyChanged事件处理代码后实例化一个Buttons控件。
该Button控件将作为一个游戏方块,指定其不能得焦点,不能具有边界,并关联其Click单击事件。
最后将该Button添加到Grid中。
cell_PropertyChanged事件主要用于判断当CellContents属性发生变更,将根据方块的内容是一个箱子还是角色来播放不同的音乐。
3、5& 处理方块单击事件
当用户单击某个按钮时,会执行Cell_Click事件处理代码。
该事件处理代码将根据鼠标单击的位置,让怪物转到当前单击的位置点,如果玩家是按下键盘的确Shit键并单击鼠标,将执行PushCommand命令,
否则JumpCommand命令。命令的执行是通过CommandManager这个命令管理器来实现的。Cell_Click事件代码如下:
void Cell_Click(object sender, RoutedEventArgs e)
Button button = (Button)e.S//得到当前单击的Button实例
Cell cell = (Cell)button.DataC//获取DataContext
//要执行的命令变量
if (Keyboard.IsKeyDown(Key.LeftShift) //如果按下左或右Shift
|| Keyboard.IsKeyDown(Key.RightShift))
//实例化一个PushCommand执行推动命令
command = new PushCommand(Game.Level, cell.Location);
else //如果没有按下Shift,则执行跳转命令
//实例化跳转命令
command = new JumpCommand(Game.Level, cell.Location);
}//使用CommandManager命令管理器执行命令
commandManager.Execute(command);
代码首先得到当前单击的Button对象,根据该Button对象获取到与其相关联的cell对象。
然后判断当前是否按下了左或右Shit键。
如理按下了Shit键,则实例化PushCommand命令,否则实例化JumpCommand命令,要求CommandManager命令
管理器来执行相应的推移或跳转操作。
3、6& 使用Command模式发送命令请求
Command模式是为了让命令的请求与命令的执行者进行解耦。CommandManager只对抽象的CommandBase进行执行,而不与实际的
命令代码进行解耦。
在用户界面上,当用户执行命令时,传递实际的命令给CommandManager 执行,实际上这是利用了面向对象的多态技术。
当用户界面按下键盘上的按钮时,一系列具体的命令对象产生,然后交给CommandManager命令管理器进行执行。
在MainWindow.xaml的定义中,响应了主窗体的KeyDown事件,将执行Window_KeyDown事件处理代码。
/// &summary&
/// 处理Window控件的KeyDown事件
/// &/summary&
void Window_KeyDown(object sender, KeyEventArgs e)
CommandBase command =//用于保存命令的变量
Level level = Game.L
//得到当前关卡对象实例
if (Game != null)
//如果己经初始化了Game
//判断当前游戏的状态是否在运行状态
if (Game.GameState == GameState.Running)
switch (e.Key) //获取按键
case Key.Up://如果是向上方向键,则向上移动
command = new MoveCommand(level, Direction.Up);
case Key.Down://如果是向下方向键,则向下移动
command = new MoveCommand(level, Direction.Down);
case Key.Left://如果是向左方向键,则向左移动
command = new MoveCommand(level, Direction.Left);
case Key.Right://如果是向右方向键,则向右移动
command = new MoveCommand(level, Direction.Right);
case Key.Z://如果是Ctrl+Z键
if (Keyboard.Modifiers == ModifierKeys.Control)
//执行Undo操作,将从撤消堆栈中取上一次执行的命令
commandManager.Undo();
case Key.Y://如果是Ctrl+Y键
if (Keyboard.Modifiers == ModifierKeys.Control)
//执行Redo操作,将从命令堆栈中取上一次执行的命令
commandManager.Redo();
switch (Game.GameState) //根据游戏的不同状态判断
case GameState.GameOver://如果游戏结束
Game.Start();
//按任意键重新开始
case GameState.LevelCompleted://如果关卡玩过关
Game.GotoNextLevel();//按任意键开始下一关
if (command != null)//根据己经赋好的命令对象
//使用命令管理器的Execute执行命令
commandManager.Execute(command);
代码中的CommandBase 抽象基类用来保存具体的Command命令,这是利用了多态的原理。
如果游戏全Game 不为null,将根据游戏是否在运行状态获取用户所按下的按钮。
3、7& 使用MultiDataTrigger改变方块外观
尽管使用Grid和Button布好了游戏界面,但是默认情况下,所有的Button都使用Cell外观。
幸好WPF提供了强大的样式触发器,可以根据指定的条件变更其外观。
到目前为止,已经使用了Expression Design创建了用于不同方块的图案及角色形状,并且这些图形都以画刷的形式嵌入到了应用程序的资源中。
那么通过MultiDataTrigger就可以根据特定的Cell名称来应用不同的按钮填充,使得按钮可以显示不同的外观。
对于方块内容样式,比如方块中是否有一个箱子,或是当前角色移动到某个方块的位置,使用MultiDataTrigger多条件触发器定义以下XAML代码:
通过WPF提供的强大的样式触发器,当移动角色或推动箱子是地,UI端会自动变更显示内容,不需要编程实现设置图形的位置。
上面讲到Button的Style是Rectangle,这是在InitialiseLevel()方法中,为每一个单元格创建按钮时,指定了按钮的默认模式为Cell时指定的。
button.Style = (Style)Resources[&Cell&];//指定按钮样式
Cell样式指定了按钮的呈现外观,因为按钮是一个内容控件,可以通过指定其Template来改变按钮的默认呈现。Cell样式如下:
方块显示的Rectangle指定的Style为&CellStyle&,它会根据Button所关联的不同的Cell类型来显示不同的方块样式。如下:
通过这些样式触发器的设置,游戏关卡内容一旦回去,就自动使用各自不同的方块外观来显示整个游戏的布局。
当鼠标或键盘移动时,会根据CellContents的Name属性自动设置移动,实现了游戏的运行显示效果。
> 本站内容系网友提交或本网编辑转载,其目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请及时与本网联系,我们将在第一时间删除内容!
推箱子游戏是老游戏了, 网上有各种各样的版本, 说下推箱子游戏的简单实现,以及我找到的一些参考视频和实例: 推箱子游戏的在线DEMO : 打开 如下是效果图: 这个拖箱子游戏做了移动端的适配, 我使用了zepto的touch模块, 通过手指滑动屏幕就可以控制乌龟走不同的方向: 因为推箱子这个游戏比较简单, 直接用了过程式的方式写代码, 模块也就是两个View ...
用函数做推箱子游戏
推箱子游戏的90个经典关卡 认为智商不低的可以试一下,将各个文件下载到本地,用游戏软件打开即可. screen.1 source screen.2 source screen.3 source screen.4 source screen.5 source screen.6 source screen.7 source screen.8 source sc ...
本游戏为推箱子游戏,即通过移动方向键来控制小人去推动箱子,直到把所有的箱子都推动到各个目标中.游戏需要在人物行走过程中无法穿越墙和箱子,并在有限的范围中放好各箱子,且每次只能搬运一个箱子.所基于的语言是8086汇编,使用的编译环境是唐都的集中开发环境TD-PIT.
本次设计的基本思想是通过将不同的元素(墙.路.箱子.人.目标位)抽象为不同的矩阵,然后将 ...
推箱子游戏在控制台上的实现.8 上 ,5下,6右,4左. 将箱子推到 10*10列地图的就算胜利. X 代表人, 0 代表箱子. #include&stdio.h& int arr[12][12] = {0}; // map void showMap(){ //显示地图 int i,j; for (i = 1;i &= 10;i++){ f ...
这一节是本文的核心内容,即推箱子游戏求解算法的设计思路过程 前面已经说过过,判断局面重复的最好标准不是局面完全一致,而是坐标排序相同且角色坐标通行 如下图,角色无论怎么移动,不推动箱子的时候,都能回到原来的位置,算作同一个局面: 再如下图,两个箱子互换位置,结果与没有移动箱子是一样的,所以排序箱子坐标以后一致,还是相同局面 问:有必要判断局面重复吗?是不是只 ...
用STL实现DFS/BFS算法 ——推箱子游戏(1) 推箱子的游戏想必很多朋友都有玩过,简单地说就是,在一个m*n的范围内有k个箱子和k个目的地,你只能使用推的方法来移动箱子,不能拖,也不能推动两个或以上的箱子,活动范围通常比较狭窄,还有一些不可移动的障碍物,所以有一定难度和可玩性.以下是一个中等难度的推箱子题目:
你可以看到,图的正中央是负责推箱子的“ ...
用STL实现DFS/BFS算法 ——推箱子游戏(2) 前面,我们给出了SokoState的输入输出操作符.接下来,我们来看看isTarget()成员函数.它很简单,我们只要检查一下是否每个箱子都已经被移动到了目的地就行了,即检查一下每个格子的isDest()状态与isBox()状态是否相同(同时为真或同时为假).代码如下: bool SokoState::i ...致福音: 推箱子游戏自动求解算法设计(一) - 综合当前位置:& &&&致福音: 推箱子游戏自动求解算法设计(一)致福音: 推箱子游戏自动求解算法设计(一)&&网友分享于:&&浏览:0次致佳音: 推箱子游戏自动求解算法设计(一)本来酷爱音乐, 老衲也想谱一曲&献给爱丽丝&之类, 通俗又有境界的曲子, 奈何没有那个水平, 也不是一个程序员做的勾当,于是就有了本文.
希望莲花妹妹跟着思路走,能遗忘那些太多的忧伤……
本文分以下四个小节:
一、平面寻路算法(Alpha Star)
二、闭合图形填充算法(扫描线种子填充)
三、推箱子求解
四、执行效率的优化
日本人有个程序叫Sokuban Automatic Solver,文件名是sokoban722.exe我附带在资源里面
不过日本人的东西没有开源,我们也不知道它里面的花花肠子是什么,同时网上我看到也有人写这样的程序,不过我没有参考
只是闭门造车,原创作品献给莲花妹妹吧,刚入门学编程,或者学了编程想进一阶的施主可以观摩一下,高手请转身再笑……
现在就先弄几张图片来作序吧,我不是作家,不知道真正的作序是什么样的,不过我猜看文章的人看不到图片是看不下去的
先是设计箱子图片,找不到好看的箱子素材,就随便找一张差不多的处理一下了:
侧面的水印比较少,我就截取侧面了,而后扭曲调整到正面图效果(PS也有简单的空间图形处理能力的)
调整水印背景亮度,消除水印背景
以32x32为单位创建11列的新图像(为什么是11列,我们在算法部分再说)
缩放到单元大小,调整下亮度对比度,让它看起来更鲜艳一些
然后是边界格子,我懒得搞什么金属质感之类的那么复杂,就随便搞个有点立体感的格子,直接斜面和浮雕完成
还有目标,用一个小圆圈标识,以空白格子为背景,画一个正圆图形,以此路径建立选区
羽化描边,即可得到小圈圈了,我画个小圈圈,不诅咒任何人
然后是箱子归位(箱子和目标重叠)的图形,我直接去色,加深,强化一点点红……
然后是搬运工和搬运工归位,我直接用笑脸和笑到脸红,牙齿东倒西歪的笑脸
限于篇幅,就到资源里看详情吧(不是卖关子,老衲……)
运行效果图
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 1234567891011 Copyright & &&版权所有推箱子游戏设计_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
推箱子游戏设计
上传于||文档简介
&&推​箱​子​游​戏​设​计​,​汇​编​语​言
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩67页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢

我要回帖

更多关于 c语言推箱子游戏 的文章

 

随机推荐