斯坦福CS106A作业1

一直想学这门课,网易公开课的版本确实不错,但是代码看不清,非常难受,所以自己搬运了youtube上2016年的课程,非常清晰,字幕是youtube自动翻译的,可能有些不准,但内容和网易公开课版本基本一致,这里给下链接。
视频地址:
https://pan.baidu.com/s/12oEpv022SiKlJGwZiQNO0g
密码:62nu
参考书籍:
https://pan.baidu.com/s/1PYRjvvq6fkV_NdTR7FOa2g
密码:h092

课程主页:
https://www.baidu.com/link?url=Ti8c7qJ4ibyIfgMgucbK5qTnnzGf3xWVsRdzORr1_fF-vGRVoHQ7Q7RlITXwHgPE&wd=&eqid=a77bcc030001438d000000045aba5907
最新版的课程其实和网易公开课上的资料基本一致,选择哪个都可以,个人感觉把这些部分都完成应该会有不错的效果。

再来简述一下这门课程,这门是编程的入门课,0基础都可以学,介绍java的,老师讲课很有意思,难度不大,感觉这门课的精华是作业,所以在这里记录下作业的思路。

来看下作业1,主要是Karel的操作。

  • problem1:

这题很简单,就是移动过去拿住物块,并返回,基本题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import stanford.karel.*;

public class CollectNewspaperKarel extends SuperKarel {

// You fill in this part
public void run() {

move2new();
pickBeeper();
return2start();
}
private void move2new() {
move();
turnRight();
move();
turnLeft();
move();
move();
}
private void return2start() {
turnAround();
move();
move();
move();
turnRight();
move();
turnRight();
}

}
  • problem 2:

这题的意思上设计代码帮助Karel在固定间隔处放物块,注意每次的高度不一定一致,一共放置的列数也不是常数,但是列和列的间隔固定。

这里定义了put方法和move4。put方法将其所在列的空缺处放上物块并返回原处,注意这里开始和结束的方向均为面朝右。move4方法为运动固定距离,这里为4。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import stanford.karel.*;

public class StoneMasonKarel extends SuperKarel {

// You fill in this part
public void run() {
put();
while (frontIsClear()) {
move4();
put();
}
}

private void move4() {
for (int i=0;i<4;i++) {
move();
}
}

private void put() {
turnLeft();
while (frontIsClear()) {
put1();
move();
}
put1();
turnAround();
while(frontIsClear()) {
move();
}
turnLeft();
}

private void put1() {
if (noBeepersPresent()) {
putBeeper();
}
}
}
  • problem 3:

这题的意思是让Karel在中点处放物块,如果墙的间隔为2k,则在k或者k+1的位置放均可,如果墙的间隔和2k+1,则在k+1的位置放。乍一看是个弱智题,但是这里Karel是没有办法计数的,所以还是有一定难度的。

这里的思路是定义一个状态量flag:如果前方为墙或者有物块,则状态为1,否则为0。利用这个状态量先放置左右两侧靠边的物块,然后递归在剩余未放置的地方重复此操作,最后会在每个地方放置一个物块。然后我在停滞的地方多放置两个物块,最后利用remove方法清理物块,正向反向各一次,最后留下的物块在中点处。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import stanford.karel.*;

public class MidpointFindingKarel extends SuperKarel {

// You fill in this part
public void run() {
put();
//在停滞的点放两块物块
putBeeper();
putBeeper();
//移除物块
remove();
turnAround();
//反向移除物块
remove();
turnAround();
while (noBeepersPresent()) {
move();
}
}

//递归定义放置函数,先放左右两边的物块,再在剩余空余位置重复此操作
public void put() {
if (noBeepersPresent()) {
putBeeper();
}
while (flag()==1) {
if (frontIsClear()) {
move();
}
}
if (noBeepersPresent()) {
putBeeper();
}
turnAround();
if (flag()==1) {
put();
}

}

//如果前面有物品或者墙,返回0,否则返回1
private int flag() {
if (frontIsBlocked()) {
return 0;
}else{
move();
if (beepersPresent()) {
turnAround();
move();
turnAround();
return 0;
}else {
return 1;
}

}
}

//如果有物块,则清理
private void remove() {
while (frontIsClear()) {
if (beepersPresent()) {
pickBeeper();
}
move();
}
if (beepersPresent()) {
pickBeeper();
}
}
}
  • problem 4



    这一题是将空盘填为棋盘的样子,要注意奇数偶数两种不同情形。这里的思路是定义put1和put2,put1处理奇数排的情形,put2处理偶数排的情形。每行处理完之后返回最左侧,如果此处有物块,则下一行为偶数排,否则为奇数排。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import stanford.karel.*;

public class CheckerboardKarel extends SuperKarel {

// You fill in this part
public void run() {
put1();
//判断是否到达最高层,右手边为墙
while(rightIsClear()) {
//如果此处有物块,下一排采用put2(),否则采用put1()
if (beepersPresent()) {
turnRight();
move();
turnRight();
put2();

}else {
turnRight();
move();
turnRight();
put1();
}
}
}

//在奇数排中每间隔一个距离放物块,结束后返回最左侧,面朝墙
private void put1() {
putBeeper();
while(frontIsClear()) {
move();
if (frontIsClear()) {
move();
putBeeper();
}
}
turnAround();
while (frontIsClear()) {
move();
}
}

//在偶数排中每间隔一个距离放物块,结束后返回最左侧,面朝墙
private void put2() {
if (frontIsClear()) {
move();
}
putBeeper();
while(frontIsClear()) {
move();
if (frontIsClear()) {
move();
putBeeper();
}
}
turnAround();
while (frontIsClear()) {
move();
}
}
}