CS61B Project0

由于考研要学习数据结构顺便想着看一下国外的优质公开课,如果想看建议看2021spring的。

我先看着的week1,proj0用的是java基础,完善2048这个项目里面的缺失的函数。

project0分为基础部分和实验部分。

这个2048程序首先是有点反人类,平时玩2048都是在认为左上角才是最小的坐标,但是程序中坐标是左下角才是开始,按照直角坐标系进行划分的,所以在这个程序中2048是按照列在前行在后的情况进行一系列函数的编写。

一、基础部分

基础部分要求完成的model.java中的emptySpaceExists(Board b)maxTileExists(Board b)atLeastOneMoveExists(Board b)这三个函数

对于emptuSpaceExists(Board b)的函数完善

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/** Returns true if at least one space on the Board is empty.  
* Empty spaces are stored as null. * */
public static boolean emptySpaceExists(Board b) {
// TODO: Fill in this function.
boolean judge = false;
for(int i = 0;i<4;i++){
for(int j = 0;j<4;j++){
if(b.tile(i,j) == null){
judge = true;
break;
}

}
}
return judge;
}

这个的代码判断是否2048这个键盘是否为空的情况,Board.java中的函数tile(int col,int row)这个函数是用来判断当前的列行对应的格子有没有数据。因此我们看到判断是否为空就是通过该函数进行判空,然后boolean judge改变即可。

对于maxTileExists(Board b)的函数完善

要求

通过这个要求就是有个注意点最好不要用x==2048而是x==MAX_PIECE就是避免了硬编程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**  
* Returns true if any tile is equal to the maximum valid value. * Maximum valid value is given by MAX_PIECE. Note that * given a Tile object t, we get its value with t.value(). */
public static boolean maxTileExists(Board b) {
// TODO: Fill in this function.
boolean judge = false;
for(int i = 0;i<4;i++){
for(int j = 0;j<4;j++){
if(b.tile(i,j) != null && b.tile(i,j).value() == MAX_PIECE){
judge = true;
break;
}
}
}
return judge;
}

这个就是在说找到2048这个最大值,因为在程序中MAX_PIECE = 2048所以就是找到2048。因此还是遍历数组寻找最大值,找不到就是false。

对于atLeastOneMoveExists(Board b)的函数完善

要求

就是有两个要求,至少有一个格子是空白的,然后是有两个相邻格子会有相同的出现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**  
* Returns true if there are any valid moves on the board. * There are two ways that there can be valid moves: * 1. There is at least one empty space on the board. * 2. There are two adjacent tiles with the same value. *///要求1:有空白
//要求2:有相邻的两个相同的
public static boolean atLeastOneMoveExists(Board b) {
// TODO: Fill in this function.
if(emptySpaceExists(b))
return true;
boolean two = false;
int[] dx = {-1, 0, 1, 0};
int[] dy = {0, 1, 0, -1};
int size = b.size();
for(int col = 0; col < size; col ++) {
for(int row = 0; row < size; row ++){
int value_cur = b.tile(col, row).value();
for(int k = 0; k < 4; k ++){
int cur_col = col + dy[k];
int cur_row = row + dx[k];
if(cur_col > 0 && cur_col < size && cur_row > 0 && cur_row < size && b.tile(cur_col, cur_row).value() == value_cur)
return true;
}
}
}
return false;
}

因此需要找到的是判断一个方块的上下左右是否会出现相同的。所以需要方向向量进行移动。判断是否会有空白就是看第一个函数。接着就是判是否有相邻相同的,就是通过暴力求解规定在board的边界内即可。

二、核心问题

核心问题就是如何写出2048的logic。

核心问题

从这段文字看出就是2048的核心逻辑完成就是通过Model.java中的函数tile()进行编写

tile的功能

通过图片可以看出上移的时候在同一列的每一行如果该数字的前面有空位就会往上补,而且通过实例中的第三列可以看出例子是同一列的最后一行(表格中的第一行)开始遍历,也就是一次2048向上滑动的逻辑。

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
public boolean tilt(Side side) {  
boolean changed;
changed = false;

// TODO: Modify this.board (and perhaps this.score) to account

int size = board.size();

if(side != Side.NORTH)
board.setViewingPerspective(side);

// 对于每一列,先找到能向上移动的最大位置(找空格数)
for(int col = 0; col < size; col ++) {
for (int row = size - 2; row >= 0; row--) {
int nulltile = 0;
Tile t = board.tile(col, row);
if(t != null) {
for(int row_before = row + 1; row_before < size; row_before ++){
if(tile(col, row_before) == null)
nulltile ++;
}
board.move(col, row + nulltile, t);
changed = true;
}
}
}
for(int col = 0; col < size; col ++){
for (int row = size - 2; row >= 0; row--) {
Tile t1 = board.tile(col, row);
if(t1 != null){
Tile t2 = board.tile(col, row + 1);
if(t2 != null && t1.value() == t2.value()){
board.move(col, row + 1, t1);
changed = true;
score += 2 * t2.value();
}
}
}
}
for(int col = 0; col < size; col ++) {
for (int row = size - 2; row >= 0; row--) {
int nulltile = 0;
Tile t = board.tile(col, row);
if(t != null) {
for(int row_before = row + 1; row_before < size; row_before ++){
if(tile(col, row_before) == null)
nulltile ++;
}
board.move(col, row + nulltile, t);
changed = true;
}
}
}

if(side != Side.NORTH)
board.setViewingPerspective(Side.NORTH);

// for the tilt to the Side SIDE. If the board changed, set the
// changed local variable to true. checkGameOver();
if (changed) {
setChanged();
}
return changed;
}

首先2048的tile()里面的是Side side然后可以看side.javaboard.java可以发现关于上下左右的滑动是做了个处理,就是通过board.setViewingPerspective(side)这是说滑动的是如果是向左划会将整个表进行翻转,翻转成向北滑动的情况,就不用额外考虑其他三种情况。

首先我们就是需要有数字的格子的行上会不会有空格有的话进行补充,跳到空格那里。

第二个for循环就是讲相同数字进行merge,而board.move()这个函数里面就有merge的操作,不需要额外写。

第三个for循环和第一个for循环一样,因为merge完了后会有新的空位出来,因此需要填充新的空位。


CS61B Project0
https://ljw030710.github.io/2024/11/29/CS61B-Project0/
Author
iolzyy
Posted on
November 29, 2024
Licensed under