明天就要去上海大学参加 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 = ;
int Add_height = ;
Diamond[] Dia = new Diamond[*];
int height = ;//高
int width=;//宽
int[,] map = new int[, ];//定义地图
int[,] flag = new int[, ];//用于深度优先搜索求连通块
int[,] dir = new int[, ];//搜索时用到的四个方向
int[] tot = new int[];//方块掉落时候用的
int[] temp = new int[];//临时存储
int D;//控制下落 Label[] labels = new Label[*];
int T;//控制显示效果
int Tot;//控制显示效果
int GameState;//控制游戏状态
int time_font;//控制下一关字样的显示时间 int Now_toll = ;//关卡数量
int score = ;//计分
int RMB = ; int num_Skill1 = ;
int num_Skill2 = ;
int num_Skill3 = ; String news; public Game()
{
InitializeComponent();
} //技能按钮状态更新
void update_skill_button()
{
if (num_Skill1 > ) button2.Enabled = true;
else button2.Enabled = false; if (num_Skill2 > ) button1.Enabled = true;
else button1.Enabled = false; if (num_Skill3 > ) button3.Enabled = true;
else button3.Enabled = false; if (RMB < ) button4.Enabled = false;
else button4.Enabled = true; if (RMB < ) button5.Enabled = false;
else button5.Enabled = true; if (RMB < ) button6.Enabled = false;
else button6.Enabled = true;
} //随机生成地图
void Rand()
{
Random myRand = new Random(DateTime.Now.Second);
for (int i = ; i < height; i++)
for (int j = ; j < width; j++)
map[i, j] = myRand.Next(,); for (int i = ; i < height; i++)
for (int j = ; j < width; j++)
Dia[i * width + j] = new Diamond(map[i, j], * j + Add_width, * i + Add_height, * j + Add_width, * i + Add_height);
} //更新
void Update()
{
for (int i = ; i < height; i++)
for (int j = ; j < width; j++)
Dia[i * width + j] = new Diamond(map[i, j], * j + Add_width, * i + Add_height, * j + Add_width, * i + Add_height); pictureBox.Invalidate();
} //深度优先搜索计算连通块
void DFS(int x, int y)
{
flag[x, y] = ;
for (int i = ; i < ; i++)
{
int NewX = x + dir[i, ];
int NewY = y + dir[i, ]; if (NewX >= && NewX < height)
if (NewY >= && NewY < width)
if (map[x, y] == map[NewX, NewY]&&map[x,y]!=)
if (flag[NewX, NewY] == )
DFS(NewX,NewY);
}
} //下一关
void GameSt()
{
Now_toll++;
label2.Text = "目标:" + (Now_toll * + Now_toll * Now_toll * Now_toll * ).ToString();
label5.Text = "关卡:" + Now_toll.ToString();
news = news + "进入下一关," + label5.Text + "\r\n";
textBox1.Text = news;
//让文本框获取焦点
this.textBox1.Focus();
//设置光标的位置到文本尾
this.textBox1.Select(this.textBox1.TextLength, );
//滚动到控件光标处
this.textBox1.ScrollToCaret();
GameState = ;
Rand();
pictureBox.Invalidate(); } //启动或者重新开始游戏之后的初始化
void init()
{
dir[, ] = ; dir[, ] = ;
dir[, ] = ; dir[, ] = -;
dir[, ] = ; dir[, ] = ;
dir[, ] = -; dir[, ] = ; //设置游戏状态
GameState = ; RMB = ; label3.Text = "金币:" + RMB.ToString();
score = ;
Now_toll = ;
num_Skill1 = ;
num_Skill2 = ;
num_Skill3 = ; //绘制“游戏即将开始”字样
Dia[] = new Diamond(, , , , ); //下一关字样
Dia[] = new Diamond(, , , , ); //绘制鼠标
Bitmap a = (Bitmap)Bitmap.FromFile("Image\\mouse.png");
SetCursor(a, new Point(, )); 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 = ; j < width; j++)
{
for (int i = ; i < ; i++) tot[i] = ;
for (int i = height - ; i >= ; i--)
{
if (map[i, j] == ) tot[i] = tot[i + ] + ;
else tot[i] = tot[i + ];
}
for (int i = height - ; i >= ; i--)
{
if (map[i, j] == ) tot[i] = -;
temp[i] = map[i, j];
map[i, j] = ;
}
for (int i = height - ; i >= ; i--)
{
if (tot[i] != -)
{
map[i + tot[i], j] = temp[i]; int id = i * width + j;
Dia[id].Ex = j * + Add_width;
Dia[id].Ey = (i + tot[i]) * + Add_height;
}
}
}
} //计算左靠
void Left()
{
for (int j = ; j < ; j++) tot[j] = ;
for (int j = ; j < width; j++)
{
if (j == )
{
if (map[height - , ] == ) tot[j] = ;
else tot[j] = ;
}
else
{
if (map[height - , j] == ) tot[j] = tot[j - ] + ;
else tot[j] = tot[j - ];
}
} for (int j = ; j < width; j++)
if (map[height - , j] == ) tot[j] = -; for (int j = ; j < width; j++)
for (int i = ; i < height; i++)
if (tot[j] != -)
map[i, j - tot[j]] = map[i, j];
for (int i = ; i < height; i++)
{
for (int j = ; j < width; j++)
{
int id = i * width + j;
Dia[id].Ex = (j - tot[j]) * + Add_width;
Dia[id].Ey = i * + Add_height;
}
}
int Max = -;
for (int j = ; j < width; j++)
if (tot[j] != -)
if (j - tot[j] > Max)
Max = j - tot[j];
for (int j = Max + ; j < width; j++)
for (int i = ; i < height; i++)
map[i, j] = ;
} //执行一系列操作
void Effect()
{
axWindowsMediaPlayer1.URL = "Music\\mus1.wav";
axWindowsMediaPlayer1.Ctlcontrols.play(); Tot = ;
for (int i = ; i < height; i++)
{
for (int j = ; j < width; j++)
{
if (flag[i, j] == )
{
labels[Tot] = new Label();
labels[Tot].Size = new System.Drawing.Size(, );
labels[Tot].Image = Image.FromFile("Image\\xg.gif");
labels[Tot].Location = new Point(j * + Add_width + , i * + Add_height + );
this.pictureBox.Controls.Add(labels[Tot]);
Tot++;
flag[i, j] = ;
}
}
} T = ;
timer3.Enabled = true;
} //判断是否还可以消去
void Judge()
{
int res = ;
for (int i = ; i < height; i++)
{
for (int j = ; j < width; j++)
{
if (map[i, j] == ) continue;
for (int ii = ; ii < height; ii++)
for (int jj = ; jj < width; jj++)
flag[ii, jj] = ; //计算连通块
DFS(i, j); int Count = ;
for (int ii = ; ii < height; ii++)
for (int jj = ; jj < width; jj++)
if (flag[ii, jj] == )
Count++; if (Count >= )
{
res = ;
break;
}
}
if (res == ) break;
} for (int ii = ; ii < height; ii++)
for (int jj = ; jj < width; jj++)
flag[ii, jj] = ; if (res == )
{
axWindowsMediaPlayer1.URL = "Music\\next.mp3";
axWindowsMediaPlayer1.Ctlcontrols.play(); //显示下一关字样
if (score >= Now_toll * + Now_toll * Now_toll * Now_toll * )
{
GameState = ;
time_font = ;
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 = ; i < height; i++)
for (int j = ; j < width; j++)
if (map[i, j] != )
map[i, j] = myRand.Next(, );
Update();
} //技能2 随机清除一列
void Skill_2()
{
int Max=;
for (int i = ; i < width; i++)
if (map[height - , i] != )
Max = i;
Random myRand = new Random(DateTime.Now.Second);
int res = myRand.Next(, Max);
for (int i = ; i < height; i++)
if (map[i, res] != )
{ map[i, res] = ; flag[i, res] = ; score = score + ; } label1.Text = "分数:" + score.ToString(); Effect();
} //技能3 随机清除一种颜色
void Skill_3()
{
int[] Kind = new int[];
int[] F = new int[];
int n = ;
for (int i = ; i < height; i++)
{
for (int j = ; j < width; j++)
{
if (map[i, j] != && F[map[i, j]] == )
{
F[map[i, j]] = ;
Kind[n++] = map[i, j];
}
}
}
if (n != )
{
Random myRand = new Random(DateTime.Now.Second);
int res = myRand.Next(, n); for (int i = ; i < height; i++)
{
for (int j = ; j < width; j++)
{
if (map[i, j] == Kind[res])
{
score = score + ;
map[i, j] = ;
flag[i, j] = ;
}
}
} 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 > && e.X - Add_width > )
{
int nowR = (e.Y - Add_height) / ;//鼠标点击的行
int nowC = (e.X - Add_width) / ;//鼠标点击的列 if (flag[nowR, nowC] == )
{
Update();
axWindowsMediaPlayer1.URL = "Music\\click.wav";
axWindowsMediaPlayer1.Ctlcontrols.play();
for (int i = ; i < height; i++)
for (int j = ; j < width; j++)
flag[i, j] = ; //计算连通块
DFS(nowR, nowC); int Count = ;
for (int i = ; i < height; i++)
for (int j = ; j < width; j++)
if (flag[i, j] == )
Count++; if (Count < )
{
for (int i = ; i < height; i++)
for (int j = ; j < width; j++)
flag[i, j] = ;
} else
{
//画线
for (int i = ; i < height; i++)
for (int j = ; j < width; j++)
if (flag[i, j] == )
{
int id = i * width + j;
Dia[id].Change();
} int add_RMB = ;
if (Count <= ) add_RMB = ;
if (Count >= && Count <= ) add_RMB = ;
if (Count >= && Count <= ) add_RMB = ;
if (Count >= ) add_RMB = ;
label11.Text = "消除选中部分 积分+" + ( * Count * Count).ToString() + ",金币+" + add_RMB.ToString();
pictureBox.Invalidate();
} } else if (flag[nowR, nowC] == )
{
int Count = ;
for (int i = ; i < height; i++)
for (int j = ; j < width; j++)
if (flag[i, j] == )
Count++; score = score + Count * Count * ; label1.Text = "分数:" + score.ToString(); int add_RMB = ;
if (Count <= )
{
add_RMB = ;
label11.Text = "Great! ";
}
if (Count >= && Count <= )
{
add_RMB = ;
label11.Text = "Cool! ";
}
if (Count >= && Count <= )
{
add_RMB = ;
label11.Text = "Perfect! ";
}
if (Count >= )
{
add_RMB = ;
label11.Text = "帅呆了! ";
}
label11.Text += "积分+" + ( * Count * Count).ToString() + ",金币+" + add_RMB.ToString();
news = news + label11.Text + "\r\n";
textBox1.Text = news; //让文本框获取焦点
this.textBox1.Focus();
//设置光标的位置到文本尾
this.textBox1.Select(this.textBox1.TextLength, );
//滚动到控件光标处
this.textBox1.ScrollToCaret(); RMB = RMB + add_RMB; label3.Text = "金币:"+RMB.ToString(); update_skill_button(); for (int i = ; i < height; i++)
for (int j = ; j < width; j++)
if (flag[i, j] == )
map[i, j] = ; //进行一系列操作
Effect(); }
}
} //执行下落
private void timer1_Tick(object sender, EventArgs e)
{
D = width * height;
for (int i = ; i < width * height; i++)
D = D - Dia[i].move(); if (D == )
{
timer1.Enabled = false;
Update(); //计算左靠
Left(); //开始左靠
timer2.Enabled = true;
}
pictureBox.Invalidate();
} private void pictureBox_Paint(object sender, PaintEventArgs e)
{
if (GameState == )
{
for (int i = width * height - ; i >= ; i--)
Dia[i].Draw(e.Graphics);
} else if (GameState == )
{
Dia[].Draw(e.Graphics);
} else if (GameState == )
{
Dia[].Draw(e.Graphics);
}
} //执行左靠
private void timer2_Tick(object sender, EventArgs e)
{
D = width * height;
for (int i = ; i < width * height; i++)
D = D - Dia[i].move(); if (D == )
{
timer2.Enabled = false;
Update(); //判断是否还有解
Judge();
}
pictureBox.Invalidate();
} //执行消除星星的效果
private void timer3_Tick(object sender, EventArgs e)
{
T++;
if (T == )
{
timer3.Enabled = false; for (int i = ; i < Tot; i++)
{
labels[i].Size = new System.Drawing.Size(, );
labels[i].Location = new Point(, );
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, );
//滚动到控件光标处
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, );
//滚动到控件光标处
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, );
//滚动到控件光标处
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 * - hotX, cursor.Height * - hotY);
Graphics g = Graphics.FromImage(myNewCursor);
g.Clear(Color.FromArgb(, , , ));
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 = ;
score = ;
Now_toll = ;
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 - >= )
{
RMB = RMB - ;
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, );
//滚动到控件光标处
this.textBox1.ScrollToCaret();
}
else
{
news = news + "金币不足,购买失败!" + "\r\n";
textBox1.Text = news;
//让文本框获取焦点
this.textBox1.Focus();
//设置光标的位置到文本尾
this.textBox1.Select(this.textBox1.TextLength, );
//滚动到控件光标处
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 - >= )
{
RMB = RMB - ;
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, );
//滚动到控件光标处
this.textBox1.ScrollToCaret();
}
else
{
news = news + "金币不足,购买失败!" + "\r\n";
textBox1.Text = news;
//让文本框获取焦点
this.textBox1.Focus();
//设置光标的位置到文本尾
this.textBox1.Select(this.textBox1.TextLength, );
//滚动到控件光标处
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 - >= )
{
RMB = RMB - ;
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, );
//滚动到控件光标处
this.textBox1.ScrollToCaret();
}
else
{
news = news + "金币不足,购买失败!" + "\r\n";
textBox1.Text = news;
//让文本框获取焦点
this.textBox1.Focus();
//设置光标的位置到文本尾
this.textBox1.Select(this.textBox1.TextLength, );
//滚动到控件光标处
this.textBox1.ScrollToCaret();
MessageBox.Show("RMB不够啦!请给Me充钱!然后联系作者!", "友情提示");
}
update_skill_button();
} private void timer4_Tick(object sender, EventArgs e)
{
time_font++;
if (time_font == )
{
timer4.Enabled = false;
GameSt();
}
} private void button7_Click(object sender, EventArgs e)
{ }
}
}