[留念贴] C#开发技术期末大作业——星月之痕
明天就要去上海大学参加 2015赛季 ACM/ICPC 最后一场比赛 —— EC-Final,在这之前,顺利地把期末大作业赶出来了。
纯手工打造。庆幸的是,历时四天,现在基本完工了。
做个作业真不容易,音乐要自己找,图片要自己P,代码也要自己写... ... 早起晚睡,脖子酸... ...
下载地址:http://pan.baidu.com/s/1mhIO1b6
下载之后先解压,然后打开DestroyStars\DestroyStars\bin\Debug文件夹下的DestroyStars.exe
据说会报毒!? 我那么善良的人怎么会制造病毒... .. 如果报毒了,解压之前关闭一下杀毒软件吧...真的没毒的。。。
预览图:
【开发过程】
Day 1.上午 “妈呀..期末快到了耶!C#学了什么?好像什么都不会啊!”.....就这样,我开始了我的期末大作业的开发,上午看了一下老师的课件,随便琢磨了一下就开始了,游戏中的所有星星方块都是一张一张的图片,画图部分就纠结了半天了,但最后还是被我画了出来。
Day 1.下午 先做了随机生成10*10地图,这个似乎so easy.. .. 然后我就是到了算法部分了,也是整个游戏中仅有的我最擅长写的一部分,消灭星星消除的是连通块,本想用广度优先搜索的,但是因为不知道C#中队列的语法,最终还是采用了深度优先搜索。palapala,这部分很快就写完了。之后做的就是方块移动的过程,也不难吧,用timer控制一下,每隔一定的时间刷新一下图片的位置。 第一天结束之后,把最最核心的东西完成了,之后就是外观与游戏玩法的添加。
Day2. 这一天似乎做的事情比较少,找了几张星星、鼠标的图片,然后消除效果的制作。
Day3. 三个技能基本定型,RMB系统基本定型,积分系统基本定型,外观基本定型。
Day4. 闯关模式基本定型,加上了音效与背景音乐,写了一下玩法说明书。
代码不多贴了,下载之后也能看到的。
放一下 Game.CS 的吧.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Media; namespace DestroyStars { public partial class Game : Form { int Add_width = 25; int Add_height = 180; Diamond[] Dia = new Diamond[100*100]; int height = 10;//高 int width=10;//宽 int[,] map = new int[100, 100];//定义地图 int[,] flag = new int[100, 100];//用于深度优先搜索求连通块 int[,] dir = new int[4, 2];//搜索时用到的四个方向 int[] tot = new int[100];//方块掉落时候用的 int[] temp = new int[100];//临时存储 int D;//控制下落 Label[] labels = new Label[100*100]; int T;//控制显示效果 int Tot;//控制显示效果 int GameState;//控制游戏状态 int time_font;//控制下一关字样的显示时间 int Now_toll = 1;//关卡数量 int score = 0;//计分 int RMB = 0; int num_Skill1 = 0; int num_Skill2 = 0; int num_Skill3 = 0; String news; public Game() { InitializeComponent(); } //技能按钮状态更新 void update_skill_button() { if (num_Skill1 > 0) button2.Enabled = true; else button2.Enabled = false; if (num_Skill2 > 0) button1.Enabled = true; else button1.Enabled = false; if (num_Skill3 > 0) button3.Enabled = true; else button3.Enabled = false; if (RMB < 2) button4.Enabled = false; else button4.Enabled = true; if (RMB < 5) button5.Enabled = false; else button5.Enabled = true; if (RMB < 5) button6.Enabled = false; else button6.Enabled = true; } //随机生成地图 void Rand() { Random myRand = new Random(DateTime.Now.Second); for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) map[i, j] = myRand.Next(1,6); for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) Dia[i * width + j] = new Diamond(map[i, j], 40 * j + Add_width, 40 * i + Add_height, 40 * j + Add_width, 40 * i + Add_height); } //更新 void Update() { for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) Dia[i * width + j] = new Diamond(map[i, j], 40 * j + Add_width, 40 * i + Add_height, 40 * j + Add_width, 40 * i + Add_height); pictureBox.Invalidate(); } //深度优先搜索计算连通块 void DFS(int x, int y) { flag[x, y] = 1; for (int i = 0; i < 4; i++) { int NewX = x + dir[i, 0]; int NewY = y + dir[i, 1]; if (NewX >= 0 && NewX < height) if (NewY >= 0 && NewY < width) if (map[x, y] == map[NewX, NewY]&&map[x,y]!=0) if (flag[NewX, NewY] == 0) DFS(NewX,NewY); } } //下一关 void GameSt() { Now_toll++; label2.Text = "目标:" + (Now_toll * 1200 + Now_toll * Now_toll * Now_toll * 50).ToString(); label5.Text = "关卡:" + Now_toll.ToString(); news = news + "进入下一关," + label5.Text + "\r\n"; textBox1.Text = news; //让文本框获取焦点 this.textBox1.Focus(); //设置光标的位置到文本尾 this.textBox1.Select(this.textBox1.TextLength, 0); //滚动到控件光标处 this.textBox1.ScrollToCaret(); GameState = 2; Rand(); pictureBox.Invalidate(); } //启动或者重新开始游戏之后的初始化 void init() { dir[0, 0] = 0; dir[0, 1] = 1; dir[1, 0] = 0; dir[1, 1] = -1; dir[2, 0] = 1; dir[2, 1] = 0; dir[3, 0] = -1; dir[3, 1] = 0; //设置游戏状态 GameState = 0; RMB = 5; label3.Text = "金币:" + RMB.ToString(); score = 0; Now_toll = 1; num_Skill1 = 0; num_Skill2 = 0; num_Skill3 = 0; //绘制“游戏即将开始”字样 Dia[400] = new Diamond(6, 60, 225, 5, 5); //下一关字样 Dia[399] = new Diamond(7, 130, 250, 5, 5); //绘制鼠标 Bitmap a = (Bitmap)Bitmap.FromFile("Image\\mouse.png"); SetCursor(a, new Point(0, 0)); update_skill_button(); news = "消息列表:\r\n" + "欢迎来到消灭星星世界,赶紧开始拯救人类的行动吧!\r\n"; textBox1.Text = news; label11.Text = "欢迎进入这个虚幻的世界"; ReStartGame.Enabled = false; } private void Game_Load(object sender, EventArgs e) { init(); } //计算下落 void Down() { for (int j = 0; j < width; j++) { for (int i = 0; i < 100; i++) tot[i] = 0; for (int i = height - 1; i >= 0; i--) { if (map[i, j] == 0) tot[i] = tot[i + 1] + 1; else tot[i] = tot[i + 1]; } for (int i = height - 1; i >= 0; i--) { if (map[i, j] == 0) tot[i] = -1; temp[i] = map[i, j]; map[i, j] = 0; } for (int i = height - 1; i >= 0; i--) { if (tot[i] != -1) { map[i + tot[i], j] = temp[i]; int id = i * width + j; Dia[id].Ex = j * 40 + Add_width; Dia[id].Ey = (i + tot[i]) * 40 + Add_height; } } } } //计算左靠 void Left() { for (int j = 0; j < 100; j++) tot[j] = 0; for (int j = 0; j < width; j++) { if (j == 0) { if (map[height - 1, 0] == 0) tot[j] = 1; else tot[j] = 0; } else { if (map[height - 1, j] == 0) tot[j] = tot[j - 1] + 1; else tot[j] = tot[j - 1]; } } for (int j = 0; j < width; j++) if (map[height - 1, j] == 0) tot[j] = -1; for (int j = 0; j < width; j++) for (int i = 0; i < height; i++) if (tot[j] != -1) map[i, j - tot[j]] = map[i, j]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int id = i * width + j; Dia[id].Ex = (j - tot[j]) * 40 + Add_width; Dia[id].Ey = i * 40 + Add_height; } } int Max = -1; for (int j = 0; j < width; j++) if (tot[j] != -1) if (j - tot[j] > Max) Max = j - tot[j]; for (int j = Max + 1; j < width; j++) for (int i = 0; i < height; i++) map[i, j] = 0; } //执行一系列操作 void Effect() { axWindowsMediaPlayer1.URL = "Music\\mus1.wav"; axWindowsMediaPlayer1.Ctlcontrols.play(); Tot = 0; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (flag[i, j] == 1) { labels[Tot] = new Label(); labels[Tot].Size = new System.Drawing.Size(32, 32); labels[Tot].Image = Image.FromFile("Image\\xg.gif"); labels[Tot].Location = new Point(j * 40 + Add_width + 4, i * 40 + Add_height + 4); this.pictureBox.Controls.Add(labels[Tot]); Tot++; flag[i, j] = 0; } } } T = 0; timer3.Enabled = true; } //判断是否还可以消去 void Judge() { int res = 0; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (map[i, j] == 0) continue; for (int ii = 0; ii < height; ii++) for (int jj = 0; jj < width; jj++) flag[ii, jj] = 0; //计算连通块 DFS(i, j); int Count = 0; for (int ii = 0; ii < height; ii++) for (int jj = 0; jj < width; jj++) if (flag[ii, jj] == 1) Count++; if (Count >= 2) { res = 1; break; } } if (res == 1) break; } for (int ii = 0; ii < height; ii++) for (int jj = 0; jj < width; jj++) flag[ii, jj] = 0; if (res == 0) { axWindowsMediaPlayer1.URL = "Music\\next.mp3"; axWindowsMediaPlayer1.Ctlcontrols.play(); //显示下一关字样 if (score >= Now_toll * 1200 + Now_toll * Now_toll * Now_toll * 50) { GameState = 1; time_font = 0; pictureBox.Invalidate(); timer4.Enabled = true; } else//游戏结束,跳出窗口 { label1.Text = "Score:0"; label2.Text = "目标:0"; StartGame.Enabled = true; textBox_Name.Enabled = true; textBox_Name.Text = ""; label4.Text = "玩家:"; MessageBox.Show("由于未达到本关的目标分数,所以本次游戏结束啦!恭喜你!" + textBox_Name.Text + "得分:" + score.ToString(), "友情提示"); End End1 = new End(); End1.Show(); this.Close(); init(); pictureBox.Invalidate(); } } } //技能1 重置地图 void Skill_1() { Random myRand = new Random(DateTime.Now.Second); for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) if (map[i, j] != 0) map[i, j] = myRand.Next(1, 5); Update(); } //技能2 随机清除一列 void Skill_2() { int Max=0; for (int i = 0; i < width; i++) if (map[height - 1, i] != 0) Max = i; Random myRand = new Random(DateTime.Now.Second); int res = myRand.Next(0, Max); for (int i = 0; i < height; i++) if (map[i, res] != 0) { map[i, res] = 0; flag[i, res] = 1; score = score + 6; } label1.Text = "分数:" + score.ToString(); Effect(); } //技能3 随机清除一种颜色 void Skill_3() { int[] Kind = new int[100]; int[] F = new int[100]; int n = 0; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (map[i, j] != 0 && F[map[i, j]] == 0) { F[map[i, j]] = 1; Kind[n++] = map[i, j]; } } } if (n != 0) { Random myRand = new Random(DateTime.Now.Second); int res = myRand.Next(0, n); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (map[i, j] == Kind[res]) { score = score + 1; map[i, j] = 0; flag[i, j] = 1; } } } label1.Text = "分数:" + score.ToString(); Effect(); } } private void Game_MouseDown(object sender, MouseEventArgs e) { } //鼠标点击 private void pictureBox_MouseDown(object sender, MouseEventArgs e) { if (timer1.Enabled == false && timer2.Enabled == false && timer3.Enabled == false &&timer4.Enabled==false&&e.Y - Add_height > 0 && e.X - Add_width > 0) { int nowR = (e.Y - Add_height) / 40;//鼠标点击的行 int nowC = (e.X - Add_width) / 40;//鼠标点击的列 if (flag[nowR, nowC] == 0) { Update(); axWindowsMediaPlayer1.URL = "Music\\click.wav"; axWindowsMediaPlayer1.Ctlcontrols.play(); for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) flag[i, j] = 0; //计算连通块 DFS(nowR, nowC); int Count = 0; for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) if (flag[i, j] == 1) Count++; if (Count < 2) { for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) flag[i, j] = 0; } else { //画线 for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) if (flag[i, j] == 1) { int id = i * width + j; Dia[id].Change(); } int add_RMB = 0; if (Count <= 4) add_RMB = 0; if (Count >= 5 && Count <= 6) add_RMB = 2; if (Count >= 7 && Count <= 8) add_RMB = 4; if (Count >= 9) add_RMB = 6; label11.Text = "消除选中部分 积分+" + (5 * Count * Count).ToString() + ",金币+" + add_RMB.ToString(); pictureBox.Invalidate(); } } else if (flag[nowR, nowC] == 1) { int Count = 0; for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) if (flag[i, j] == 1) Count++; score = score + Count * Count * 5; label1.Text = "分数:" + score.ToString(); int add_RMB = 0; if (Count <= 4) { add_RMB = 0; label11.Text = "Great! "; } if (Count >= 5 && Count <= 6) { add_RMB = 2; label11.Text = "Cool! "; } if (Count >= 7 && Count <= 8) { add_RMB = 4; label11.Text = "Perfect! "; } if (Count >= 9) { add_RMB = 6; label11.Text = "帅呆了! "; } label11.Text += "积分+" + (5 * Count * Count).ToString() + ",金币+" + add_RMB.ToString(); news = news + label11.Text + "\r\n"; textBox1.Text = news; //让文本框获取焦点 this.textBox1.Focus(); //设置光标的位置到文本尾 this.textBox1.Select(this.textBox1.TextLength, 0); //滚动到控件光标处 this.textBox1.ScrollToCaret(); RMB = RMB + add_RMB; label3.Text = "金币:"+RMB.ToString(); update_skill_button(); for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) if (flag[i, j] == 1) map[i, j] = 0; //进行一系列操作 Effect(); } } } //执行下落 private void timer1_Tick(object sender, EventArgs e) { D = width * height; for (int i = 0; i < width * height; i++) D = D - Dia[i].move(); if (D == 0) { timer1.Enabled = false; Update(); //计算左靠 Left(); //开始左靠 timer2.Enabled = true; } pictureBox.Invalidate(); } private void pictureBox_Paint(object sender, PaintEventArgs e) { if (GameState == 2) { for (int i = width * height - 1; i >= 0; i--) Dia[i].Draw(e.Graphics); } else if (GameState == 1) { Dia[399].Draw(e.Graphics); } else if (GameState == 0) { Dia[400].Draw(e.Graphics); } } //执行左靠 private void timer2_Tick(object sender, EventArgs e) { D = width * height; for (int i = 0; i < width * height; i++) D = D - Dia[i].move(); if (D == 0) { timer2.Enabled = false; Update(); //判断是否还有解 Judge(); } pictureBox.Invalidate(); } //执行消除星星的效果 private void timer3_Tick(object sender, EventArgs e) { T++; if (T == 5) { timer3.Enabled = false; for (int i = 0; i < Tot; i++) { labels[i].Size = new System.Drawing.Size(0, 0); labels[i].Location = new Point(0, 0); this.pictureBox.Controls.Add(labels[i]); } //更新 Update(); //计算下落 Down(); //开始下落 timer1.Enabled = true; } } private void Close_Click(object sender, EventArgs e) { this.Close(); } private void pictureBox_Click(object sender, EventArgs e) { } //执行技能1 private void button1_Click(object sender, EventArgs e) { news = news + "使用技能:唯我独尊\r\n"; textBox1.Text = news; //让文本框获取焦点 this.textBox1.Focus(); //设置光标的位置到文本尾 this.textBox1.Select(this.textBox1.TextLength, 0); //滚动到控件光标处 this.textBox1.ScrollToCaret(); num_Skill2--; label9.Text = "唯我独尊 ×" + num_Skill2.ToString(); Skill_1(); update_skill_button(); } //执行技能2 private void button2_Click(object sender, EventArgs e) { news = news + "使用技能:浮生万刃\r\n"; textBox1.Text = news; //让文本框获取焦点 this.textBox1.Focus(); //设置光标的位置到文本尾 this.textBox1.Select(this.textBox1.TextLength, 0); //滚动到控件光标处 this.textBox1.ScrollToCaret(); num_Skill1--; label8.Text = "浮生万仞 ×" + num_Skill1.ToString(); Skill_2(); update_skill_button(); } //执行技能3 private void button3_Click(object sender, EventArgs e) { news = news + "使用技能:咫尺天涯\r\n"; textBox1.Text = news; //让文本框获取焦点 this.textBox1.Focus(); //设置光标的位置到文本尾 this.textBox1.Select(this.textBox1.TextLength, 0); //滚动到控件光标处 this.textBox1.ScrollToCaret(); num_Skill3--; label10.Text = "咫尺天涯 ×" + num_Skill3.ToString(); Skill_3(); update_skill_button(); } //自定义光标 public void SetCursor(Bitmap cursor, Point hotPoint) { int hotX = hotPoint.X; int hotY = hotPoint.Y; Bitmap myNewCursor = new Bitmap(cursor.Width * 2 - hotX, cursor.Height * 2 - hotY); Graphics g = Graphics.FromImage(myNewCursor); g.Clear(Color.FromArgb(0, 0, 0, 0)); g.DrawImage(cursor, cursor.Width - hotX, cursor.Height - hotY, cursor.Width, cursor.Height); this.Cursor = new Cursor(myNewCursor.GetHicon()); g.Dispose(); myNewCursor.Dispose(); } //开始游戏 private void StartGame_Click(object sender, EventArgs e) { axWindowsMediaPlayer1.URL = "Music\\click.wav"; axWindowsMediaPlayer1.Ctlcontrols.play(); news += "游戏已经开始啦!" + "当前玩家:" + textBox_Name.Text+"!\r\n"; textBox1.Text = news; label11.Text = "游戏开始啦!"; ReStartGame.Enabled = true; StartGame.Enabled = false; textBox_Name.Enabled = false; GameState = 2; score = 0; Now_toll = 0; label4.Text = "玩家:" + textBox_Name.Text; update_skill_button(); GameSt(); } //重新开始游戏 private void ReStartGame_Click(object sender, EventArgs e) { axWindowsMediaPlayer1.URL = "Music\\click.wav"; axWindowsMediaPlayer1.Ctlcontrols.play(); label1.Text = "Score:0"; label2.Text = "目标:0"; StartGame.Enabled = true; textBox_Name.Enabled = true; textBox_Name.Text = ""; label4.Text = "玩家:" ; init(); pictureBox.Invalidate(); } private void label5_Click(object sender, EventArgs e) { } private void button4_Click(object sender, EventArgs e) { axWindowsMediaPlayer1.URL = "Music\\click.wav"; axWindowsMediaPlayer1.Ctlcontrols.play(); if (RMB - 2 >= 0) { RMB = RMB - 2; num_Skill1++; label3.Text = "金币:" + RMB.ToString(); label8.Text = "浮生万仞 ×" + num_Skill1.ToString(); news = news + "购买一个浮生万仞,金币-2." + "\r\n"; textBox1.Text = news; //让文本框获取焦点 this.textBox1.Focus(); //设置光标的位置到文本尾 this.textBox1.Select(this.textBox1.TextLength, 0); //滚动到控件光标处 this.textBox1.ScrollToCaret(); } else { news = news + "金币不足,购买失败!" + "\r\n"; textBox1.Text = news; //让文本框获取焦点 this.textBox1.Focus(); //设置光标的位置到文本尾 this.textBox1.Select(this.textBox1.TextLength, 0); //滚动到控件光标处 this.textBox1.ScrollToCaret(); MessageBox.Show("RMB不够啦!请给Me充钱!然后联系作者!", "友情提示"); } update_skill_button(); } private void button5_Click(object sender, EventArgs e) { axWindowsMediaPlayer1.URL = "Music\\click.wav"; axWindowsMediaPlayer1.Ctlcontrols.play(); if (RMB - 5 >= 0) { RMB = RMB - 5; num_Skill2++; label3.Text = "金币:" + RMB.ToString(); label9.Text = "唯我独尊 ×" + num_Skill2.ToString(); news = news + "购买一个唯我独尊,金币-5." + "\r\n"; textBox1.Text = news; //让文本框获取焦点 this.textBox1.Focus(); //设置光标的位置到文本尾 this.textBox1.Select(this.textBox1.TextLength, 0); //滚动到控件光标处 this.textBox1.ScrollToCaret(); } else { news = news + "金币不足,购买失败!" + "\r\n"; textBox1.Text = news; //让文本框获取焦点 this.textBox1.Focus(); //设置光标的位置到文本尾 this.textBox1.Select(this.textBox1.TextLength, 0); //滚动到控件光标处 this.textBox1.ScrollToCaret(); MessageBox.Show("RMB不够啦!请给Me充钱!然后联系作者!", "友情提示"); } update_skill_button(); } private void button6_Click(object sender, EventArgs e) { axWindowsMediaPlayer1.URL = "Music\\click.wav"; axWindowsMediaPlayer1.Ctlcontrols.play(); if (RMB - 5 >= 0) { RMB = RMB - 5; num_Skill3++; label3.Text = "金币:" + RMB.ToString(); label10.Text = "咫尺天涯 ×" + num_Skill3.ToString(); news = news + "购买一个咫尺天涯,金币-5." + "\r\n"; textBox1.Text = news; //让文本框获取焦点 this.textBox1.Focus(); //设置光标的位置到文本尾 this.textBox1.Select(this.textBox1.TextLength, 0); //滚动到控件光标处 this.textBox1.ScrollToCaret(); } else { news = news + "金币不足,购买失败!" + "\r\n"; textBox1.Text = news; //让文本框获取焦点 this.textBox1.Focus(); //设置光标的位置到文本尾 this.textBox1.Select(this.textBox1.TextLength, 0); //滚动到控件光标处 this.textBox1.ScrollToCaret(); MessageBox.Show("RMB不够啦!请给Me充钱!然后联系作者!", "友情提示"); } update_skill_button(); } private void timer4_Tick(object sender, EventArgs e) { time_font++; if (time_font == 25) { timer4.Enabled = false; GameSt(); } } private void button7_Click(object sender, EventArgs e) { } } }