关于高校选课系统,请帮忙进来看看!有些问题未能解决,谢谢了!(300分)

  • 主题发起人 主题发起人 心动痕迹
  • 开始时间 开始时间

心动痕迹

Unregistered / Unconfirmed
GUEST, unregistred user!
要求: 现在要做这样的一个选课系统,
总共有三个志愿可以报,
每个志愿可以报而且必须报两门课程,
即总共报六门课,可最终能修读的只有两门课,
这两门课程可以是任何一个志愿内的,
如第一志愿一门,第二志愿一门。
必须要先选完课才可以进行排课,
所以当学生进行选课后不是立即获知结果,
等待处理后,才能的到结果。

注册,登录,选课的功能都实现了,
是采用了以下的库结构,
三个表来装载这三个志愿的人。
即第一志愿的表装的是全部是报第一志愿的学生,

第一志愿的表 第二志愿的表 第三志愿的表

学号 课程 学号 课程 学号 课程
9801 B001 9801 B003 9801 B005
9801 B002 9801 B004 9801 B006
9802 B001 9802 B005 9802 B003
9802 B002 9802 B006 9802 B004
9803 B003 9803 B005 9803 B001
9803 B004 9803 B006 9803 B002
9804 B005 9804 B003 9804 B001
9804 B006 9804 B002 9804 B002
' ' ' ' ' '
' ' ' ' ' '
' ' ' ' ' '
还有一个课程班表

课程 教师 地点 时间 限定人数 第一志愿已报人数 第二志愿已报人数 第三志愿已报人数
BOO1 A001 AA BB 10 4 4 5
BOO2 A002 DD UU 15 3 3 4
BOO3 A003 EE WW 14 5 3 7
BOO4 A004 FF HH 12 13 2 4
B005 A005 QQ II 15 10 10 2
B006 A006 PP KK 12 2 3 3

最后是一个排课表
学号 课程1 课程2
(该表的内容是要等待排课的时候即时进入更新的)

以上的数据都是学生们已经选完课后所获得的,
呵呵,都是小弟虚拟的,可能会有不合理之处,

现在要排课功能的实现,因为这个时候学生们已经选完课了,
于是必须进行排课,对于限定人数比报名人数大的采用随机数
进行筛选,排课的时候必须做到公平。
最后如果某些学生最终没能实现读两门课的话,用手工进行排课。

以下是小第的想法:
遍历课程班里的课程,
比如B001课程,只能限定10人,于是对限定人数和已报的人数进行比较,
志愿当然是优先考虑的。
于是第一志愿库里的的学生可以全部进入,
第二志愿库的学生也可以,但是第三志愿库的学生只能有2位可以,
用随机数筛选,剩下的3位要落选。

不晓的这样做是否符合了公平的原则,因为这样坐做的话,那某些学生很肯能是
他的第三志愿可以被选中,但是第一志愿却不能选中。

但还必须考虑一个是否有资格的问题,
就是假如某名学生已经可以获的了选修两们课程,
那他就没有资格再参加下一门课程的排课了,
那他的余下志愿所选修的课程都是无效的,
即使他余下志愿所选的课程有空余的名额,他也没有资格进行。

现在小第在排课这里非常困惑,并且做出来的程序根本无法实现自己所想的功能,
希望各位高手可以帮帮忙,如果能帮忙写出代码的话,那就更加感谢了。
其实上述的库结构如果大家觉得不合理的,也可以进行修改,只要能实现
选课的公平功能就行了。



 
我考,是不是网上招聘程序员啊?
呵呵。
 
各位高手们,帮忙看看啊!
 
其实你要实现的程序逻辑,据我所知,在清华大学、南京大学、东南大学的选修课程程序
中都有体现,他们的算法思路如下:
1、对已选课的三个自愿与课程的自愿核定人数之差,进行排序。
2、对自愿报修的人数差最大的进行分配,原则与你的算法差不多,就是选修的人数少于
核定人数就全上,否则就随机抽取。
3、删除已选满两个课程的学生;删除已排过课的课程。
4、对删除后的志愿表与删除后的课程表按1进行重新排序,重复2、3、4的动作,直到所
有的课程分配完为止。
5、对没有选完课的课程与没有选到课的学生进行手动调整。
 
  其实我也晓的要删除已经选了两门的学生,可是该如果实现呢?
如果设置标志位的话,首先要确定是否选了两门课,接着还要计算所有选了两门课的学生的
人数究竟是多少。那又必须有个计算的变量存在是啊。那样的话,代码究竟应该怎样写才
更加合理呢?
下面是小弟写的代码,是否符合逻辑与要求呢?
 可是无法实现排课的功能啊,请帮忙看看哪里出错了,还是算法就已经存在问题?
