项目的要求很简单:

  模拟出十字路口的交通控制情况;

  考虑东、西、南、北四个方向,每条路分为两个车道,每个路口设置一盏显示灯。为简单起见, 每种灯显示时间为8秒。

  当东西(或南北)方向红灯时,所有车辆(除了消防车、救护车、警车)均排队等待,当东西(或南北)方向绿灯时,所有车辆按序行驶(不准超车)。

制作这个小框体程序我选择的平台是JAVA,实现结果效果图如下所示:

  首先分析整个项目题目上的要求,在十字路口上通过的车辆可以抽象为两类:普通车辆和特殊车辆(包括警车,消防车,救护车等),所谓普通的车辆和特殊种类的车辆之间的差别是是否需要在红绿灯路口之前进行等待操作,特殊车辆享有优先权并且可以直接通过路口,而普通的车辆必须严格遵守交通规则。

由于整个题目的环境假定为交通十字路口,那么有如下几个隐式的条件要求:

(1)不失一般性的,任意车辆在前方有车辆在等待的情况下必须也进行等待操作。

(2)车辆与车辆之间无论是正面还是侧面之间都不允许发生碰撞且最好保持一个“安全距离”,换句话讲,一个严格的要求是车辆之间不允许发生重叠。

(3)红绿灯按照一个既定的规律进行变换,控制普通车辆的行进与停止

(4)车辆的次序或者方向要实现随机分配,即整个路口可以处理各种车辆位置的情况

在这个项目之中我们不妨假设车辆的行进路径只有单方向,即不会出现车辆转弯的状况,这样一来就大大简化了整个项目的难度。所以因为所有车辆都是直行,所以在整个十字路口的范围内我们需要一定数量的信号来处理路口内部车辆行进的分配问题,其次是红绿灯的分配也需要一个信号量来处理车辆和红绿灯变换之间的关系。

如右图所示,MyMutex.center是表示整个十字路口正中央的信号辆所代表的位置,东西南北是个方向分别在这个信号量表示中为上下左右四个方向,每个方向有4条道路,其中的道路两两并行,每组方向相反。举个具体的例子就是(车辆靠右侧通行)北(上)边最右侧的车道驶来的车辆与西(左)边最左侧的车道驶来的车辆可能会在图中的MyMutex.center[0][0]处相遇,在相遇的同时只有一辆车辆允许通行,若已经有车辆通过该交汇处,那么已经进入并且占有信号量的车

辆优先通过,反之亦然。

在上述的条件的约束之下,我们决定使用可视化界面来实现整个十字路口车辆分配的问题。

不妨把车辆抽象成为矩形,利用java.awt库下的类做出两个模拟的车辆的模样,分别代表特殊车辆和普通车辆。(特殊车辆一律用警车图案来概括)

那么车辆行驶的过程就是车辆图案的平移过程,经过草图设计我们暂定车辆LOGO的大小为30*50(道路的宽度为50)也就是说会在车辆的两侧个留出10pixel的矩形作为所谓安全距离,整个车辆的平移的过程经过测试评估最终确定为每0.2s移动10像素,会留下较好的动画效果和观察准度。

接下来是实现整个界面底层的环节:

(1)所有车辆模型的实质是java.awt库内的矩形和线条,车辆模型的移动的实质就是线条和矩形的移动过程,但是在移动的过程之中,首先需要图案进行旋转处理以使之对应东西走向上的车辆,为了避免反复重复计算出每个线条的位置,我们做出8个容器来存储每个方向上每个车道上的车辆初始线条位置,从次之后的每次绘制只需要在容器中取出每个线条再对之进行比较简单的平移操作即可。

(2)我们整个界面的动画是通过不断调用JComponent类的repaint()方法来实现的,所以我们首先需要重写paint()方法,从P/V操作的角度考虑,对于每一条路径上的车辆可能会处理的情况如下所示:

(3)整个界面的宏观角度来看,整个程序的流程过程图如下所示:

