实验内容
桌子上有一只水果篮,最多可容纳两个水果,每次只能放入或者取出一个水果。爸爸专门向水果篮中放香蕉,妈妈专门向水果篮中放草莓,儿子专门等待吃水果篮中的香蕉,女儿专门等吃水果篮中的草莓。每个小孩最多连吃2个水果后,等另一个小孩吃至少一个水果才会再次开始吃水果,为此,水果篮中若连续房4个相同水果,则必须由放置该水果的人将水果拿回1个。试编程实现爸爸、妈妈、儿子、女儿四个人之间的同步。
(1)水果、水果篮均通过导入图片来实现可视化;
(2)放水果、拿水果均有动画显示,包括把水果拿到手上去放、放完空手回来等均通过的动画予以展示;
(3)执行顺序由并发控制机制决定,而非通过延时实现;
(4)要求界面美观、动作流畅。
实验代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace family
{
public partial class Form1 : Form
{
//设置信号量
public static Mutex mutex=new Mutex();//对水果篮的互斥访问
public static Semaphore banana = new Semaphore(0,2);//放、吃操作之间的同步信号量
public static Semaphore strawberry = new Semaphore(0, 2);
public static Semaphore empty = new Semaphore(2, 2);
public static Semaphore fatherput = new Semaphore(4, 4);//连放、连吃操作的同步信号量,表示可以连放多少次
public static Semaphore motherput = new Semaphore(4, 4);
public static Semaphore soneat = new Semaphore(2, 2);
public static Semaphore daughtereat = new Semaphore(2, 2);
public static int put = 0;//记录上一次放水果的人是谁
public static int eat = 0;
public static int banana_n = 0;//水果数记录
public static int strawberry_n = 0;
public static int empty_n = 2;
public static int fatherput_n = 0;//记录连放、连吃的次数
public static int motherput_n = 0;
public static int soneat_n = 0;
public static int daughtereat_n = 0;
public void Painting_ready()//动画前的准备工作
{
thefather.Parent = pictureBox1;//背景透明,图片之间尽量无遮挡
themother.Parent = pictureBox1;
theson.Parent = pictureBox1;
thedaughter.Parent = pictureBox1;
thebanana1.Parent = pictureBox1;
thebanana2.Parent = pictureBox1;
thebanana3.Parent = pictureBox1;
thebanana4.Parent = pictureBox1;
thestrawberry1.Parent = pictureBox1;
thestrawberry2.Parent = pictureBox1;
thestrawberry3.Parent = pictureBox1;
thestrawberry4.Parent = pictureBox1;
pictureBox2.Parent = pictureBox1;
pictureBox3.Parent = pictureBox1;
textBox1.Parent = pictureBox1;
textBox2.Parent = pictureBox1;
thebanana2.Visible = false;//初始化,不可见
thebanana3.Visible = false;
thebanana4.Visible = false;
thestrawberry2.Visible = false;
thestrawberry3.Visible = false;
thestrawberry4.Visible = false;
pictureBox2.Visible = false;
pictureBox3.Visible = false;
textBox1.Visible = false;
textBox2.Visible = false;
}
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
private void Form1_Load_1(object sender, EventArgs e)
{
Painting_ready();
for (int i = 0; i < 100; i++)
{
Thread father = new Thread(Father);//各进程并发
Thread mother = new Thread(Mother);
Thread son = new Thread(Son);
Thread daughter = new Thread(Daughter);
father.Start();
mother.Start();
son.Start();
daughter.Start();
}
}
public void Father()
{
mutex.WaitOne();
//水果篮已满
if (empty_n == 0)
{
mutex.ReleaseMutex();
System.Threading.Thread.Sleep(500);
}
//水果篮未满
else
{
empty.WaitOne();//申请一个水果篮中的空位
fatherput.WaitOne();//申请一个爸爸放水果的权限
Father_move();//对临界资源的访问
fatherput_n++;
//如果上一次是妈妈放的水果,就将妈妈的放水果记录全部释放
if (put == 2)
{
for (int i = 0; i < motherput_n; i++)
{
motherput.Release();//释放掉所有妈妈申请的放水果的权限,放水果记录重置
}
motherput_n = 0;
}
put = 1;
if (fatherput_n != 4)
{
banana_n++;
empty_n--;
mutex.ReleaseMutex();
banana.Release();//香蕉资源加一
Father_say();
}
else//第四次放后,需要再取回一个水果(第四次放置失败)
{
Father_take();
fatherput.Release();//退回去一个
empty.Release();
fatherput_n--;
mutex.ReleaseMutex();
}
}
}
public void Mother()
{
mutex.WaitOne();
//水果篮已满
if (empty_n == 0)
{
mutex.ReleaseMutex();
System.Threading.Thread.Sleep(500);
}
//水果篮未满
else
{
empty.WaitOne();//申请一个水果篮中的空位
motherput.WaitOne();//申请一个妈妈放水果的权限
Mother_move();//对临界资源的访问
motherput_n++;
//如果上一次是爸爸放的水果,就将爸爸的放水果记录全部释放
if (put == 1)
{
for (int i = 0; i < fatherput_n; i++)
{
fatherput.Release();//释放掉所有妈妈申请的放水果的权限,放水果记录重置
}
fatherput_n = 0;
}
put = 2;
if (motherput_n != 4)
{
strawberry_n++;
empty_n--;
mutex.ReleaseMutex();
strawberry.Release();//草莓资源加一
Mother_say();
}
else//第四次放后,需要再取回一个水果(第四次放置失败)
{
Mother_take();
motherput.Release();//退回去一个
empty.Release();
motherput_n--;
mutex.ReleaseMutex();
}
}
}
public void Son()
{
mutex.WaitOne();
//篮中无香蕉
if (banana_n == 0)
{
mutex.ReleaseMutex();
System.Threading.Thread.Sleep(500);
}
//篮中有香蕉
else
{
//已经连吃两次了
if (soneat_n == 2)
{
mutex.ReleaseMutex();
System.Threading.Thread.Sleep(500);
}
//还未连吃两次
else
{
banana.WaitOne();//申请一个香蕉
soneat.WaitOne();//申请一个儿子连吃水果的权限
Son_move();//对临界资源的访问
banana_n--;
empty_n++;
soneat_n++;
//如果上一次是女儿吃的水果,就将女儿的吃水果记录清空
if (eat == 2)
{
for (int i = 0; i < daughtereat_n; i++)
{
daughtereat.Release();//释放所有女儿申请的连吃水果的权限,连吃记录重置
}
daughtereat_n = 0;
}
eat = 1;
mutex.ReleaseMutex();
empty.Release();//水果篮空位资源加一
Son_eat();
}
}
}
public void Daughter()
{
mutex.WaitOne();
//篮中无草莓
if (strawberry_n == 0)
{
mutex.ReleaseMutex();
System.Threading.Thread.Sleep(500);
}
//篮中有草莓
else
{
//已经连吃两次了
if (daughtereat_n == 2)
{
mutex.ReleaseMutex();
System.Threading.Thread.Sleep(500);
}
//还未连吃两次
else
{
strawberry.WaitOne();//申请一个草莓
daughtereat.WaitOne();//申请一个女儿连吃水果的权限
Daughter_move();//对临界资源的访问
strawberry_n--;
empty_n++;
daughtereat_n++;
//如果上一次是儿子吃的水果,就将儿子的吃水果记录清空
if (eat == 1)
{
for (int i = 0; i < soneat_n; i++)
{
soneat.Release();//释放儿子所有申请的连吃水果权限,连吃记录重置
}
soneat_n = 0;
}
eat = 2;
mutex.ReleaseMutex();
empty.Release();//水果篮空位资源加一
Daughter_eat();
}
}
}
public void Father_move()//爸爸放香蕉
{
int x, y, bx, by;
int move_x, move_y;//步长
int n = 10;
if (thebanana2.Visible == false && thestrawberry2.Visible == false)//篮子左边无水果
{
move_x = 6;
move_y = 9;
for(int i = 0; i < n; i++)//爸爸移步到篮子边,放香蕉
{
x = thefather.Location.X + move_x;
y = thefather.Location.Y + move_y;
bx = thebanana1.Location.X + move_x;
by = thebanana1.Location.Y + move_y;
thefather.Location = new Point(x, y);
thebanana1.Location = new Point(bx, by);
Thread.Sleep(100);
}
thebanana2.Location = new Point(thebanana1.Location.X, thebanana1.Location.Y);//在篮子左边放置了一个香蕉
thebanana2.Visible = true;
thebanana1.Visible = false;
for (int i = 0; i < n; i++)//原路返回
{
x = thefather.Location.X - move_x;
y = thefather.Location.Y - move_y;
bx = thebanana1.Location.X - move_x;
by = thebanana1.Location.Y - move_y;
thefather.Location = new Point(x, y);
thebanana1.Location = new Point(bx, by);
Thread.Sleep(100);
}
thebanana1.Visible = true;
}
else if (thebanana3.Visible == false && thestrawberry3.Visible == false)//篮子右边无水果
{
move_x = 12;
move_y = 9;
for (int i = 0; i < n; i++)//移步到篮子旁边,放香蕉
{
x = thefather.Location.X + move_x;
y = thefather.Location.Y + move_y;
bx = thebanana1.Location.X + move_x;
by = thebanana1.Location.Y + move_y;
thefather.Location = new Point(x, y);
thebanana1.Location = new Point(bx, by);
Thread.Sleep(100);
}
thebanana3.Location = new Point(thebanana1.Location.X, thebanana1.Location.Y);//在篮子右边放置了一个香蕉
thebanana3.Visible = true;
thebanana1.Visible = false;
for (int i = 0; i < n; i++)//原路返回
{
x = thefather.Location.X - move_x;
y = thefather.Location.Y - move_y;
bx = thebanana1.Location.X - move_x;
by = thebanana1.Location.Y - move_y;
thefather.Location = new Point(x, y);
thebanana1.Location = new Point(bx, by);
Thread.Sleep(100);
}
thebanana1.Visible = true;
}
//Thread.Sleep(1000);
}
public void Father_take()//爸爸取回香蕉
{
thebanana1.Visible = false;
int x, y, bx, by;
int move_x=6, move_y=9;
int n = 10;
for (int i = 0; i < n; i++)
{
x = thefather.Location.X + move_x;
y = thefather.Location.Y + move_y;
bx = thebanana1.Location.X + move_x;
by = thebanana1.Location.Y + move_y;
thefather.Location = new Point(x, y);
thebanana1.Location = new Point(bx, by);
Thread.Sleep(100);
}
thebanana2.Location = new Point(thebanana1.Location.X, thebanana1.Location.Y);//把篮子左边的香蕉拿走了
thebanana1.Visible = true;
thebanana2.Visible = false;
for (int i = 0; i < n; i++)//拿着香蕉原路返回
{
x = thefather.Location.X - move_x;
y = thefather.Location.Y - move_y;
bx = thebanana1.Location.X - move_x;
by = thebanana1.Location.Y - move_y;
thefather.Location = new Point(x, y);
thebanana1.Location = new Point(bx, by);
Thread.Sleep(100);
}
}
public void Father_say()//通知儿子来吃香蕉
{
textBox1.Visible = true;
Thread.Sleep(1000);
textBox1.Visible = false;
}
public void Mother_move()//妈妈放草莓
{
int x, y, bx, by;
int move_x, move_y;//步长
int n = 10;
if (thebanana2.Visible == false && thestrawberry2.Visible == false)//盘子左边无水果
{
move_x = -10;
move_y = 9;
for (int i = 0; i < n; i++)//移步到盘子旁边,放草莓
{
x = themother.Location.X + move_x;
y = themother.Location.Y + move_y;
bx = thestrawberry1.Location.X + move_x;
by = thestrawberry1.Location.Y + move_y;
themother.Location = new Point(x, y);
thestrawberry1.Location = new Point(bx, by);
Thread.Sleep(100);
}
thestrawberry2.Location = new Point(thestrawberry1.Location.X, thestrawberry1.Location.Y);//在篮子左边放置了一个香蕉
thestrawberry2.Visible = true;
thestrawberry1.Visible = false;
for (int i = 0; i < n; i++)//原路返回
{
x = themother.Location.X - move_x;
y = themother.Location.Y - move_y;
bx = thestrawberry1.Location.X - move_x;
by = thestrawberry1.Location.Y - move_y;
themother.Location = new Point(x, y);
thestrawberry1.Location = new Point(bx, by);
Thread.Sleep(100);
}
thestrawberry1.Visible = true;
}
else if (thebanana3.Visible == false && thestrawberry3.Visible == false)//篮子右边无水果
{
move_x = -4;
move_y = 9;
for (int i = 0; i < n; i++)//移步到篮子旁边,放草莓
{
x = themother.Location.X + move_x;
y = themother.Location.Y + move_y;
bx = thestrawberry1.Location.X + move_x;
by = thestrawberry1.Location.Y + move_y;
themother.Location = new Point(x, y);
thestrawberry1.Location = new Point(bx, by);
Thread.Sleep(100);
}
thestrawberry3.Location = new Point(thestrawberry1.Location.X, thestrawberry1.Location.Y);//在篮子右边放置了一个草莓
thestrawberry3.Visible = true;
thestrawberry1.Visible = false;
for (int i = 0; i < n; i++)//妈妈原路返回
{
x = themother.Location.X - move_x;
y = themother.Location.Y - move_y;
bx = thestrawberry1.Location.X - move_x;
by = thestrawberry1.Location.Y - move_y;
themother.Location = new Point(x, y);
thestrawberry1.Location = new Point(bx, by);
Thread.Sleep(100);
}
thestrawberry1.Visible = true;
}
//Thread.Sleep(1000);
}
public void Mother_take()//妈妈取回草莓
{
thestrawberry1.Visible = false;
int x, y, bx, by;
int move_x = -4, move_y = 9;
int n = 10;
for (int i = 0; i < n; i++)
{
x = themother.Location.X + move_x;
y = themother.Location.Y + move_y;
bx = thestrawberry1.Location.X + move_x;
by = thestrawberry1.Location.Y + move_y;
themother.Location = new Point(x, y);
thestrawberry1.Location = new Point(bx, by);
Thread.Sleep(100);
}
thestrawberry3.Location = new Point(thestrawberry1.Location.X, thestrawberry1.Location.Y);//把篮子右边的草莓拿走了
thestrawberry1.Visible = true;
thestrawberry3.Visible = false;
for (int i = 0; i < n; i++)//拿着草莓原路返回
{
x = themother.Location.X - move_x;
y = themother.Location.Y - move_y;
bx = thestrawberry1.Location.X - move_x;
by = thestrawberry1.Location.Y - move_y;
themother.Location = new Point(x, y);
thestrawberry1.Location = new Point(bx, by);
Thread.Sleep(100);
}
}
public void Mother_say()//通知女儿来吃草莓
{
textBox2.Visible = true;
Thread.Sleep(1000);
textBox2.Visible = false;
}
public void Son_move()//儿子取香蕉
{
int x, y, bx, by;
int move_x, move_y;//步长
int n = 10;
pictureBox2.Visible = false;
thebanana4.Visible = false;
if (thebanana2.Visible == true)//篮子左边有香蕉
{
move_x = 6;
move_y = -9;
for (int i = 0; i < n; i++)
{
x = theson.Location.X + move_x;
y = theson.Location.Y + move_y;
bx = thebanana4.Location.X + move_x;
by = thebanana4.Location.Y + move_y;
theson.Location = new Point(x, y);
thebanana4.Location = new Point(bx, by);
Thread.Sleep(100);
}
thebanana2.Location = new Point(thebanana4.Location.X, thebanana4.Location.Y);//把篮子左边的香蕉拿走了
thebanana4.Visible = true;
thebanana2.Visible = false;
for (int i = 0; i < n; i++)//拿着香蕉原路返回
{
x = theson.Location.X - move_x;
y = theson.Location.Y - move_y;
bx = thebanana4.Location.X - move_x;
by = thebanana4.Location.Y - move_y;
theson.Location = new Point(x, y);
thebanana4.Location = new Point(bx, by);
Thread.Sleep(100);
}
}
else if (thebanana3.Visible == true)//篮子右边有香蕉
{
move_x = 12;
move_y = -9;
for (int i = 0; i < n; i++)
{
x = theson.Location.X + move_x;
y = theson.Location.Y + move_y;
bx = thebanana4.Location.X + move_x;
by = thebanana4.Location.Y + move_y;
theson.Location = new Point(x, y);
thebanana4.Location = new Point(bx, by);
Thread.Sleep(100);
}
thebanana3.Location = new Point(thebanana4.Location.X, thebanana4.Location.Y);//把篮子右边的香蕉拿走了
thebanana4.Visible = true;
thebanana3.Visible = false;
for (int i = 0; i < n; i++)//拿着香蕉原路返回
{
x = theson.Location.X - move_x;
y = theson.Location.Y - move_y;
bx = thebanana4.Location.X - move_x;
by = thebanana4.Location.Y - move_y;
theson.Location = new Point(x, y);
thebanana4.Location = new Point(bx, by);
Thread.Sleep(100);
}
}
}
public void Son_eat()//儿子吃香蕉
{
pictureBox2.Visible = true;//吃香蕉
Thread.Sleep(1000);
thebanana4.Visible = false;
pictureBox2.Visible = false;
}
public void Daughter_move()//女儿取草莓
{
int x, y, bx, by;
int move_x, move_y;//步长
int n = 10;
pictureBox3.Visible = false;
thestrawberry4.Visible = false;
if (thestrawberry2.Visible == true)//篮子左边有草莓
{
move_x = -10;
move_y = -9;
for (int i = 0; i < n; i++)
{
x = thedaughter.Location.X + move_x;
y = thedaughter.Location.Y + move_y;
bx = thestrawberry4.Location.X + move_x;
by = thestrawberry4.Location.Y + move_y;
thedaughter.Location = new Point(x, y);
thestrawberry4.Location = new Point(bx, by);
Thread.Sleep(100);
}
thestrawberry2.Location = new Point(thestrawberry4.Location.X, thestrawberry4.Location.Y);//把篮子左边的草莓拿走了
thestrawberry4.Visible = true;
thestrawberry2.Visible = false;
for (int i = 0; i < n; i++)//拿着草莓原路返回
{
x = thedaughter.Location.X - move_x;
y = thedaughter.Location.Y - move_y;
bx = thestrawberry4.Location.X - move_x;
by = thestrawberry4.Location.Y - move_y;
thedaughter.Location = new Point(x, y);
thestrawberry4.Location = new Point(bx, by);
Thread.Sleep(100);
}
}
else if (thestrawberry3.Visible == true)//篮子右边有草莓
{
move_x = -4;
move_y = -9;
for (int i = 0; i < n; i++)
{
x = thedaughter.Location.X + move_x;
y = thedaughter.Location.Y + move_y;
bx = thestrawberry4.Location.X + move_x;
by = thestrawberry4.Location.Y + move_y;
thedaughter.Location = new Point(x, y);
thestrawberry4.Location = new Point(bx, by);
Thread.Sleep(100);
}
thestrawberry3.Location = new Point(thestrawberry4.Location.X, thestrawberry4.Location.Y);//把篮子右边的草莓拿走了
thestrawberry4.Visible = true;
thestrawberry3.Visible = false;
for (int i = 0; i < n; i++)
{
x = thedaughter.Location.X - move_x;
y = thedaughter.Location.Y - move_y;
bx = thestrawberry4.Location.X - move_x;
by = thestrawberry4.Location.Y - move_y;
thedaughter.Location = new Point(x, y);
thestrawberry4.Location = new Point(bx, by);
Thread.Sleep(100);
}
}
}
public void Daughter_eat()//女儿吃草莓
{
pictureBox3.Visible = true;//吃草莓
Thread.Sleep(1000);
thestrawberry4.Visible = false;
pictureBox3.Visible = false;
}
private void Stop_Click(object sender, EventArgs e)
{
Environment.Exit(0);
}
}
}
运行结果