【build a computer】 project 9
week9
目前已经开始了build a computer系列的最后几章了,后面的章节感觉越来越难,build a computer的part II部分基本上全是软件,需要编码,耗费大量的实践和精力来应付这些代码,不过能够最终通过测试的话还是成就满满,特别是只剩下后面三章了,主要是完成一个jack语言编译器和一个最基本的微型操作系统,并提供基本的系统库函数。感觉难度和挑战还是挺高的,非常喜欢这类基础的课程,要是这些课程放在大学本科该多好,有这么好的教程和资源,却一直从来没有机会接触到这么好的教育资源。其实从内心来说,叶不想让自己的孩子再重复一遍国内这种糟糕的教育,希望孩子能够正常成长吧,等他长大以后,作为老父亲的我能够把自己亲身体会到一些先进的理念和知识体系传授给他。
project
本周的project是完全任意发挥,就是利用jack语言自己实现一个小游戏之类的,我用jack语言实现了一个贪吃蛇的小游戏,感觉还是非常有意思的。在jack语言中,重新设计了缓存和随机数生成器,题目本身不难,但是如果想设计出来有意思的还是不太容易。大概编码加调试花了两个半天的时间,现在时常感觉有非常多有意思的课程和知识可以学习,但是因为家庭的原因,根本没有时间能够话费在自己的爱好和兴趣上。今天读书的时候,书中写到了一句话,叫做四个责任,“对自己负责,对家庭负责,对工作负责,对社会负责”,这是依次递进的关系,从小到大的原则。
最终完成的project代码如下:
代码
游戏运行截图如下:
本身project难度不大,但是如何发挥出聪明才智,看到好多老外真心有创意,利用jack语言做了许多非常有意思的游戏,记得映像比较深刻的,有人做了个射击游戏,还有人做了个汉诺塔的游戏。
在此项目完成过程,主要就是重新设计了循环队列之类的。
- 循环队列实现
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91/* GluttonousSnake */
/* created by mike meng @ 2020.10.3
* email: mml1106@126.com
*/
class Queue {
field Array buffer;
field int capbility;
field int rear;
field int front;
field int length;
constructor Queue new(int size){
let capbility = size;
let front = 0;
let rear = 0;
let buffer = Memory.alloc(size);
let length = 0;
return this;
}
method void dispose(){
do buffer.dispose();
do Memory.deAlloc(this);
return;
}
method boolean isEmpty(){
return (rear = front);
}
method int size(){
return length;
}
method boolean isFull(){
var int check;
let check = Snake.mod(rear + 1,capbility);
return (check = front);
}
method boolean push_back(int val){
/*check the Queue is Full*/
if(isFull()){return false;}
let length = length + 1;
let buffer[rear] = val;
let rear = Snake.mod(rear + 1,capbility);
return true;
}
method boolean push_front(int val){
/*check the Queue is Full*/
if(isFull()){ return false;}
let length = length + 1;
let front = Snake.mod(front - 1 + capbility,capbility);
let buffer[front] = val;
return true;
}
method int pop_front(){
var int res;
if(isEmpty()){return -1;}
let res = buffer[front];
let front = Snake.mod(front + 1,capbility);
let length = length - 1;
return res;
}
method int pop_back(){
var int res;
/*check the Queue is Full*/
if(isEmpty()){return -1;}
let length = length - 1;
let rear = Snake.mod(rear - 1 + capbility,capbility);
return buffer[rear];
}
method void print(){
var int curr;
var int data;
/*debug all elements of the queue*/
let curr = length;
while(~(curr = 0)){
let data = pop_front();
do Output.printInt(data);
do Output.printChar(32); // prints a space
do push_back(data);
let curr = curr - 1;
}
return;
}
} - 随机数生成器: 这个可以在维基百科上找到线性方法生成简单的随机数的原理
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/*
Random Number Generator
Original author: Taylor Wacker
Modified by: Connor McKay
This is a pseudo random number generator that uses the
Linear Congruential Generator (LCG) to generate random
numbers.
*/
class Random {
static int x;
/*
Sets a new seed value.
*/
function void seed(int seed) {
let x = seed;
return;
}
/*
Returns a mod b. b must be positive.
*/
function int mod(int a, int b) {
if (a < 0) {
let a = -a;
}
while ((a + 1) > b) {
let a = a - b;
}
return a;
}
/*
Returns the next random number. Can be negative or positive.
*/
function int next() {
let x = Random.mod(7919 + (17*x),7919);
return x;
}
/*
Returns a random value between x (inclusive) and y (non-inclusive).
y must be greater than x.
*/
function int between(int x, int y) {
var int diff;
let diff = y - x;
return Random.mod(Random.next(), diff) + x;
}
} - 游戏的逻辑主体部分,不过写的过于复杂点了,其实还可以写的更简单一些,或者完成俄罗斯方块游戏之类的。
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267/* GluttonousSnake */
/* created by mike meng @ 2020.10.3
* email: mml1106@126.com
*/
class Snake {
field int row;//
field int col;//width
field int bsize;//square size
field Array head; /*snake Queuehead*/
field Queue foods; /*current foods*/
field int foodCount; // food number count
field Queue body; // current snake body;
field int speed; //snake speed
field Array mask;// direction mask
field int direction; /*-1: none, 0: up, 1: right, 2 : down, 3 : left*/
field int state; //current state;
field int score; //current score;
/** Constructs a new square with a given location and size. */
constructor Snake new(int w,int h){
var int i;
var int val;
/*matrix height & width*/
let row = h;
let col = w;
let bsize = 16;
/*game state: 0: runing, 1: game over*/
let state = 0;
/*snake head*/
let head = Array.new(2);
let head[0] = 0;
let head[1] = 0;
do drawBlock(0,0);
/*snake foods*/
let foods = Queue.new(100);
let i = 20;
do Random.seed(1);
while(~(i = 0)){
let val = Snake.mod(Random.next(),row*col);
do foods.push_back(val);
//do Snake.debug(val);
do drawFood(val);
let i = i - 1;
}
/*snake body*/
let body = Queue.new(row*col);
do body.push_back(0);
/*snake direction*/
/*-1: none, 0: up, 1: right, 2 : down, 3 : left*/
let mask = Array.new(5);
let direction = 1;
let mask[0] = -1;
let mask[1] = 0;
let mask[2] = 1;
let mask[3] = 0;
let mask[4] = -1;
/*snake score*/
let score = 0;
return this;
}
/** Disposes this square. */
method void dispose() {
do head.dispose();
do foods.dispose();
do body.dispose();
do mask.dispose();
do Memory.deAlloc(this);
return;
}
/*math mod function*/
function int mod(int m,int n){
return (m - ((m/n)*n));
}
/** game is over**/
method boolean isOver(){
return state = 1;
}
/** snake move up **/
method void moveUp() {
if(direction = 2){return;}
let direction = 0;
return;
}
/** snake move down **/
method void moveDown() {
if(direction = 0){return;}
let direction = 2;
return;
}
/** snake move left **/
method void moveLeft() {
if(direction = 1){return;}
let direction = 3;
return;
}
/** snake move right **/
method void moveRight() {
if(direction = 3){return;}
let direction = 1;
return;
}
/*draw a block*/
method void drawBlock(int rx,int cx){
do Screen.setColor(true);
do Screen.drawRectangle(cx*16,(rx+2)*16,cx*16 + 15,(rx+2)*16 + 15);
return;
}
/*erase a block*/
method void eraseBlock(int location){
var int rx;
var int cx;
let rx = location/col;
let cx = Snake.mod(location,col);
do Screen.setColor(false);
do Screen.drawRectangle(cx*16,(rx+2)*16,cx*16 + 15,(rx+2)*16 + 15);
return;
}
/*debug*/
function void debug(int x){
do Screen.setColor(true);
do Output.moveCursor(0,0);
do Output.printInt(x);
return;
}
/*draw a food*/
method void drawFood(int location){
var int rx;
var int cx;
let rx = location/col;
let cx = Snake.mod(location,col);
do Screen.setColor(true);
do Screen.drawLine(cx*16,(rx+2)*16,cx*16 + 15,(rx+2)*16);
do Screen.drawLine(cx*16,(rx+2)*16,cx*16,(rx+2)*16 + 15);
do Screen.drawLine(cx*16,(rx+2)*16,cx*16 + 15,(rx+2)*16 + 15);
do Screen.drawLine(cx*16,(rx+2)*16 + 15,cx*16 + 15,(rx+2)*16 + 15);
do Screen.drawLine(cx*16+15,(rx+2)*16,cx*16 + 15,(rx+2)*16 + 15);
do Screen.drawLine(cx*16+15,(rx+2)*16,cx*16,(rx+2)*16 + 15);
return;
}
/*draw snake head*/
method void drawHead(int rx,int cx){
do Screen.setColor(true);
do Screen.drawLine(cx*16,(rx+2)*16,cx*16 + 15,(rx+2)*16 + 15);
do Screen.drawLine(cx*16+15,(rx+2)*16,cx*16,(rx+2)*16 + 15);
return;
}
/*snake move one step*/
method boolean move() {
var int x;
var int y;
var int i;
var int val;
var int rx;
var int cx;
var boolean eat;
if(isOver()){ return false;}
if(direction < 0){ return true;}
/*get the current move location*/
let x = head[0] + mask[direction];
let y = head[1] + mask[direction + 1];
let i = 0;
/*check the snake will touch the edge*/
if((x < 0)|(y < 0)|(x = row)|(y = col)){
let state = 1;
return false;
}
/*check the snake will touch the body*/
let i = body.size();
while(~(i = 0)){
let val = body.pop_front();
let i = i - 1;
let rx = val/col;
let cx = Snake.mod(val,col);
if((rx = x) & (cx = y)){
let state = 1;
return false;
}
do body.push_back(val);
}
if(isOver()){ return false;}
/*check the snake touch the foods*/
let i = foods.size();
while(~(i = 0)){
let i = i - 1;
let val = foods.pop_front();
let rx = val/col;
let cx = Snake.mod(val,col);
if((rx = x) & (cx = y)){
let eat = true;
let score = score + 1;
}else{
do foods.push_back(val);
}
}
/*move snake one step*/
let head[0] = x;
let head[1] = y;
do drawBlock(x,y);
do body.push_front(x*col + y);
if(~eat){
do eraseBlock(body.pop_back());
}else{
/*we can produce a random food for the snake*/
//do prodFood();
}
return true;
}
method int prodFood(){
var boolean valid;
var int location;
var int val;
var int i;
let valid = false;
while(~valid){
let location = Snake.mod(Random.next(),row*col);
let i = body.size();
let valid = true;
while(~(i=0)){
let val = body.pop_front();
do body.push_back(val);
if(val = location){
let valid = false;
}
}
}
do drawFood(location);
do foods.push_back(location);
return location;
}
/*get the game score*/
method int getScore(){
return score;
}
}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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96/* GluttonousSnake */
/* created by mike meng @ 2020.10.3
* email: mml1106@126.com
*/
class SnakeGame {
field Snake snake; // the square of this game
field int width; // the current score of the snake game.
field int height; // the current score of the snake game.
field int speed; // the current move speed of the snake game.
/** Constructs a new Square Game. */
constructor SnakeGame new(int w,int h) {
let snake = Snake.new(w,h);
let speed = 1; // initial state is no movement
return this;
}
/** Disposes this game. */
method void dispose() {
do snake.dispose();
do Memory.deAlloc(this);
return;
}
/**speed up game**/
method void speedUp(){
let speed = speed + 1;
return;
}
/**speed down game**/
method void speedDown(){
if(speed = 1) {return;}
let speed = speed - 1;
return;
}
/** Moves the square in the current direction. */
method void moveSnake() {
do snake.move();
do Sys.wait(5); // delays the next movement
return;
}
method void sleep(int seconds){
do Sys.wait(200/speed);
return;
}
method void drawBackgroud(){
do Screen.setColor(true);
do Screen.drawLine(0,0,0,255);
do Screen.drawLine(0,0,511,0);
do Screen.drawLine(511,0,511,255);
do Screen.drawLine(0,255,511,0255);
do Screen.drawLine(0,30,511,30);
return;
}
method void drawText(){
do Screen.setColor(true);
do Output.moveCursor(0,20);
do Output.printString("Your score is :");
do Output.printInt(snake.getScore());
if(snake.isOver()){
do Output.moveCursor(1,24);
do Output.printString("Game Over!");
}
return;
}
/** Runs the game: handles the user's inputs and moves the square accordingly */
method void run() {
var char key; // the key currently pressed by the user
var boolean exit;
let exit = false;
while (~exit) {
// waits for a key to be pressed
do sleep(1);
do drawBackgroud();
do moveSnake();
do drawText();
let key = Keyboard.keyPressed();
if (key = 81) { let exit = true; } // q key
if (key = 43) { do speedUp();} // speed up
if (key = 45) { do speedDown();} // speed down
if (key = 131) { do snake.moveUp();} // up arrow
if (key = 133) { do snake.moveDown(); } // down arrow
if (key = 130) { do snake.moveLeft(); } // left arrow
if (key = 132) { do snake.moveRight(); } // right arrow
} // while
return;
}
}
【build a computer】 project 9
http://example.com/2026/09/08/公开课学习/82/