(4)根据上述设计,个人感觉java中的synchronized关键字不太适合这个项目,因为直接使用synchronized很有使得两个同时相碰的车辆发生死锁现象,所以我的解决方法是根据java代码执行的特点,将八个线程的运行run() 函数内容直接依次排序,实质上是相当于给八个线程设定了默认的优先级这样一来就解决了死锁的现象。

代码分享: ## 由于作业Deadline还没有到我就先发布一些关键的绘制部分的代码块,等到Deadline一过就把源码全部展示出来 ##

(1)paint()函数重载后的写法

    public void paint(Graphics g){
super.paint(g);
Graphics2D g2=(Graphics2D)g;
/////Traffic Lights
g2.setPaint(Color.black);
g2.fill(signalpane);
g2.setPaint(Color.red.darker());
g2.fill(redsignal);
g2.setPaint(Color.green.darker());
g2.fill(greensignal); /////PaintRoad
g2.setPaint(Color.gray.brighter());
Rectangle2D roadh=new Rectangle2D.Float(250,0,200,700);
Rectangle2D roadv=new Rectangle2D.Float(0,250,700,200);
g2.fill(roadh);
g2.fill(roadv); ///// /////Graphics Defination
g2.setPaint(Color.black);
g.drawLine(250, 0, 250, 700);
g.drawLine(350, 0, 350, 700);
g.drawLine(450, 0, 450, 700);
g.drawLine(0, 250, 700, 250);
g.drawLine(0, 350, 700, 350);
g.drawLine(0,450,700, 450);
g2.setPaint(Color.gray.darker());
g.drawLine(300,0,300,700);
g.drawLine(400,0,400,700);
g.drawLine(0,300,700,300);
g.drawLine(0,400,700,400);
Rectangle2D centerroad=new Rectangle2D.Float(250,250,200,200);
///////////////////////Road Drawing
///////////////////////Color can be attached
g2.setPaint(Color.gray.brighter());
g2.fill(centerroad);
g2.setPaint(Color.black);
g2.draw(centerroad);
////////////////////////Specail Car Outline painting
////////////////////////Located from 500,20 size 30,50
///////////////////////Combined by llright,rlight,specialCarOut,specialCarIn,specialCarLightLeft,specialCarLightRight
g2.fill(specialCarOut);
g2.setPaint(Color.gray);
g2.draw(specialCarLightLeft);
g2.draw(specialCarLightRight);
g2.draw(specialCarOut);
g2.setPaint(Color.white);
g2.fill(specialCarIn);
g2.setPaint(Color.red);
g2.fill(specialCarLightLeft);
g2.setPaint(Color.blue);
g2.fill(specialCarLightRight);
g2.setPaint(Color.yellow);
g2.fill(sllight);
g2.fill(srlight);
//////////////////////////////////////Normal Car Outline Painting
//////////////////////////////////////Located from 550,20 size 30,50 g2.setPaint(Color.gray);
g2.draw(normalCarIn);
g2.draw(normalCarOut);
g2.setPaint(Color.red);
g2.fill(normalCarOut);
g2.setPaint(Color.magenta);
g2.fill(normalCarIn);
g2.setPaint(Color.yellow);
g2.fill(nllight);
g2.fill(nrlight);
//////////////////
/////////////////Painting Finished
/////////////////For switch to change
if(bLight==true){
g2.setPaint(Color.green.brighter());
g2.fill(greensignal);
g2.setPaint(Color.black);
g2.fill(redsignal);
}else{
g2.setPaint(Color.black);
g2.fill(greensignal);
g2.setPaint(Color.red.brighter());
g2.fill(redsignal);
} ////Testing Field ////nn
Iterator iter=northCars.iterator();
while(iter.hasNext()){
Car c=(Car)iter.next();
paintCar(g2,c);
}
////sn
iter=snorthCars.iterator();
while(iter.hasNext()){
Car c=(Car)iter.next();
paintCar(g2,c);
}
////ns
iter=southCars.iterator();
while(iter.hasNext()){
Car c=(Car)iter.next();
paintCar(g2,c);
}
////ss
iter=ssouthCars.iterator();
while(iter.hasNext()){
Car c=(Car)iter.next();
paintCar(g2,c);
}
///ne
iter=eastCars.iterator();
while(iter.hasNext()){
Car c=(Car)iter.next();
paintCar(g2,c);
}
////se
iter=seastCars.iterator();
while(iter.hasNext()){
Car c=(Car)iter.next();
paintCar(g2,c);
}
/////nw
iter=westCars.iterator();
while(iter.hasNext()){
Car c=(Car)iter.next();
paintCar(g2,c);
}
////sw
iter=swestCars.iterator();
while(iter.hasNext()){
Car c=(Car)iter.next();
paintCar(g2,c);
}
///////////////////Testtttting!!!!!! ///////////////////
}

