专业课程设计I报告 - B09040208

更新时间:2024-05-10 15:38:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

专业课程设计I报告

(2011 / 2012 学年 第 二 学期)

题目1: 进程的同步与互斥

题目2: 计算机图形动画

专 业 计算机科学与技术 学 生 姓 名 黄金花 班 级 学 号 B09040208 指 导 教 师 黄海平 指 导 单 位 计算机学院 日 期 2012.4.16-4.26

指导教师成绩评定表

学生姓名 评分内容 平时成绩 班级学号 评分标准 认真对待课程设计,遵守实验室规定,上机不迟到早退,不做和设计无关的事 设计的科学、合理性 功能丰富、符合题目要求 设计成果 界面友好、外观漂亮、大方 程序功能执行的正确性 程序算法执行的效能 设计报告正确合理、反映系统设计流程 设计报告 文档内容详实程度 文档格式规范、排版美观 简练、准确阐述设计内容,能准确有条理回答各种问题,系统演示顺利。 专业 优秀 计算机科学与技术 良好 中等 差 √ 验收答辩 评分等级 指导教师 简短评语 该同学出勤率(满勤、较高、一般,较低),学习态度(端正、较端正、一般、较差),演示程序(未)达到了(基本要求、提高要求1或/和2),撰写报告格式(规范、一般)、表述(清晰、一般、不清楚),圆满(较好、基本)完成了课题任务。(可选:尚存在??缺陷。) 指导教师签名 备注

日期 2012-4-30 评分等级有五种:优秀、良好、中等、及格、不及格

教师对学生的项目评分——进程的同步与互斥

一、 课题内容和要求

1、课题内容

题目:教师对学生的项目评分——进程的同步与互斥

内容:在一个班上有S个学生。每个学生都要做一个项目,每一个项目由K个老师一起评分。总共有M个老师。每个老师最多给N个项目评分。其中,S*K<=M*N。 在项目结束后,老师们提供T分钟用来检查学生们的项目。检查每一个学生的项目需要用时D分钟。其中,T>D。每一个学生的项目由K个老师共同来检查。在

T分钟的时间段内,学生可以在任何时间进入教室(random),除了在最后的D分钟内。所有的老师一直保持工作状态直到他检查完N个项目或者是T分钟过去后。

T分钟过去后,所有的老师和同学都必须离开教室。另外,在T分钟结束前的D分钟内(即在最后的D分钟内),如果有任何老师或者是学生都处在没有任务的状态下,都必须离开教室,因为已经没有时间让他完成任务了(因为一个项目检查的时间是整整D分钟)。 具体过程:

当一个学生进入教室后,他立即开始找K个没有任务的老师(一次找一个老师,假如没有空闲的老师,则等到有老师为止),找齐K个老师之后给老师检查,然后离开教室。刚开始每一个老师都是处于空闲状态直到他被学生找到,被学生找到后只能等待,直到学生找齐K个老师(在等待学生找其他老师的时间里,他是不能接受其他同学检查作业的请求的),当学生找齐K个老师后,老师们执行完检查任务,然后重新变成空闲状态。每个老师在总共检查了N个学生的作业后,离开教室。 2.课程要求

用一个程序来模拟上面描述的作业检查过程。每一个学生和每一个老师应该用不同的线程来完成。可以选用C、C++和Java作为开发语言,但是考虑到专业课程设计I的实验大纲,请尽可能使用Java语言。 提高要求:

(1) 考虑到跨平台的特性,请尽量使用posix线程标准(采用该标准有额外的加分);

(2) 实现良好的图形用户界面;

(3) 在程序演示过程中能清晰的展示多个学生线程和多个老师线程的同步和互斥流程。

二、需求和思路分析

该课题主要考察操作系统中PV操作知识点,涉及到多进程管理和死锁的相关知识。

1.为了实现老师与学生能协调进行下去,可以采用多线程,这里可以使用三种线程:总线程,老师线程,学生线程。