因为遍历的是课程班。所以就不必要再执行删除排完课的课程了。
procedure Tform1.button1(Sender: TObject);
begin
table5.disablecontrols;//table5是课程班
table5.first;
while not table5.eof do//首先考虑第一门课程
begin
if table5.fieldbyname('第一志愿已报人数').value<=table5.fieldbyname('限定人数').value then
begin
paike(table2); //paike是排课函数,既进入排课库
m:=table5.fieldbyname('限定人数').value-table5.fieldbyname('第一志愿已报人数').value;
if m>0 then //既有名额剩余
begin
biaozhi(table3); //biaozhi的作用是要获的没有资格参加选课的学生的人数
if table5.fieldbyname('第二志愿已报人数').value-p<=m then
// P就是从biaozhi里获得的没有资格进行排课的人数
begin
paike(table3);
m:=m-table5.fieldbyname('第二志愿已报人数').value;
if m>0 then
begin
biaozhi(table4);
if table5.fieldbyname('第三志愿已报人数').value-p<=m then
paike(table4)
else
gongping(table4);//gongping为公平算法,即要进行筛选
end
else
post;
table5.Next;
end
else
begin
gongping(table3);
post;
table5.next;
end;
end
else
begin
gongping(table2);
post;
table5.next;
end;
end;
table5.enablecontrols;
end;
end;
procedure Tform1.biaozhi;
begin
table6.disablecontrols;//table6 是排课库
table6.first;
while not table6.eof do
begin
if (table6.fieldbyname('课程编号1').asstring<>'')and
(table6.fieldbyname('课程编号2').asstring<>'') then
begin
p:=0;
p:=p+1; //这里P是全局变量,因为要在上面的程序里调用。
end;
table6.next;
end;
table.enablecontrols;
table6.enablecontrols;
end;

procedure Tfrmgxskxt.gongping(table:Ttable);
var
n:integer;
begin
with table do
begin
disablecontrols;
first;
while not table.eof do
begin
if random(15)<m then
begin
paike(table);
biaozhi;
end
else
begin
with table7 do// table7是落选库
begin
edit;
append;
fieldbyname('学号').asstring:=table.fieldbyname('学号').asstring;
fieldbyname('课程编号').asstring:=table.fieldbyname('课程编号').asstring;
post;
refresh;
 end;
end;
  end;
end;
end;


procedure Tfrmgxskxt.paike(table:Ttable);
begin
with table do
begin
table.disablecontrols;
table.first;
while not table.eof do
  begin
  if table.fieldbyname('课程编号').asstring=table5.fieldbyname('课程编号').asstring then
begin
with table6 do
    begin
     disablecontrols;
     first;
     while not table6.eof do
      begin
edit;
      fieldbyname('学号').asstring:=table.fieldbyname('学号').asstring;
if fieldbyname('课程编号1')='' then
fieldbyname('课程编号1').asstring:=table.fieldbyname('课程编号').asstring
else
fieldbyname('课程编号2').asstring:=table.fieldbyname(' 课程编号').asstring;
post;
refresh;
next;
end;
enablecontrols;
end;
end; 
  table.next;
end;     
enablecontrols     
end.    

 
你的代码基本上能实现排课,但是缺点是没有删除已经选了两门课的学生,导致这些学生
仍然参加下一课程的排课。
解决办法是:在排完一门课后,将你自愿表中的在排课表中已有两门课的学生过滤掉就可
已啦。

但是就你的算法来看,不要使用Table,而是使用Query,动态查询选修了当前待排课的学生
名单(剔除已选满两门课的学生),如果记录数大于核定数就随机派课,如果记录数小于核定
数,就全部选中。
 
不好意思,table2是第一志愿的库,table3是第二志愿的库,table4是第四志愿的库
 
不好意思,小弟的delphi只学了一个多月,只是对
table比较熟悉,如果用query的话,高手们可否
帮忙写来看看,谢谢!
 
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Append('Select [学号] from [第一志愿表]');
Query1.SQL.Append(' Where [学号] not in (Select [学号] From [排课表]');
Query1.SQL.Append(' Where [课程1]<>"" and [课程2]<>""');
Query1.SQL.Append(' ) and [课程]=:KC');
Query1.ParamByName('KC').AsString:=当前的课程号;
Query1.Open;
以上代码是实现查询当前课程的第一志愿的选课学生(已剔除选满两门课的学生),
你只要变一变就可以得到[第二志愿表]、[第三志愿表]的选课学生。
 