(2)线条/图案容器

public static Vector<Car> northCars=new Vector<>();
public static Vector<Car> southCars=new Vector<>();
public static Vector<Car> eastCars=new Vector<>();
public static Vector<Car> westCars=new Vector<>();
public static Vector<Car> snorthCars=new Vector<>();
public static Vector<Car> ssouthCars=new Vector<>();
public static Vector<Car> seastCars=new Vector<>();
public static Vector<Car> swestCars=new Vector<>();
public static boolean bLight=true;

(3)车辆坐标容器

    protected static Vector<Shape> northshape=new Vector<>();
protected static Vector<Shape> southshape=new Vector<>();
protected static Vector<Shape> eastshape=new Vector<>();
protected static Vector<Shape> westshape=new Vector<>();
protected static Vector<Shape> snorthshape=new Vector<>();
protected static Vector<Shape> ssouthshape=new Vector<>();
protected static Vector<Shape> seastshape=new Vector<>();
protected static Vector<Shape> swestshape=new Vector<>();

(4)actionPerformed接口方法实现

    public void actionPerformed(ActionEvent e){
Object source=e.getSource();
if(source==timer){
Iterator it;
////nn
it=northCars.iterator();
while(it.hasNext()){
Car car=(Car)it.next();
if(car.y==700)it.remove();
if(car.y==250){
if(bLight==true)continue;///Stop
//}else if(car.y==250){
if(MyMutex.center[0][0]==0)MyMutex.center[0][0]--;else continue;///Stop
}else if(car.y==340){
MyMutex.center[0][0]++;
}else if(car.y==300){
if(MyMutex.center[1][0]==0)MyMutex.center[1][0]--;else continue;///Stop
}else if(car.y==390){
MyMutex.center[1][0]++;
}else if(car.y==350){
if(MyMutex.center[2][0]==0)MyMutex.center[2][0]--;else continue;
}else if(car.y==440){
MyMutex.center[2][0]++;
}else if(car.y==400){
if(MyMutex.center[3][0]==0)MyMutex.center[3][0]--;else continue;
}else if(car.y==490){
MyMutex.center[3][0]++;
}
car.y+=10;
}
///////ns
it=snorthCars.iterator();
while(it.hasNext()){
Car car=(Car)it.next();
if(car.y==700)it.remove();
if(car.y==250){
//if(bLight==true)continue;///Stop
//}else if(car.y==250){
if(MyMutex.center[0][1]==0)MyMutex.center[0][1]--;else continue;///Stop
}else if(car.y==340){
MyMutex.center[0][1]++;
}else if(car.y==300){
if(MyMutex.center[1][1]==0)MyMutex.center[1][1]--;else continue;///Stop
}else if(car.y==390){
MyMutex.center[1][1]++;
}else if(car.y==350){
if(MyMutex.center[2][1]==0)MyMutex.center[2][1]--;else continue;
}else if(car.y==440){
MyMutex.center[2][1]++;
}else if(car.y==400){
if(MyMutex.center[3][1]==0)MyMutex.center[3][1]--;else continue;
}else if(car.y==490){
MyMutex.center[3][1]++;
}
car.y+=10;
}
/////sn
it=southCars.iterator();
while(it.hasNext()){
Car car=(Car)it.next();
if(car.y==0)it.remove();
if(car.y==450){
if(bLight==true)continue;///Stop
//}else if(car.y==450){
if(MyMutex.center[3][3]==0)MyMutex.center[3][3]--;else continue;///Stop
}else if(car.y==360){
MyMutex.center[3][3]++;
}else if(car.y==400){
if(MyMutex.center[2][3]==0)MyMutex.center[2][3]--;else continue;///Stop
}else if(car.y==310){
MyMutex.center[2][3]++;
}else if(car.y==350){
if(MyMutex.center[1][3]==0)MyMutex.center[1][3]--;else continue;
}else if(car.y==260){
MyMutex.center[1][3]++;
}else if(car.y==300){
if(MyMutex.center[0][3]==0)MyMutex.center[0][3]--;else continue;
}else if(car.y==210){
MyMutex.center[0][3]++;
}
car.y-=10;
}
////ss
it=ssouthCars.iterator();
while(it.hasNext()){
Car car=(Car)it.next();
if(car.y==0)it.remove();
if(car.y==450){
//if(bLight==true)continue;///Stop
//}else if(car.y==450){
if(MyMutex.center[3][2]==0)MyMutex.center[3][2]--;else continue;///Stop
}else if(car.y==360){
MyMutex.center[3][2]++;
}else if(car.y==400){
if(MyMutex.center[2][2]==0)MyMutex.center[2][2]--;else continue;///Stop
}else if(car.y==310){
MyMutex.center[2][2]++;
}else if(car.y==350){
if(MyMutex.center[1][2]==0)MyMutex.center[1][2]--;else continue;
}else if(car.y==260){
MyMutex.center[1][2]++;
}else if(car.y==300){
if(MyMutex.center[0][2]==0)MyMutex.center[0][2]--;else continue;
}else if(car.y==210){
MyMutex.center[0][2]++;
}
car.y-=10;
}
///ne
it=eastCars.iterator();
while(it.hasNext()){
Car car=(Car)it.next();
if(car.x==0)it.remove();
if(car.x==450){
if(bLight==false)continue;///Stop
//}else if(car.x==450){
if(MyMutex.center[0][3]==0)MyMutex.center[0][3]--;else continue;///Stop
}else if(car.x==360){
MyMutex.center[0][3]++;
}else if(car.x==400){
if(MyMutex.center[0][2]==0)MyMutex.center[0][2]--;else continue;///Stop
}else if(car.x==310){
MyMutex.center[0][2]++;
}else if(car.x==350){
if(MyMutex.center[0][1]==0)MyMutex.center[0][1]--;else continue;
}else if(car.x==260){
MyMutex.center[0][1]++;
}else if(car.x==300){
if(MyMutex.center[0][0]==0)MyMutex.center[0][0]--;else continue;
}else if(car.x==210){
MyMutex.center[0][0]++;
}
car.x-=10;
}
//se
it=seastCars.iterator();
while(it.hasNext()){
Car car=(Car)it.next();
if(car.x==0)it.remove();
if(car.x==450){
//if(bLight==false)continue;///Stop
//}else if(car.x==450){
if(MyMutex.center[1][3]==0)MyMutex.center[1][3]--;else continue;///Stop
}else if(car.x==360){
MyMutex.center[1][3]++;
}else if(car.x==400){
if(MyMutex.center[1][2]==0)MyMutex.center[1][2]--;else continue;///Stop
}else if(car.x==310){
MyMutex.center[1][2]++;
}else if(car.x==350){
if(MyMutex.center[1][1]==0)MyMutex.center[1][1]--;else continue;
}else if(car.x==260){
MyMutex.center[1][1]++;
}else if(car.x==300){
if(MyMutex.center[1][0]==0)MyMutex.center[1][0]--;else continue;
}else if(car.x==210){
MyMutex.center[1][0]++;
}
car.x-=10;
}
//nw
it=westCars.iterator();
while(it.hasNext()){
Car car=(Car)it.next();
if(car.x==700)it.remove();
if(car.x==250){
if(bLight==false)continue;///Stop
//}else if(car.x==250){
if(MyMutex.center[3][0]==0)MyMutex.center[3][0]--;else continue;///Stop
}else if(car.x==340){
MyMutex.center[3][0]++;
}else if(car.x==300){
if(MyMutex.center[3][1]==0)MyMutex.center[3][1]--;else continue;///Stop
}else if(car.x==390){
MyMutex.center[3][1]++;
}else if(car.x==350){
if(MyMutex.center[3][2]==0)MyMutex.center[3][2]--;else continue;
}else if(car.x==440){
MyMutex.center[3][2]++;
}else if(car.x==400){
if(MyMutex.center[3][3]==0)MyMutex.center[3][3]--;else continue;
}else if(car.x==490){
MyMutex.center[3][3]++;
}
car.x+=10;
}
///sw
it=swestCars.iterator();
while(it.hasNext()){
Car car=(Car)it.next();
if(car.x==700)it.remove();
if(car.x==250){
//if(bLight==false)continue;///Stop
//}else if(car.x==250){
if(MyMutex.center[2][0]==0)MyMutex.center[2][0]--;else continue;///Stop
}else if(car.x==340){
MyMutex.center[2][0]++;
}else if(car.x==300){
if(MyMutex.center[2][1]==0)MyMutex.center[2][1]--;else continue;///Stop
}else if(car.x==390){
MyMutex.center[2][1]++;
}else if(car.x==350){
if(MyMutex.center[2][2]==0)MyMutex.center[2][2]--;else continue;
}else if(car.x==440){
MyMutex.center[2][2]++;
}else if(car.x==400){
if(MyMutex.center[2][3]==0)MyMutex.center[2][3]--;else continue;
}else if(car.x==490){
MyMutex.center[2][3]++;
}
car.x+=10;
}
adjust();
repaint();
}else if(source==timerLight){
bLight=!bLight;
if(bLight)hint.setText("Now Right-Left Road is Accessible!");
else hint.setText("Now Up-Down Road is Accessible!");
}else if(source==testTimer){
//northCars.add(new Car(0,0,260,50));
//snorthCars.add(new Car(0,1,310,50));
//southCars.add(new Car(1,0,440,650));
//ssouthCars.add(new Car(1,1,410,650));
//eastCars.add(new Car(2,0,650,260));
//seastCars.add(new Car(2,1,650,310));
//westCars.add(new Car(3,0,50,440));
//swestCars.add(new Car(3,1,50,410));
}else if(source==westn){
westCars.add(new Car(3,0,50,440));
}else if(source==wests){
swestCars.add(new Car(3,1,50,410));
}else if(source==eastn){
eastCars.add(new Car(2,0,650,260));
}else if(source==easts){
seastCars.add(new Car(2,1,650,310));
}else if(source==northn){
northCars.add(new Car(0,0,260,50));
}else if(source==norths){
snorthCars.add(new Car(0,1,310,50));
}else if(source==southn){
southCars.add(new Car(1,0,440,650));
}else if(source==souths){
ssouthCars.add(new Car(1,1,410,650));
} /////Swtich Table For Source Handling }

Tips:如果有任何问题欢迎联系我或者留下评论

<JAVA图像学习笔记>十字路口交通模拟--操作系统模拟课后小项目的更多相关文章

  1. <JAVA图像学习笔记>关于Graphics/Graphics2D以及简单的几何图像制作(一个简单钟表的实现)

    题外话:正好赶上OperatingSystem的作业要做一个模拟线程/进程调度的问题,决定用JAVA实现才发现这些内容和之前学过的GUI制作是两码事儿- -b 通过学习java.swing库的Acti ...

  2. [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  3. Android(java)学习笔记167:Java中操作文件的类介绍(File + IO流)

    1.File类:对硬盘上的文件和目录进行操作的类.    File类是文件和目录路径名抽象表现形式  构造函数:        1) File(String pathname)       Creat ...

  4. Android(java)学习笔记110:Java中操作文件的类介绍(File + IO流)

    1.File类:对硬盘上的文件和目录进行操作的类.    File类是文件和目录路径名抽象表现形式  构造函数:        1) File(String pathname)       Creat ...

  5. java多线程学习笔记——详细

    一.线程类  1.新建状态(New):新创建了一个线程对象.        2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...

  6. Android(java)学习笔记233: 远程服务的应用场景(移动支付案例)

    一. 移动支付:       用户需要在移动终端提交账号.密码以及金额等数据 到 远端服务器.然后远端服务器匹配这些信息,进行逻辑判断,进而完成交易,返回交易成功或失败的信息给移动终端.用户提交账号. ...

  7. Java IO学习笔记二

    Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...

  8. Android(java)学习笔记176: 远程服务的应用场景(移动支付案例)

    一. 移动支付:       用户需要在移动终端提交账号.密码以及金额等数据 到 远端服务器.然后远端服务器匹配这些信息,进行逻辑判断,进而完成交易,返回交易成功或失败的信息给移动终端.用户提交账号. ...

  9. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

