net: [[../BehaviorTracking/else/笔记系统构建]]
实验九
完成捉猴子游戏的设计与开发,实现以下基本功能:
(1) 小猴子随机出现在某个位置;
(2) 在一个给定的时间内,玩家可以用鼠标左键来点击该猴子,若击中,则该小猴子立即“变脸”;
(3) 在给定时间结束时,若玩家还没有击中,该小猴子就会逃走,随机出现在另外的位置……;
(4) 利用菜单开始游戏、设置猴子数量和时间间隔。
(5) 给游戏添加背景音乐和音效。
实验过程
- 设计UI界面,包括游戏主窗体及菜单项,并添加必要的控件,如Label、Button等。

2. 设计一个猴子类,包括以下几个属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Monkey
{
public int X { get; set; }
public int Y { get; set; }
public bool IsCaptured { get; set; }
public Image FreeImage { get; set; }
public Image CapturedImage { get; set; }
}
|
3. 进行一些初始变量的声明,包括猴子数量、时间间隔等
1 2 3 4 5 6 7 8 9
| private int monkeyCount = 1;
private int timeInterval = 1000;
private List<Monkey> monkeys = new List<Monkey>();
private Timer timer = new Timer();
|
4. 对窗体进行一些初始化设置,具体代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
InitializeComponent();
timer.Interval = timeInterval;
timer.Tick += timer_Tick;
}
|
5. 定义生成猴子函数,用于相应数量的猴子生成,这里用到了tag将monkey类与picbox相关联。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| private void GenerateMonkeys(int num)
{
Random ran = new Random();
for (int i = 0; i < num; i++)
{
Monkey monkey = new Monkey();
monkey.FreeImage = Image.FromFile("monkey_normal.png");
monkey.CapturedImage = Image.FromFile("monkey_hit.png");
monkey.X = ran.Next(0, this.ClientSize.Width - monkey.FreeImage.Width);
monkey.Y = ran.Next(0, this.ClientSize.Height - monkey.FreeImage.Height);
monkeys.Add(monkey);
PictureBox picBox = new PictureBox();
picBox.Location = new Point(monkey.X, monkey.Y);
picBox.Image = monkey.FreeImage;
picBox.Size = new Size(monkey.FreeImage.Width, monkey.FreeImage.Height);
picBox.Tag = monkey;
picBox.Click += PicBox_Click;
this.Controls.Add(picBox);
}
}
|
这里注意:要先将猴子的图片放在项目中的“游戏技术基础:实验九\游戏技术基础:实验九\bin\Debug”目录中
6. 利用picturebox的点击事件,检测鼠标左键的点击动作,判断是否击中猴子,并更新猴子的图案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| private void PicBox_Click(object sender, EventArgs e)
{
PictureBox picBox = sender as PictureBox;
Monkey monkey = picBox.Tag as Monkey;
if (!monkey.IsCaptured)
{
monkey.IsCaptured = true;
picBox.Image = monkey.CapturedImage;
score.Text = (int.Parse(score.Text) + 1).ToString();
}
}
|
7. 设置定时器,控制猴子的移动与刷新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| private void timer_Tick(object sender, EventArgs e)
{
Random ran = new Random();
foreach (var picBox in this.Controls.OfType<PictureBox>())
{
Monkey monkey = picBox.Tag as Monkey;
if (!monkey.IsCaptured)
{
monkey.X = ran.Next(0, this.ClientSize.Width - monkey.FreeImage.Width);
monkey.Y = ran.Next(0, this.ClientSize.Height - monkey.FreeImage.Height);
picBox.Location = new Point(monkey.X, monkey.Y);
picBox.Image = monkey.FreeImage;
}
}
}
|
- 添加菜单项,实现游戏开始、重置猴子数量和时间间隔等功能,使用Dialog窗体进行设置。
7.1 开始游戏菜单设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| private void 开始ToolStripMenuItem_Click(object sender, EventArgs e)
{
score.Text = "0";
this.Controls.OfType<PictureBox>().ToList().ForEach(x => this.Controls.Remove(x));
this.monkeys.Clear();
GenerateMonkeys(monkeyCount);
timer.Start();
}
|
7.2 猴子数量的菜单设置,这里新建了一个窗口用来接收猴子数量
#主窗口函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private void 猴子数量ToolStripMenuItem_Click(object sender, EventArgs e)
{
MonkeyCountDialog dlg = new MonkeyCountDialog(monkeyCount);
if (dlg.ShowDialog() == DialogResult.OK)
{
monkeyCount = dlg.MonkeyCount;
GenerateMonkeys(monkeyCount);
}
}
|
#新建窗口form2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| public partial class MonkeyCountDialog : Form
{
public int MonkeyCount { get; private set; }
public MonkeyCountDialog(int count)
{
InitializeComponent();
txtCount.Text = count.ToString();
txtCount.SelectAll();
txtCount.Focus();
}
private void MonkeyCountDialog_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
if (int.TryParse(txtCount.Text.Trim(), out int count))
{
if (count >= 1 && count <= 10)
{
MonkeyCount = count;
DialogResult = DialogResult.OK;
Close();
}
else
{
MessageBox.Show("猴子数量应在1~10之间!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
txtCount.Focus();
txtCount.SelectAll();
}
}
else
{
MessageBox.Show("请输入有效的猴子数量!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
txtCount.Focus();
txtCount.SelectAll();
}
}
}
|
7.3 时间间隔菜单设置,与猴子数量的设置实现思路一致
#主窗口函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private void 时间间隔ToolStripMenuItem_Click(object sender, EventArgs e)
{
TimeIntervalDialog dlg = new TimeIntervalDialog(timeInterval);
if (dlg.ShowDialog() == DialogResult.OK)
{
timeInterval = dlg.TimeInterval;
timer.Interval = timeInterval;
}
}
|
#新建窗口TimeIntervalDialog

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| public partial class TimeIntervalDialog : Form
{
public int TimeInterval { get; private set; }
public TimeIntervalDialog(int interval)
{
InitializeComponent();
txtInterval.Text = interval.ToString();
txtInterval.SelectAll();
txtInterval.Focus();
}
private void button1_Click(object sender, EventArgs e)
{
if (int.TryParse(txtInterval.Text.Trim(), out int interval))
{
if (interval >= 1000 && interval <= 10000)
{
TimeInterval = interval;
DialogResult = DialogResult.OK;
Close();
}
else
{
MessageBox.Show("时间间隔应在1s~10s之间!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
txtInterval.Focus();
txtInterval.SelectAll();
}
}
else
{
MessageBox.Show("请输入有效的时间间隔!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
txtInterval.Focus();
txtInterval.SelectAll();
}
}
}
|
8. 最后在代码中添加播放背景音乐和音效的功能,同样需要把音效和音乐文件放在与图片文件相同的地方。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| public partial class Form1 : Form
{
private SoundPlayer captureSound;
private SoundPlayer bgm;
private void Form1_Load(object sender, EventArgs e)
{
captureSound = new SoundPlayer("capture.wav");
bgm = new SoundPlayer("bgm.wav");
bgm.PlayLooping();
}
private void PicBox_Click(object sender, EventArgs e)
{
PictureBox picBox = sender as PictureBox;
Monkey monkey = picBox.Tag as Monkey;
if (!monkey.IsCaptured)
{
monkey.IsCaptured = true;
picBox.Image = monkey.CapturedImage;
score.Text = (int.Parse(score.Text) + 1).ToString();
captureSound.Play();
}
}
|
实现效果:

References