这个过程应该该为
procedure Tform1.biaozhi;
begin
p:=0;
table6.disablecontrols;//table6 是排课库
table6.first;
while not table6.eof do
begin
if (table6.fieldbyname('课程编号1').asstring<>'')and
(table6.fieldbyname('课程编号2').asstring<>'') then
begin
p:=p+1; //这里P是全局变量,因为要在上面的程序里调用。
end;
table6.next;
end;
table.enablecontrols;
table6.enablecontrols;
end;
 
将志愿表合成一个,加一个字段志愿编号,这样编程会方便一些,而且设计也合理
 
初步该了该看有什么不合适的地方你在调调

procedure Tform1.button1(Sender: TObject);
begin
table课程班表.disablecontrols;//table5是课程班
table课程班表.first;
while not table课程班表.eof do//首先考虑第一门课程
begin
if table课程班表.fieldbyname('第一志愿已报人数').value<=table课程班表.fieldbyname('限定人数').value then
begin
paike(table第一志愿库); //paike是排课函数,既进入排课库
m:=table课程班表.fieldbyname('限定人数').value-table课程班表.fieldbyname('第一志愿已报人数').value;
if m>0 then //既有名额剩余
begin
biaozhi;//(table第2志愿库); //biaozhi的作用是要获的没有资格参加选课的学生的人数
if table课程班表.fieldbyname('第二志愿已报人数').value-p<=m then
// P就是从biaozhi里获得的没有资格进行排课的人数
begin
paike(table第2志愿库);
m:=m-table课程班表.fieldbyname('第二志愿已报人数').value;
if m>0 then
begin
biaozhi(table第3志愿库);
if table课程班表.fieldbyname('第三志愿已报人数').value-p<=m then
paike(table第3志愿库)
else
gongping(table第3志愿库);//gongping为公平算法,即要进行筛选
end;
table课程班表.Next;
end
else
gongping(table第2志愿库);
end;
end
else
gongping(table2);
end;
table课程班表.enablecontrols;
end;

procedure Tform1.biaozhi;
begin
p:=0;
table排课库.disablecontrols;//table排课库 是排课库
table排课库.first;
while not table排课库.eof do
begin
if (table排课库.fieldbyname('课程编号1').asstring<>'')and
(table排课库.fieldbyname('课程编号2').asstring<>'') then
p:=p+1; //这里P是全局变量,因为要在上面的程序里调用。
table排课库.next;
end;
table.enablecontrols;
table排课库.enablecontrols;
end;

procedure Tfrmgxskxt.gongping(table:Ttable);
var
n,i,ipos:integer;
begin
while m<>n then
begin
i := random(table.recordcount+1);
with table do
begin
disablecontrols;
first;
while not table.eof do
begin
if i = ipos then
begin
with Query排课库 do
begin
Close;
Sql.Text := 'Select * from 排课库 where 课程编号 = :param1';
ParambyName('param1').asstring := table.fieldbyname('课程编号').asstring
Open;
   disablecontrols;
    first;
   while not Query排课库.eof do
  begin
edit;
  fieldbyname('学号').asstring:=table.fieldbyname('学号').asstring;
if fieldbyname('课程编号1')='' then
fieldbyname('课程编号1').asstring:=table.fieldbyname('课程编号').asstring
else
fieldbyname('课程编号2').asstring:=table.fieldbyname(' 课程编号').asstring;
post;
next;
end;
enablecontrols;
end;
biaozhi;
break;
end else
begin
inc(iPos);
Next;
end;
end;
end;
end;
end;


procedure Tfrmgxskxt.paike(table:Ttable);
begin
table.Open;
table.disablecontrols;
table.first;
while not table.eof do
begin
with Query排课库 do
begin
Close;
Sql.Text := 'Select * from 排课库 where 课程编号 = :param1';
ParambyName('param1').asstring := table.fieldbyname('课程编号').asstring
Open;
   disablecontrols;
   first;
   while not Query排课库.eof do
  begin
edit;
 fieldbyname('学号').asstring:=table.fieldbyname('学号').asstring;
if fieldbyname('课程编号1')='' then
fieldbyname('课程编号1').asstring:=table.fieldbyname('课程编号').asstring
else
fieldbyname('课程编号2').asstring:=table.fieldbyname(' 课程编号').asstring;
post;
end;
next;
end;
enablecontrols;
end;
 table.next;
end;     
 
实在是高手很多,我来学习
 
多人接受答案了。
 
后退
顶部