C#大作业课程设计推箱子小游戏设计(12页).doc
-C#大作业课程设计推箱子小游戏设计-第 12 页可视化程序设计大作业推箱子小游戏班 级:学 号:指导教师:东北大学秦皇岛分校计算机与通信工程学院2018.01一、任务描述:1.题目:推箱子小游戏2.功能描述:(1)箱子只能推动而不能拉动。一次只能推动一个箱子。(2)在一个狭小的仓库中,要求把木箱放到指定的位置,稍不小心就会出现箱子无法移动或者通道被堵住的情况。(3)本游戏的目的就是把所有的箱子都推到目标位置上。(4)通过使用键盘的方向键来控制移动方向。(5)具有重玩本关、跳过本关的功能。二、成员负责部分:独立完成(6分)三、正文1.功能设计:(1).能够显示主菜单和界面:允许玩家对游戏关卡进行设置,增设关卡,把编辑好的关卡进行存储,并能弹出窗体提示当前设计完成的关卡数;(2).能够实现键盘操作功能:使用上、下、左、右方向键控制工人的移动方向,空格键重玩;(3).能够把放置到目的地的箱子进行变色显示;(4).游戏胜负判断功能:当玩家把箱子移动到指定位置时,成功通过当前关卡;(5).可以切换上一关、下一关、增加关卡以及重玩当前关卡;(6).可以判断当前的关卡数,在处于第一关和最后一关时分别不能进行“前一关”和“后一关”操作,并弹出窗体进行提示;2.界面设计:用到的图片及窗体设计3.具体设计:(1).地图编辑器Form2:使用地图编辑器来编辑每一关游戏的界面,就是在窗体上点击生成墙、工人、箱子、通道、目的地,将地图转换为一个一维数组:010101234567. 其中0代表墙,1代表人,2代表箱子,3代表路,4代表目的地,5代表人在目的地,6代表放到目的地的箱子,通过这个数组游戏就可以进行初始化布局了。最后导出一个关卡的配置的plist文件.info,里面存储的即为初始化数组。Form2里面共两个控件。toolStripBtn:进行增加关卡时,选中编辑地图所需要的图片,在编辑地图时直接将要用到的图片拖到窗口内,进行布局;pictureBox:用于编辑地图时,存放布局的样式;(2).游戏窗口Form1:通过依次读取已保存在固定位置的plist文件进行初始化页面信息,生成相应的游戏界面;并定义控制功能,实现用键盘方向键控制工人的移动方向;实现对关卡的切换,如上一关、下一关,能增加关卡以及重玩当前关卡。Form1共两个控件ToolStripMenuItem:游戏菜单中分为四个子菜单,分别为上一关、下一关、重玩、编辑地图和退出上一关:进入上一个关卡下一关:进入下一个关卡重玩:对本关卡初始化,重新开始本关编辑地图:增加关卡退出:退出游戏pictureBox:用于显示地图内容4.运行结果:源代码:Form1:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.IO;namespace 推箱子游戏 public partial class Form1 : Form private int x; /工人当前位置(x,y) private int y; /private bool flag = true; /0代表墙,1代表人,2代表箱子,3代表路,4代表目的地 /5代表人在目的地,6代表放到目的地的箱子 private enum Map_State None=-1,Wall = 0, Worker, Box, Passageway, Destination,WorkerInDest,RedBox ; private Map_State, myArray; /private int, my; private int Order = 1; /游戏关的序号 public Form1() InitializeComponent(); private void ReadMap(int n) string filename = "mapmap_" + n.ToString() + ".info" FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader (fs); /读取数据 for (int i = 0; i < 7; i+) for (int j = 0; j < 7; j+) myArrayi, j=(Map_State) r.ReadByte(); for (int i = 0; i < 7; i+) for (int j = 0; j < 7; j+) if(myArrayi, j =Map_State.Worker) x=i;y=j; r.Close(); fs.Close(); public void initdata() myArray = new Map_State7, 7; ReadMap(Order); private void Form1_Load(object sender, System.EventArgs e) initdata(); drawimage(); /绘制整个游戏区域图形 private void drawimage() Bitmap bit =new Bitmap(this.pictureBox1.Width, this.pictureBox1.Height); Graphics g= Graphics.FromImage(bit); SolidBrush redBrush = new SolidBrush(Color.Red); System.Drawing.Image image=new Bitmap("worker.gif"); for(int i =0;i<7;i+) for(int j=0;j<7;j+) if (myArrayi, j = Map_State.Wall) image = new Bitmap("wall.gif"); g.DrawImage(image,i*50,j*50,50,50); if (myArrayi, j = Map_State.Worker ) image = new Bitmap("worker.gif"); g.DrawImage(image,i*50,j*50,50,50); if (myArrayi, j = Map_State.Box ) image=new Bitmap("box.gif"); g.DrawImage(image,i*50,j*50,50,50); if(myArrayi,j= Map_State.Passageway) image = new Bitmap("passageway.gif"); g.DrawImage(image,i*50,j*50,50,50); if(myArrayi,j= Map_State.Destination) image = new Bitmap("destination.gif"); g.DrawImage(image,i*50,j*50,50,50); if (myArrayi, j = Map_State.WorkerInDest) image = new Bitmap("worker.gif"); g.DrawImage(image, i * 50, j * 50, 50, 50); if (myArrayi, j = Map_State.RedBox) image = new Bitmap("redbox.gif"); g.DrawImage(image, i * 50, j * 50, 50, 50); this.pictureBox1.Image=bit; private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) int x1, y1, x2, y2; /工人当前位置(x,y) switch (e.KeyCode)/分析按键消息 /向上 case Keys.Up: x1 = x; y1 = y - 1; x2 = x; y2 = y - 2; /将所有位置输入以判断并作地图更新 MoveTo(x1, y1, x2, y2); break; /向下 case Keys.Down: x1 = x; y1 = y + 1; x2 = x; y2 = y + 2; MoveTo(x1, y1, x2, y2); break; /向左 case Keys.Left : x1 = x - 1; y1 = y; x2 = x - 2; y2 = y; MoveTo(x1, y1, x2, y2); break; /向右 case Keys.Right: x1 = x + 1; y1 = y; x2 = x + 2; y2 = y; MoveTo(x1, y1, x2, y2); break; case Keys.Space:/空格键 重玩ToolStripMenuItem_Click(null, null); break; private void MoveMan(int x, int y) if (myArrayx, y = Map_State.Worker) myArrayx, y = Map_State.Passageway; else if (myArrayx, y = Map_State.WorkerInDest) myArrayx, y = Map_State.Destination; private void MoveTo(int x1, int y1, int x2, int y2) Map_State P1,P2; P1 = P2 = Map_State.None; if(IsInGameArea(x1, y1) /判断是否在游戏区域 P1=myArrayx1, y1; if (IsInGameArea(x2, y2) P2 = myArrayx2, y2; if (P1 = Map_State.Passageway)/P1处为通道 MoveMan(x,y); x = x1; y = y1; myArrayx1, y1 = Map_State.Worker; if (P1 = Map_State.Destination)/P1处为目的地 MoveMan(x, y); x = x1; y = y1; myArrayx1, y1 = Map_State.WorkerInDest; if (P1 = Map_State.Wall | !IsInGameArea(x1, y1) /P1处为墙或出界 return; if (P1 = Map_State.Box )/P1处为箱子 if (P2 = Map_State.Wall |!IsInGameArea(x1, y1)| P2 = Map_State.Box)/P2处为墙或出界 return; /以下P1处为箱子 /P1处为箱子,P2处为通道 if (P1 = Map_State.Box && P2 = Map_State.Passageway) MoveMan(x, y); x = x1; y = y1; myArrayx2,y2=Map_State.Box; myArrayx1, y1 = Map_State.Worker; if (P1 = Map_State.Box && P2 = Map_State.Destination) MoveMan(x, y); x = x1; y = y1; myArrayx2,y2=Map_State.RedBox; myArrayx1, y1 = Map_State.Worker; /P1处为放到目的地的箱子,P2处为通道 if (P1 = Map_State.RedBox && P2 = Map_State.Passageway) MoveMan(x, y); x = x1; y = y1; myArrayx2, y2 = Map_State.Box; myArrayx1, y1 = Map_State.WorkerInDest; /P1处为放到目的地的箱子,P2处为目的地 if (P1 = Map_State.RedBox && P2 = Map_State.Destination) MoveMan(x, y); x = x1; y = y1; myArrayx2, y2 = Map_State.RedBox; myArrayx1, y1 = Map_State.WorkerInDest; drawimage(); /这里要验证是否过关 if (IsFinish() MessageBox.Show("恭喜你顺利过关","提示"); 下一关ToolStripMenuItem_Click(null, null); return; /判断是否在游戏区域 private bool IsInGameArea(int row, int col) return (row >= 0 && row < 7 && col >= 0 && col < 7); public bool IsFinish()/验证是否过关 bool bFinish = true; for (int i = 0; i < 7; i+) for (int j = 0; j < 7; j+) if (myArrayi,j = Map_State.Destination | myArrayi,j = Map_State.WorkerInDest) bFinish = false; return bFinish; private void 编辑地图ToolStripMenuItem_Click(object sender, EventArgs e) Form2 f2 = new Form2(); f2.ShowDialog(); private void 重玩ToolStripMenuItem_Click(object sender, EventArgs e) this.Text = "第" + Order.ToString() + "关" initdata(); drawimage(); private void 退出ToolStripMenuItem_Click(object sender, EventArgs e) Application.Exit(); private void 下一关ToolStripMenuItem_Click(object sender, EventArgs e) Order+; string filename = "mapmap_" + Order.ToString() + ".info" if (!File.Exists(filename) MessageBox.Show("没有下一关了", "提醒"); Order-; return; this.Text = "第" + Order.ToString() + "关" initdata(); drawimage(); private void 上一关ToolStripMenuItem_Click(object sender, EventArgs e) Order-; string filename = "mapmap_" + Order.ToString() + ".info" if (!File.Exists(filename) MessageBox.Show("没有上一关了", "提醒"); Order+; return; this.Text = "第" + Order.ToString() + "关" initdata(); drawimage(); private void pictureBox1_Click(object sender, EventArgs e) private void 游戏ToolStripMenuItem_Click(object sender, EventArgs e)Form2:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.IO;namespace 推箱子游戏 public partial class Form2 : Form private enum Map_State None=-1,Wall = 0, Worker, Box, Passageway, Destination,WorkerInDest,RedBox ; private Map_State m_now_Select;/当前选中的图标工具 private Map_State, myArray=new Map_State7,7 ; private int BlockSize = 50; public Form2() InitializeComponent(); private void Form2_Load(object sender, EventArgs e) ClearMap(); private void toolStripBtn_Wall_Click(object sender, EventArgs e) /选中墙 m_now_Select = Map_State.Wall; private void toolStripBtn_Box_Click(object sender, EventArgs e) /选中箱子 m_now_Select = Map_State.Box; private void toolStripBtn_Destination_Click(object sender, EventArgs e) /选中目的地 m_now_Select = Map_State.Destination; private void toolStripBtn_Passageway_Click(object sender, EventArgs e) /选中通道 m_now_Select = Map_State.Passageway; private void toolStripBtn_Worker_Click(object sender, EventArgs e) /选中人 m_now_Select = Map_State.Worker; private void toolStripBtn_New_Click(object sender, EventArgs e) ClearMap(); private void toolStripBtn_Save_Click(object sender, EventArgs e) SaveMap(); private void ClearMap() m_now_Select = Map_State.None; /当前未选中图标工具 for (int i = 0; i < 7; i+) for (int j = 0; j < 7; j+) myArrayi, j = Map_State.None ; pictureBox1.Width = 7 * BlockSize+2; pictureBox1.Height = 7 * BlockSize+2; drawimage(); private void SaveMap() if (!Directory.Exists("map")/map文件夹是否存在 Directory.CreateDirectory("map"); string files = Directory.GetFiles("map"); int n=files.Length+1; string filename = "mapmap_"+n.ToString()+".info" FileStream fs = new FileStream(filename, FileMode.OpenOrCreate); BinaryWriter w = new BinaryWriter(fs); for (int i = 0; i < 7; i+) for (int j = 0; j < 7; j+) w.Write(byte)myArrayi, j); w.Close(); fs.Close(); MessageBox.Show ("你设计的是" + n.ToString() + "关"); private void pictureBox1_MouseDown(object sender, MouseEventArgs e) int x, y; x = e.X / 50; y = e.Y / 50; myArrayx, y = m_now_Select;/修改地图 drawimage(); /绘制整个游戏区域图形 private void drawimage() Bitmap bit = new Bitmap(this.pictureBox1.Width, this.pictureBox1.Height); Graphics g = Graphics.FromImage(bit); SolidBrush redBrush = new SolidBrush(Color.Red); System.Drawing.Image image; for (int i = 0; i < 7; i+) for (int j = 0; j < 7; j+) if (myArrayi, j = Map_State.Wall) image = new Bitmap("wall.gif"); g.DrawImage(image, i * 50, j * 50, 50, 50); if (myArrayi, j = Map_State.Worker) image = new Bitmap("worker.gif"); g.DrawImage(image, i * 50, j * 50, 50, 50); if (myArrayi, j = Map_State.Box) image = new Bitmap("box.gif"); g.DrawImage(image, i * 50, j * 50, 50, 50); if (myArrayi, j = Map_State.Passageway) image = new Bitmap("passageway.gif"); g.DrawImage(image, i * 50, j * 50, 50, 50); if (myArrayi, j = Map_State.Destination) image = new Bitmap("destination.gif"); g.DrawImage(image, i * 50, j * 50, 50, 50); this.pictureBox1.Image = bit;四、心得在本次程序设计中,主要使用了picturebox控件和toolstripbtn,游戏中的关卡设计均使用toobstripbtn在picturebox里添加图片来实现。为实现对关卡的存储,在设计关卡时将图像存储为一维数组,导出plist文件,在游戏中读取plist文件,将一维数组重新转化为图像。由于没有考虑到使用“上一关”和“下一关”功能时,分别处于第一关和最后一关的情况,导致了程序出错,后来增加了当跳转的关卡不存在时,则回到当前关卡并提示“没有上一关了”或“没有下一关了”。一直以来,我都想要自己做一个小游戏,奈何能力有限,不知如何进行。尤其是在学习C语言的时候,感觉编程很抽象,运行达到的效果与自己的目标相差甚远。当接触到C#的时候,可以设计、操作窗体,让编程突然变得很具体,更加方便、容易理解。于是我就大胆地尝试去做一个简单的推箱子小游戏,虽然界面的画风有些奇特,但终归是完成了一个小小的心愿。我开始的时间较早,当下发必须三人结组的通知时,我的设计已经完成了。考虑到设计的难度并不大,不适合三个人做,再更换题目又有些不甘心,于是就一个人独立完成了。虽然没有达到老师想要的团队合作的效果,有点小遗憾,但我在这个完成的过程中学会了很多东西。通过这次的程序设计,增强了我对C#语言的运用能力,能够使用VS设计出一个简单的小程序。