计算机类课程
(211G0290)计算机科学基础(A)
- 考核方式:25%小测+35%作业(平时作业/论文)+40%期末
- 这门课在22级开始教改,23级继续教改,24级大约是取消了😄。
- 虽然不知道22级以前是咋样的,不过22级教改之后,这门课的内容变得杂乱繁多,包括很多计算机偏底层的知识(编码/系统/硬件),office等软件的使用和许多python内容。 高中学过技术的大概对python会熟悉一些,但是python真不难,背背语法就能拿分。反倒是基础知识类因为考试范围不明确要难一些。
- 期末复习可以参考bhh的ppt,在他的个人主页(需内网)上可以下载,另外也需要复习pta作业。
(211G0280)C程序设计基础
- 考核方式:20%作业+30%小测+15%期末上机考+35%期末理论考
Note
- 22级及以前,非工信类专业若选择c语言课程学习,须和工信类专业学生一起修读该课程。23级开始,新增“C程序设计基础与实验”(211G0310)作为专供工信类专业修读的c语言基础课。因此23级开始,该课程学习内容可能有所变动,请以老师实际安排为准。
- 但以下经验同样适合修读“C程序设计基础与实验”(211G0310)的同学阅读。
- 如果你计算机基础没那么好,建议你先使用dev c/在线编程网站/pta自带的编程工具完成该课程的编程要求,不建议为了该课程装clion或visual studio,更不要碰visual studio code。
- 这门课是基础课中少数需要按照作业正确率给作业分的课程,因此对于不会做的作业建议csdn/gpt查一下,确保pta上是正确的。(这门课抄代码也没啥,自己弄懂即可)
- 上机课属于历史遗留,现在大家毕竟都有电脑,如果老师不点名不小测的话可以不去。其实正课上不上也差不多,这门课真要学会还是得 多写代码 ,别太指望老师讲会你除了语法以外的问题。
- 期末考试分为两个部分,理论考和上机考,上机考在后半学期中旬(11月/5月)进行,分为四批,每批题目不一样。需要在半小时完成2道题, 必须完整做对一道题,否则挂科 (如果挂的人太多了会调整,以及22春夏搞了个上机考补考)。理论考按教务网时间进行(不同班时间不一样,大约是分为两批),也会根据情况设置斩杀线。
- 上机考试由于斩杀线的原因,一向是挂人重灾区。但是课程的目的毕竟是让你学会写代码,因此平时需要除了搞会语法,也要注重调试(debug)技巧的学习,题目是不难的。另外,上机考不考指针(除非你认为scanf也是用了指针)。
- 理论考就比较抽象了,非常喜欢考一些不是正常人写出来的代码,幸好,我们有前人的总结这个cc98链接、这位同学整理了很多笔记,把他们理解,满绩绰绰有余。顺带一提,c语言的权威语法规则详见cppreference,注意我们学习的是c89标准。
- 我的授课老师是侯启明,他在作业里加了自己出了一道附加题,我认为非常有趣,在这里贴出来,并在最后附上了解题思路。
犯规七人大战
裁判用C语言实现了一个简单的RPG游戏,有若干个用
Character
结构体表示的角色:你需要实现一个函数,代表struct Character{ char name[16]; //角色名 float hp; //生命值 float mp; //魔法值 };
name
是"Player"
的角色,综合运用各种招数,击倒所有其它角色。每回合,你会收到:struct Action ActAsPlayer ( struct Character you, const char* enemy_name, struct Action next_action );
- 自己的当前状态
you
- 下一个对手的角色名
enemy_name
- 对手的预定出招
next_action
你需要用
Action
结构体返回一个自己的出招,格式和对手的预定出招next_action
相同:以下描述仅供参考,实际规则以裁判程序为准。struct Action{ char kind; float value; };
其中kind可以是:
'A'
表示攻击,对方的hp
降低10'H'
表示治疗,己方的hp
增加value
,己方的mp
消耗value
'X'
表示爆发,直接将对方hp
变成0,己方的mp
消耗999
在
ActAsPlayer
返回后,裁判程序会让对战双方依次行动。行动结束后,如果某一方的hp
小于等于0,那么就判定他/她战斗不能。如果Player
战斗不能,该测试用例直接判错。否则会换上下一个敌方角色继续战斗。当击败全部敌方角色后,你就可以得到这个测试点的分数。如果进行
'H'
或者'X'
行动时mp
不足,Player
会被直接判负。最初回合
Player
先手,后续回合敌人先手。如果先手角色行动结束时后手角色已经战斗不能,那么后手角色将无法行动。仅供参考部分结束。
包括
Player
在内,最多只会有7个角色参与战斗。提示:
- 实际的裁判程序和题面中完全相同,务必仔细阅读
- 你的代码和裁判程序是对抗关系而非合作
- 按题面规则内的手段战斗最多获得一半的分数
- 这是C程序设计的考题,涉及的知识点是 指针、结构和浮点运算
裁判测试程序:
输入样例#include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> #include <math.h> #include <memory.h> struct Character{ char name[16]; float hp; float mp; }; struct Action{ char kind; float value; }; struct Action ActAsPlayer ( struct Character you, const char* enemy_name, struct Action next_action ); #define MAX_N_CHARS 8 void PerformAction( struct Character* actor, struct Character* target, struct Action action ){ // Defeated characters can't act if(actor->hp<=0.f){return;} switch(action.kind){ case 'A':{ target->hp-=10.f; break; } case 'H':{ actor->hp+=action.value; actor->mp-=action.value; if(actor->mp<0.f){ printf("%s healed too much\n",actor->name); actor->hp=0.f; } break; } case 'X':{ if(actor->mp>=999.f){ actor->mp-=999.f; target->hp=0.f; } break; } default:{ printf("%s used an invalid action '%c'\n",actor->name,action.kind); actor->hp=0.f; break; } } } int main(){ // Read in the character data struct Character characters[MAX_N_CHARS]={}; struct Action* actions[MAX_N_CHARS]={}; int p_actions[MAX_N_CHARS]={}; int n_chars=0; int id_player=0; int n_read=0; n_read+=scanf("%d",&n_chars); for(int i=0;i<n_chars;i++){ int n_actions=0; n_read+=scanf("%15s%f%f%d", characters[i].name, &characters[i].hp, &characters[i].mp, &n_actions ); // Read in standard action sequences actions[i]=(struct Action*)calloc(sizeof(struct Action), n_actions+1); for(int j=0;j<n_actions;j++){ char tmp[2]={}; n_read+=scanf("%1s%f",tmp,&actions[i][j].value); actions[i][j].kind=tmp[0]; } if(strncmp(characters[i].name,"Player",7)==0){ id_player=i; } } assert(n_read>0); // Start the combat int player_first=1; for(;;){ // Test for player loss if(characters[id_player].hp<=0.f){ printf("Player has lost\n"); return 0; } // Find a surviving enemy int id_enemy=-1; for(int i=0;i<n_chars;i++){ if(i!=id_player&&characters[i].hp>0.f){ id_enemy=i; break; } } if(id_enemy<0){ break; } // Get enemy action struct Action act_enemy={}; do{ act_enemy=actions[id_enemy][p_actions[id_enemy]++]; if(!act_enemy.kind){p_actions[id_enemy]=0;} }while(!act_enemy.kind); // Get player action struct Action act_player=ActAsPlayer( characters[id_player], characters[id_enemy].name, act_enemy ); // Act out int id_first=id_player; int id_second=id_enemy; struct Action act_first=act_player; struct Action act_second=act_enemy; if(!player_first){ int tmp=id_first; id_first=id_second; id_second=tmp; act_first=act_enemy; act_second=act_player; } PerformAction( &characters[id_first], &characters[id_second], act_first ); PerformAction( &characters[id_second], &characters[id_first], act_second ); player_first=0; } printf("Player has beaten "); const char* sep=""; for(int i=0;i<n_chars;i++){ if(i!=id_player){ printf("%s%s",sep,characters[i].name); sep=", "; } } putchar('\n'); } /* 请在这里填写答案 */
输出样例3 Goblin 5 3 1 A 0 Player 80 50 0 Kobold 15 50 2 H 5 A 0
样例解释: 两个敌人,Player has beaten Goblin, Kobold
Goblin
一直攻击,Kobold
交替治疗/攻击。敌人都很弱,一直'A'
就能获胜。代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB
- 自己的当前状态
解题思路和答案在这里
- 根据题目暗示“按题面规则内的手段战斗最多获得一半的分数”“涉及的知识点是 指针、结构和浮点运算”以及题目标题“ 犯规 七人大战”,我们需要考虑一些非常规的通过方法。
- 通过课程学习大家知道指针保存的是地址,我们在需要写的函数中获得了参数
const char* enemy_name
,这个值是保存敌人名字的字符数组char name[16]
的第0位的地址,而根据结构体Character
的定义,char name[16]
和float hp
的地址是连续的,因此enemy_name+16
就是变量hp
的起始地址,使用memset函数修改连续四个字节的值为0即可,代码如下。struct Action ActAsPlayer (struct Character you, const char* enemy_name, struct Action next_action) { memset(enemy_name+16,0,4); struct Action data; data.kind='A'; data.value=0; return data;//随便返回一个不出问题的动作 }