(1).总线程:主线程作为主类,实现对老师线程和学生线程的调用 产生老师线程,并激活;

产生随机数来定义每个学生进入的时间; 产生学生线程;并按上面产生的时间激活; 时间结束,程序结束; (2).老师线程:

(0) 老师进入教室;

(1) 在教室中空闲;

(2) 直到被一个学生选择后等待(所有K个老师聚集); (3) 等待结束项目检查开始; (4) 做D分钟的项目检查;

(5) N次检查完毕或者T分钟时间到,离开教室。否则回到(1) (3).学生线程: (0)进入教室

(1) 选择一个进入的时间(random()%(T-D))minutes ; (2) 进入教室;

(3) 选择K个空闲的老师,若找不齐,则等待; (4) 找齐后,做D分钟的检查; (5) 检查完毕离开教室。

2.在此题目要求中涉及PV操作的有学生选择老师阶段,在学生选择老师时刻,可能出现学生甲,学生乙同时发现有K个老师,于是每个人占有了一部分但又不够,且不放开资源,造成死锁的现象,对于这一问题可以设定,只要有一个学生在选择老师时,其他的学生都不可以选,一个人选完了,另外一个人才可以再选,这样就避免了死锁的发生;

还有一个同步和互斥的问题,教室每次只可以进去或出来一个人,即学生、老师不可以同时进入教室,离开教室。这可以通过相关修饰符来解决; 以上两个问题皆可以用修饰符synchronized来解决。

如果线程进入,则得到对象锁,那么别的线程在该类所有对象上的任何操作都不能进行。

3.注意事项

(1) 在剩余时间小于D时,一个已创建的学生线程只能执行第(5)步,不能再创建新的学生线程;

(2) 在剩余时间小于D时,一个老师进程只能在执行(3)—(4)步或者直接执行第(5)步;

(3) 对于所有合理的S, M, K, N, T, D数值(这些数必须都是正整数并且满足条件:S*K<=M*N and T>D),你的程序都能够运行成功;

(4) 你的程序对所有的时间安排策略都必须运行成功。例如不管线程的相对速度,例如要把握好sleep的毫秒数;

(5) 在每一个线程的生命周期内,每一步都要有一个合理的说明信息,来表明这个线程中包括哪个老师,哪个学生,进行到什么程度了;

(6) 要特别注意防范死锁问题的发生。

三、概要设计

1. 主类

通过人机对话获得所需要的学生人数S,老师人数M,学生需要接受检查的老师数K,老师最多检查学生数N,学生接受检查所需时间D,总时间 T。创建获取时间函数,进入,离开公共函数,供学生线程和老师线程使用,调用随机函数产生学生线程产生的时间,接着产生老师线程,等老师线程全部产生,一旦学

生线程产生时间一到立即产生学生线程,等待时间T到,结束所有未结束的学生和老师线程,退出程序。

流程图如下:

static int busy[];//0表示闲1表示忙 static int count[];//老师已经检查的个数 static int Tnum;//教室中空闲老师的个数 static int S=1,M=2,K=1,N=2,D=1,T=2,p; static long start; static Object oo=new Object();//用于锁 static int r[]; public static int gettime(); public static synchronized voidcomein(); public static synchronized void leave();

2、老师线程

在教师线程中,老师进入和离开教室时利用修饰符synchronized来解决同步与互斥的问题;在进入的函数声明为: public static synchronized void comein(),离开的函数声明为 public static synchronized void comein(),在synchronized的修饰下,每次只能有一个线程调用comein和leave函数,且这两个函数是在主类中声明的,故老师与老师,学生与学生,老师与同学都不会同时进入或离开。

教师线程中,老师先进来并告知用户老师已经进入,刚开始时,进来一个

教师,教室中的空闲教师就增加一个,老师进来后,程序先判断该教室检查的学生数够N没,时间已经不够了。若两者有一个满足则老师要离开教室并告知用户,教室中空闲的教室少一个,且要把改离开的教室的状态设为忙,因为学生并不知道老师的编号,通过随机数找老师时,仍可能找到该老师,故只能通过设“忙”使该老师不可用才行。告知用户老师离开时,通过对比老师离开的原因,输出不同的信息;

