项目的要求很简单:
模拟出十字路口的交通控制情况;
考虑东、西、南、北四个方向,每条路分为两个车道,每个路口设置一盏显示灯。为简单起见, 每种灯显示时间为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:如果有任何问题欢迎联系我或者留下评论