<JAVA图像学习笔记>十字路口交通模拟--操作系统模拟课后小项目
项目的要求很简单:
模拟出十字路口的交通控制情况;
考虑东、西、南、北四个方向,每条路分为两个车道,每个路口设置一盏显示灯。为简单起见, 每种灯显示时间为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图像学习笔记>十字路口交通模拟--操作系统模拟课后小项目的更多相关文章
- <JAVA图像学习笔记>关于Graphics/Graphics2D以及简单的几何图像制作(一个简单钟表的实现)
题外话:正好赶上OperatingSystem的作业要做一个模拟线程/进程调度的问题,决定用JAVA实现才发现这些内容和之前学过的GUI制作是两码事儿- -b 通过学习java.swing库的Acti ...
- [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Android(java)学习笔记167:Java中操作文件的类介绍(File + IO流)
1.File类:对硬盘上的文件和目录进行操作的类. File类是文件和目录路径名抽象表现形式 构造函数: 1) File(String pathname) Creat ...
- Android(java)学习笔记110:Java中操作文件的类介绍(File + IO流)
1.File类:对硬盘上的文件和目录进行操作的类. File类是文件和目录路径名抽象表现形式 构造函数: 1) File(String pathname) Creat ...
- java多线程学习笔记——详细
一.线程类 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...
- Android(java)学习笔记233: 远程服务的应用场景(移动支付案例)
一. 移动支付: 用户需要在移动终端提交账号.密码以及金额等数据 到 远端服务器.然后远端服务器匹配这些信息,进行逻辑判断,进而完成交易,返回交易成功或失败的信息给移动终端.用户提交账号. ...
- Java IO学习笔记二
Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...
- Android(java)学习笔记176: 远程服务的应用场景(移动支付案例)
一. 移动支付: 用户需要在移动终端提交账号.密码以及金额等数据 到 远端服务器.然后远端服务器匹配这些信息,进行逻辑判断,进而完成交易,返回交易成功或失败的信息给移动终端.用户提交账号. ...
- 尚学堂JAVA基础学习笔记
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
随机推荐
- StringUtils和IOUtils工具包的使用
加载apache的工具类 <dependency> <groupId>commons-lang</groupId> <artifactId>common ...
- hibernate save update merge 区别
1.save save的对象是临时对象,首先将对象写入缓存,使其变为持久对象. save函数底层使用的是Insert语句,因此如果数据库中已经存在相同ID的记录,那么会报错 2.update upda ...
- Synchronized与ReentrantLock的区别
1.ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候 线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O ...
- 【前端阅读】——《程序员思维修炼》摘记&读后感&思维导图
前言:这是一本介绍如何用脑的书,并从思维的角度(以程序员为例),介绍如何从新手成为专家.作者带领着读者(我)共同经历一次有关认知科学.神经学.学习和行为理论的旅程,探索人类大脑令人 惊奇的工作的机制, ...
- Django和Flask的区别以及运行流程
Django: Python Web框架里比较有名当属Django,Django功能全面,它提供一站式解决方案,集成了MVT(Model-View-Template)和ORM,以及后台管理.但是缺点也 ...
- 第一个Swift程序Hello World
import Foundation print("Hello, World!") print("I am here!") var arr=["项羽&q ...
- 对国外某hotel的内网域简单渗透
Penetration Testing不单单是一个博客,更热衷于技术分享的平台. 本文将讲述对国外某一hotel的渗透测试,让更多的人安全意识得到提高,有攻才有防,防得在好,也有疏忽的地方,这就是为啥 ...
- vs code编辑器
1.vs code配置 { "editor.tabSize": 2, "workbench.startupEditor": "newUntitledF ...
- apue学习笔记(第十章 信号)
本章先对信号机制进行综述,并说明每种信号的一般用法. 信号概念 每个信号都有一个名字,这些名字都以3个字符SIG开头.在头文件<signal.h>中,信号名都被定义为正整形常量. 在某个信 ...
- 栈(C++)
简介: 限定仅在表尾进行插入或删除操作的线性表 表尾端称为栈顶(top),表头端称为栈底(bottom) 特点: 在栈中,后入栈的元素先出栈 C语言版本 用于测试的文件,以及测试结果可以去作者GitH ...