如果不满足条件,则通过while语句让老师处在等待之中;等待学生请老师来检查; 流程图如下:

2、学生进程

在学生线程中,进入之前先判断现在进去时间够不够检查,如果不够,学生则不进入,离开,输出离开信息。如果够,学生。进入,并向用户打印进入信息。

学生进入后就开始看有没有K个空闲的老师,且时间够不够,如果时间够,但老师不足,则通过while语句一直等待;如果等待中时间不够了(不管空闲老师足够了没有),则直接离开,输出离开信息;如果在有效时间内等到了K个老师则开始选择老师;

一个学生选择老师时,不允许他人选择,且一开始就将空闲教师数减K,老师编号是通过随机数产生的,随机产生一个老师,看他忙不忙,如果忙则再随机找,如果不忙,则将老师编号存起来,将老师的状态改为忙;找到K个空闲老师后,通过sleep函数来表示检查D这么长的时间。

检查完毕后,输出检查完毕信息,学生释放老师,将选择的老师的状态改为空闲,老师空闲数加依次增加,每个老师的检查次数增加1,(此时判断时间够不够,老师是否已近检查了N个人,如果不够或已经检查够N个人,则让老师离开,状态改为忙空闲老师相应减少。若不是,则继续等待;)学生离开,输出离开信息;

流程图:

四、详细设计

源程序代码如下:

/*

* To change this template, choose Tools | Templates * and open the template in the editor. */

package 教师对学生项目评分;

import java.util.*;

import java.util.Scanner;