随机推荐

  1. Windows API 教程(七) hook 钩子监听

    茵蒂克丝 如何创建一个窗口 手动创建窗口的流程 实际代码 安装钩子 (Install hook) 钩子简介 SetWindowsHookEx 函数 设置监听[键盘]消息 设置监听[鼠标]消息 如何创建 ...

  2. Linux学习之十-Linux系统时间

    Linux系统时间 1.date命令用于查看以及修改Linux系统的时间,关于date命令的详细帮助文档如下 [root@localhost ~]# date --help Usage: date [ ...

  3. Linux内核——内存管理

    内存管理 页 内核把物理页作为内存管理的基本单位.内存管理单元(MMU,管理内存并把虚拟地址转换为物理地址)通常以页为单位进行处理.MMU以页大小为单位来管理系统中的页表. 从虚拟内存的角度看,页就是 ...

  4. CodeForces - 344B Simple Molecules (模拟题)

    CodeForces - 344B id=46665" style="color:blue; text-decoration:none">Simple Molecu ...

  5. openssl之BIO系列之22---Cipher类型的BIO

    Cipher类型BIO ---依据openssl doc\crypto\bio_f_cipher.pod翻译和自己的理解写成 (作者:DragonKing, Mail: wzhah@263.net , ...

  6. 简单记录一次ORA-00600: internal error code, arguments: [2662]

    接上一个,REDO报错搞定后OPEN数据库时又报错ORA-00600: internal error code, arguments: [2662]. 原因是_ALLOW_RESETLOGS_CORR ...

  7. mixare的measureText方法在频繁调用时抛出“referencetable overflow max 1024”的解决方式

    这几天在搞基于位置的AR应用,採用了github上两款开源项目: mixare android-argument-reality-framework 这两个项目实现机制大致同样.我选取的是androi ...

  8. ORA-01591错误的原因和处理方法

    http://blog.csdn.net/tclcaojun/article/details/6777022错误代码:ORA-01591 错误原因:使用了分布式事务,造成这个问题的原因很多时候都是由于 ...

  9. Java系统中如何拆分同步和异步

    很多开发人员说,将应用程序切换到异步处理很复杂.因为他们有一个天然需要同步通信的Web应用程序.在这篇文章中,我想介绍一种方法来达到异步通信的目的:使用一些众所周知的库和工具来设计他们的系统. 下面的 ...

  10. jQuery Validate(一)

    jQuery Validate 插件为表单提供了强大的验证功能,让客户端表单验证变得更简单. 但是在学习的过程中,我也遇到了疑惑,网上的很多例子貌似都是依赖jquery.metadata.js这个库, ...