public class job {

static int busy[]; //老师忙,0表示闲,1表示忙

static int count[]; //老师已经检查的个数 static int Tnum; //教室中空闲老师的个数 static int S=1,M=2,K=1,N=2,D,T,p; static long start;

static int r[];

public static int gettime() {

double duration;

long finish=System.currentTimeMillis(); duration=(double)(finish-start); return (int)duration; }

public static void main(String args[]) {

do {

if(S*K>M*N||S<0||K<0||M<0||N<0)

System.out.println(\ System.out.println(\请输入学生个数S:\ Scanner input = new Scanner(System.in); S = input.nextInt();

System.out.println(\请输入老师个数M:\ M = input.nextInt();

System.out.println(\请输入检查每个项目需要的老师数K:\ K= input.nextInt();

System.out.println(\请输入每个老师可以检查的项目数N:\

N = input.nextInt();

System.out.println(\请输入总时间T:\ T = input.nextInt();

System.out.println(\请输入检查每个项目所需时间D:\ D = input.nextInt();

}while(S*K>M*N||S<0||K<0||M<0||N<0);

busy= new int[M]; count= new int[M]; Tnum= 0; r=new int[S];

for(int i=0;i

busy[i]=0; count[i]=0; }

Teacher tea[]= new Teacher[M]; for(int k=0;k

tea[k]=new Teacher(k); }

Student stu[]=new Student[S]; for(int k=0;k

stu[k]=new Student(k); }

System.out.println(\ for(int i=0;i

count[i]=0; busy[i]=0; }

start=System.currentTimeMillis(); for(int i=0;i

tea[i].start(); }

for(int i=0;i

while(gettime()<=T); } }

class Teacher extends Thread {

int I;//第几个老师 public Teacher(int i){ I=i; }

public synchronized void comein() {

job.Tnum++; //教室中空闲老师人数加1 System.out.println(job.gettime()+\老师进入教室\ }

public synchronized void leave() {

job.Tnum--; this.stop(); }

public void run() {

this.comein();

while(job.count[I]

{

this.leave();

System.out.println(job.gettime()+\老师离开教室(已经检查够N个)\ else

{ if(job.busy[I]==0) {

System.out.println(job.gettime()+\老师离开教室(剩下时间不足以检查一个项目))\

this.leave();

} //老师由于时间不够再查一个人,所以离开

} } } }

class Student extends Thread {

int I; int a=0;

int visit[]=new int[job.K]; public Student(int i) {I=i;}

public synchronized void comein()

{ System.out.println(job.gettime()+\ \学生进入教室\ public synchronized void leave()

{ System.out.println(job.gettime()+\ \学生离开教室\ this.stop(); }

public void run() {

if(job.gettime()>job.T-job.D) //剩余时间是否小于D //是,则学生离开 {

System.out.println(job.gettime()+\ \学生离开教室(时间不足)\ this.stop(); //结束学生线程 } else { this.comein();//不是,学生进入教室 //System.out.println(Work.gettime()+\ }

while(job.Tnum

if(job.gettime()>=job.T-job.D) //等老师够,可是等;老师够的时候时间不够了

{

System.out.println(job.gettime()+\学生离开教室(时间不够)\ this.stop(); } else

synchronized(this){ {

job.Tnum = job.Tnum - job.K; for(int j=0;j=job.N || job.busy[a]!=0) //test[a]>=N表明老师已完成任务,已离开 a=(int)((double)Math.random()*job.M); //busy[a]!=0表明老师正在忙,为别人检查,继续寻找 job.busy[a]=1; //找到老师,修改其忙闲状态 visit[j]=a; //保存老师序号

System.out.println(job.gettime()+\老师\检查\学生\ }} try{Thread.sleep(job.D);}

catch(InterruptedException e) {}//检查学生 for(int j=0;j

if(job.gettime()>job.T-job.D)//如果时间已经不够了,立即让老师离开(即让他们不可用)//离开不能同时 {

System.out.println(job.gettime()+\老师\离开教室(时间不够).\

job.busy[visit[j]]=1; } } }

this.leave(); }

}

五、测试数据及其结果分析

输入数据:S=3.M=3,K=2,N=3,T=1000,D=200

系统为S=3个学生生成三个随机进入教室的时间:

单位是毫秒。

运行结果:

六、调试过程中的问题

1、程序中学生进入教室的时间是通过随机函数产生随机的,但是由于学生线程是依次产生的,如果先开始的学生线程的随机时间比较迟,后开始的学生线程的随机时间比较早,那么会导致先开始的学生线程没有开始时,把后面的学生线程都堵塞了。所以在这里通过对产生的随机时间从小到大排列,这样就可以避免这种问题。

2.还有就是在老师线程中,当老师时间不足或者检查够作业离开后,将空闲老师数量减一,输出离开消息,但是并没有使这个老师线程消亡,与世就出现了老师离开后,后面还有学生成功的找到他为自己检查。为了解决这一问题,当老师离开的时候就将老师的状态改为忙,这样,学生就不会再去找这个老师检查作业了。

七、专业课程设计总结

通过这次实验,我对java语言有了更进步一步的了解,通过不断地查阅,好像自己重新学了一遍java 语言一样。

这次实验,刚开始是没有头绪的,一直在图书馆查资料,也不知道从何着手,后来老师给了C++版本的,回去装了 LUNIX虚拟机,把老师的给的运行了一下才有了一些头绪。

后来和同学一起研究讨论,一点点的硬是把C++语言改成了java语言,其实对我们来说这是个挺艰难的事情,这个时候才发现自己学了一个学期java 真的好像白学了一样。这次实验让我发现了自己对java掌握的严重不足,其实理解了,还是觉得挺简单的,以后我会继续努力学习java这门语言

图形动画制作

一、 课题内容和要求

用图形函数设计动画,一个人在公路上奔跑,这时从屏幕右端开出一辆卡车,

最终将人撞倒了。

基本要求:

(1) 编程实现该动画;

(2) 实物演示时要求讲出程序原理; (3) 程序操作友好、界面清晰。 提高要求:

(1) 人和卡车的图形设计轮廓明晰,动画显示清楚、逼真; (2) 能够给动画赋予色彩,甚至实现三维效果。

二、需求和思路分析

此程序用C语言实现 使用的是EasyX 库

一个人在路上跑,然后出现一个行驶的车将其撞倒,可将这个程序分为两个部分,一部分是奔跑的人,一部分是行驶的车。最后将两部分组合。主要任务便是构造人,小车,以及用getimage,和putimage函数制造运动的效果。

奔跑的人:

由于人奔跑时有多个动作,所以需要画多个小人的图形,再组合起来形成奔跑的动作。

行驶的小车:

行驶的小车只需要画一个小车即可。 人与小车的结合:

本程序的即在这部分,为了使人与车能同时运动,故使用了嵌套的方法。人没跑一步小车也跑若干步。

Void far getimage(int x1,y1,int x2,y2,void *bitmap);

该函数将制定区域的图形从屏幕拷贝到内存区域。要复制的品目区域由左上角(x1,y1)和右下角(x2,y2)给出,它应当与imagesize函数中参数相同。Bitmap是一个void类型指针,需要复制的屏幕区域将保存在由他所指向的数组中。

void far putimage(int x,int y,void *bitmap,int op);

改函数将getimage函数保存的图形重新送回屏幕。参数(x,y)是回复显示图形左上角的位置,bitmap是指向void类型的指针,它指向用getimage函数复制的数组。参数op是一个整型数,是图形复制到屏幕上的显示模式。其取值有COPY_PUT,XOR_PUT等,前者是原样拷贝到屏幕,后者是与屏幕像素异或后拷贝。

如果使用XOR_PUT,则内存中的像素与当前屏幕上的像素进行异或操作。如果两个像素都为1,则相应的位置为0,从而使原来的图形小室。如果在复制一次,则会重新出现。利用这一特性,可以实现动画操作。

三、概要设计

步骤一:

用 line(),//直线函数

int points3[] = { }; fillpoly();//多边形填充函数 画车身;

用fillcircle()画车轮 步骤二:

用circle(); line();画小人 步骤三:

用getimage(&img1, x1, y1, x2,y2);getimage(&img2, x1, y1, x2, y2); 分别得到车的图像和人的图像并保存;

用getimage(&img3, x1, y1, x2,y2);得到背景色的空填充图片,功能类似于cleardevice()达到清屏的效果 步骤四:

分割屏幕的X轴像素,用i记录车与人行驶的像素长度,设为x 步骤五:

用for循环当想i

当i=x时,车与人相撞,此时画倒的小人 l

四、详细设计

#include // 就是需要引用这个图形库 #include

void main() {

initgraph(640,480); setcolor(BLUE); setlinestyle(PS_SOLID, NULL, 3); line(2,470,630,470);setfillstyle(GREEN, PATTERN_FILL, \

setlinestyle(PS_SOLID, NULL, 2);

int points3[] = { 30, 415, 30, 435,145,435,145,415,30, 415 }; fillpoly(5, points3); int points2[] = { 145, 390,160, 420, 160, 435,145,435,145, 390 };

fillpoly(5, points2);setcolor(RED);//line(30,415,40,400);line(30,415,145 ,415); fillcircle(50,450,15); fillcircle(130,450,15);setfillstyle(BLACK);

int points1[] = { 42, 404, 145, 404,145,415,30,415,42, 404 }; fillpoly(5, points1); //画小人 setlinestyle(PS_SOLID, NULL, 2); circle(450,415,10); line(443,413,448,413); line(452,413,457,413); line(447,420,453,420);

line(450,425,450,455); line(450,455,440,465); line(450,455,460,465); line(440,440,460,440); IMAGE img1,img2,img3; getimage(&img3, 30, 30, 135, 64); getimage(&img1, 30, 390, 135, 76); getimage(&img2, 440, 405, 21, 63); for(int i=1;i<140;i++) {

putimage(29+i, 390, &img1); if(i<139)

{putimage(440-i, 405, &img2);

Sleep(20);putimage(28+i, 390, &img3);putimage(441-i, 405, &img3); //cleardevice(); } else {

putimage(31+i, 390, &img1); circle(510-i,455,10);

line(470-i,455,500-i,455);line(512-i,449,516-i,452);line(515-i,458,511-i,461);line(505-i,451,505-i,459);

line(485-i,445,485-i,465); line(470-i,455,460-i,465); line(470-i,455,460-i,445); Sleep(50);putimage(28+i, 390, &img3); putimage(33+i, 390, &img1); //后面的五句是模拟车撞完人以后惯性停下来的过程 Sleep(80);putimage(28+i, 390, &img3); putimage(35+i, 390, &img1); Sleep(100);putimage(28+i, 390, &img3); putimage(37+i, 390, &img1); Sleep(110);putimage(28+i, 390, &img3); putimage(38+i, 390, &img1); Sleep(120);putimage(28+i, 390, &img3); putimage(39+i, 390, &img1); Sleep(150);putimage(28+i, 390, &img3); putimage(40+i, 390, &img1); } }

getch(); closegraph();

} }

五、测试数据及其结果分析

运行中:小车向右行驶,人向左行驶中

人与小车相撞后人倒下:

六、调试过程中的问题

程序中所用到的putimage()函数是通过IMAGE定义一个指针,然后后面的getimage()函数又把指针所指的图像显示在相应的位置上,所以刚开始出现了拖尾现象,后来我想到了使用清屏函数cleardevice();,可是那样的话就把公路这个图

像也清楚掉了,所以后来使用与图像相同大小的背景色来达到清屏功能。

void putimage(

int X, // 绘制位置的 x 坐标 int Y, // 绘制位置的 y 坐标

IMAGE *Img, // 要绘制的 IMAGE 对象指针 );

void getimage(

IMAGE* Img, // 保存图像的 IMAGE 对象指针 int X, // 要获取图像区域左上角 x 坐标 int Y, // 要获取图像区域的左上角 y 坐标 int Width, // 要获取图像区域的宽度 int Height // 要获取图像区域的高度 );

七、专业课程设计总结

通过此次实验,我对C语言与图像动画的方面有了更进一步的了解,也对图形学这门课有了更进一步的熟悉,因为学过一个学期的图形学课程,但上机实践的机会却很少,而这一次试过这个课程设计,虽然说是简单,但是还是再次巩固了我对图形学的学习。我翻阅了去年学的教科书,由于我迟迟装不上图形库头文件函数,而TC又太麻烦,所以我使用的是EasyX 库,这是我在网上查到的一个,从

中也学到了很多。

人与小车相撞后人倒下:

六、调试过程中的问题

程序中所用到的putimage()函数是通过IMAGE定义一个指针,然后后面的getimage()函数又把指针所指的图像显示在相应的位置上,所以刚开始出现了拖尾现象,后来我想到了使用清屏函数cleardevice();,可是那样的话就把公路这个图

像也清楚掉了,所以后来使用与图像相同大小的背景色来达到清屏功能。

void putimage(

int X, // 绘制位置的 x 坐标 int Y, // 绘制位置的 y 坐标

IMAGE *Img, // 要绘制的 IMAGE 对象指针 );

void getimage(

IMAGE* Img, // 保存图像的 IMAGE 对象指针 int X, // 要获取图像区域左上角 x 坐标 int Y, // 要获取图像区域的左上角 y 坐标 int Width, // 要获取图像区域的宽度 int Height // 要获取图像区域的高度 );

七、专业课程设计总结

通过此次实验,我对C语言与图像动画的方面有了更进一步的了解,也对图形学这门课有了更进一步的熟悉,因为学过一个学期的图形学课程,但上机实践的机会却很少,而这一次试过这个课程设计,虽然说是简单,但是还是再次巩固了我对图形学的学习。我翻阅了去年学的教科书,由于我迟迟装不上图形库头文件函数,而TC又太麻烦,所以我使用的是EasyX 库,这是我在网上查到的一个,从

中也学到了很多。

本文来源:https://www.bwwdw.com/article/sqpg.html

Top