Java程序辅导

C C++ Java Python Processing编程在线培训 程序编写 软件开发 视频讲解

客服在线QQ:2653320439 微信:ittutor Email:itutor@qq.com
wx: cjtutor
QQ: 2653320439
 1 
 
ECS Taster 2023 
Electronics and Computer Science Taster Course 
 
Southampton 
Snake 
An Introduction to 
Programming in JavaScript 
  
 2 
ECS Taster Lab Notes 
 
Southampton Snake 
An Introduction to Programming in JavaScript 
Version 1.6 (July 27, 2023) 
 
 
Written by 
Professor David Millard 
Web and Internet Science Research Group 
Electronics and Computer Science 
The University of Southampton 
 
dem@ecs.soton.ac.uk   
http://www.davidmillard.org  
@hoosfoos 
 
Acknowledgments 
Southampton Snake is based on original code published by 
thecodeplayer.com 
Front image ‘Ouroboros by Zanaq’ (CC BY-SA 2.5) available from 
https://commons.wikimedia.org/wiki/File:Ouroboros-Zanaq.png  
 
Copyright ©2023 The University of Southampton  
 
 
 
 
 
 
 3 
 
Introduction 
JavaScript is a programming language for writing code that runs within a web browser, 
it is used on millions of websites to create dynamic effects (such as menus that open and 
close, pictures that change, or forms that alter themselves according to what you type). 
However, it is a much more powerful language than this suggests, and in this lab we are 
going to look at how it can be used to create a simple game.  
Javascript is part of the C family of languages (alongside other big names such as C, C++, 
Objective C, C# and Java) and shares a lot of its syntax with these other languages. The C 
family of languages contain some of the most popular types of programming language, 
representing over 50% of all programming activity according to the TIOBE index1.  
Javascript is the most forgiving of all these languages, as it is weakly typed (does not care 
about the type of variables), is prototype-based (you can define and declare new objects 
at the same time), and supports a number of different programming paradigms (styles) 
including procedural and object-oriented. It means you can get a lot done relatively 
quickly. 
Javascript is therefore a fun language to learn and experiment with. It also helps that it 
requires no specialist tools (you can edit the files in any text editor, and run them in any 
browser).  
Introducing Snake 
Today we are going to look at a simple web browser game written in Javascript. The game 
is called Snake, and originates from arcade machines in the 1970s. It became well known 
in the 1990s when it was bundled with some of the early Nokia phones. The game is 
simple; you guide a snake around a grid. Food appears on the grid and when you collide 
with it your snake grows and you gain points. However, if you collide with the walls or 
with yourself the game ends. You can try a simple online version of the game here: 
 
 
1 The TIOBE Programming Community index is an indicator of the popularity of 
programming languages, based on the number of skilled engineers world-wide, courses 
and third party vendors (www.tiobe.com). 
 4 
 
http://playsnake.org 
Introducing Southampton Snake  
To run this lab you will need a web browser to load the web page (.html), and a text editor 
to edit the javascript file (.js); there is one on the University machines called Notepad++ 
that you can use for the lab. You should download the two files you need from the site 
below (you can do this by right clicking on them): 
http://bit.ly/soton-snake 
These files are: 
• snakecore.js – this is a JavaScript file that deals with all the drawing of the game, 
and sets up the main game loop. We will be looking at this file, but you do not have 
to edit it to complete the lab 
 
• snakepage.html – this is a HTML file that sets up the webpage. It also contains the 
JavaScript that runs the logic of the game. This logic is incomplete, and our job in 
this lab is to fix it, and learn some JavaScript along the way. 
Download both files to the same directory and then open a file explorer and change to that 
directory. The game should work as long as both files are in the same directory. Double-
click snakepage.html to load it into Internet Explorer. You should see the following: 
 
 5 
 
This is how our game begins. With a Snake that only moves right (reload the page to see 
it again as it disappears off the side of the grid), and food we cannot eat.  
Let’s see if we can change that… 
 6 
Exercise 1: Movement  
1.1. Bigger Snakes are Better Snakes 
Our first job is to increase the size of the Snake. But before we begin lets take a quick 
look at how this program works.  
Open snakecore.js in Notepad++ and take a moment to scan the file. Don’t worry if 
there is a lot of stuff here you don’t understand, but see if the following parts make sense 
to you: 
Towards the top of the file you will see some variables defined. Variables are named 
pieces of data. Southampton Snake has four of them of interest to us: 
 
var d;  //direction of the snake  
//(right, left, up, down) 
 
var food; //cell representing the current item of 
//food, has a food.x and food.y position 
 
var score; //the players current score 
 
var snake_array;  //an array of cells to make up the 
//snake, each has x and y position 
 
 
These are global variables, they can be referenced anywhere in the program, and they 
contain key bits of information about the game. Because the browser will ignore 
anything following a // we can use this to write comments in our code. Good comments 
are an essential part of good programming, and help remind us (and explain to others 
looking at the code) what the code does. Here they have been used to explain the 
purpose of each of those global variables. 
Notice that each atomic piece of code (these are called statements) ends with a ; In 
JavaScript these are optional as long as there is only one statement per line, but it is 
good practice to include them anyway. 
The code in Southampton Snake reads and writes these variables in order to control the 
game. Now let’s look at snakepage.html where most of this control code lives. 
Load snakepage.html into Notepad++, you should find a section of the document with 
script tags, this is where we can write our JavaScript. When the web browser encounters 
these tags it knows to run whatever is inside them as a script, rather than simply display 
them in the browser: 
 
To make it more manageable JavaScript can be broken down into reusable sections of 
code called functions. There is a function here that is called to create the snake when the 
game is first loaded, it currently looks like this: 
 function create_snake() 
 7 
 { 
  snake_array = []; //Empty array to start with 
   
  snake_array[0] = {x: 6, y:0};  
  snake_array[1] = {x: 5, y:0}; 
  snake_array[2] = {x: 4, y:0}; 
 } 
 
You may remember that snake_array was one of the four global variables defined in 
snakecore.js. It is an array of co-ordinate objects that defines the current position of the 
snake. The co-ordinate at index 0 represents the head. 
 
Explanation: Arrays 
 
In JavaScript (and many other languages) it is very useful to be able to create lists of 
things called arrays. We can refer to a particular item in the array using an index, this 
is a position in the array, assuming that the first item is always at position 0. So for 
example, if we wanted to store a shopping list we could write: 
 
var shop_list = [];    //create it as an empty array 
shop_list[0] = “cheese”; 
shop_list[1] = “milk”; 
shop_list[2] = “bread”; 
 
We can then use the same syntax to get the values out: 
 
var msg = “Remember to get ” + shop_list[0];   
 
Explanation: Objects 
 
In JavaScript (and lots of other languages) it is useful to collect several bits of data 
together into an object. Javascript is a prototype-based language, so you don’t have to 
define the possible objects first, you can just create them as you need them.  When you 
define an object you give each variable inside it a name and a value. For example, we 
might create an object to represent a person like this: 
 
var s1 = {name: “Alice”, age: 18, course: “CompSci”}; 
 
We can then access them (to read or write) using the dot operator: 
 
s1.age = 19;  //changes Alice’s age to 19 
var msg = “Hello “ + s1.name; 
 
In Southampton Snake we use objects to represent co-ordinates. So the snake is really an 
array of co-ordinate objects, where each co-ordinate is given an x and a y value. So the line 
of code: 
snake_array[0] = {x: 6, y:0}; 
Means we create a new object with an x value of 6, and a y value of 0 and we assign that 
object to the first position (the 0 index) of the snake_array. 
Try changing the initial position of the snake, by altering the x and y positions of these 
three co-ordinate objects. Remember that they should be in sequence, with the head of 
 8 
the snake in position 0.  Can you add new lines of code to make the snake longer? Change 
the code so that the snake starts out being 5 cells long. 
1.2. Steering the Snake 
Our first job in making this into a working program is to make it respond to user input. 
Southampton Snake is driven using the cursor (sometimes called the arrow) keys. Look 
in snakepage.html for the following code: 
//set it so that when the user hits a key the  
//keystroke function is called 
document.onkeydown = keystroke 
 
function keystroke(evt) 
{ 
 //TODO: fix this so that it changes the value of  
//direction according to the key 
} 
 
The first statement about document.onkeydown is an instruction to the browser to call 
the keystroke function whenever the user presses a key. The function is defined 
immediately afterwards, but currently does nothing, we need to change that by writing 
some code in the function. 
We can change the direction of the snake by altering the global variable called d that we 
saw earlier on.  
Try adding the following code to the keystroke function: 
d = “down”; 
Now reload the snakepage.html in your browser. You need to click inside the snake grid 
to give it focus (send it all the keystrokes), do this quickly once the game starts and then 
hit any key. The snake should change direction. Try setting it to one of the other valid 
directions (“up”, “right”, “left”). 
Of course the function really needs to respond to the key that was actually pressed, so we 
need to check what that was and act accordingly. We can use an if statement to do this, if 
statements are used when we want to check if something is true before we do something, 
they can also be combined in an if/else statement to choose between two alternatives 
(we’ll see that in just a moment).  
Instead of setting the value of d automatically to “down”, put the following code inside the 
keystroke function: 
if(evt.keyCode == 37) d = "left"; 
This looks at the keycode of the key that was pressed (a number that represents the key) 
and if it was a certain value changes the value of d. 
Try reloading snakepage.html. Now the snake should only respond when the left arrow 
key is pressed. 
  
 9 
Explanation: If statements 
 
An if statement is a simple check before another statement is executed. It has the form: 
 
if(check) statement; 
 
We can put anything as the check as long as it resolves to be either true or false, typically 
these are comparison operators that compare two variables, for example to check if 
there is enough money in an account before making a withdrawal: 
 
if(balance >= withdrawal) balance = balance – withdrawal; 
 
There are several built in comparison operators, including: 
 
if(a < b)  //if a is less than b 
if(a <= b) //if a is less than or equal to b 
if(a > b)  //if a is greater than b 
if(a >= b) //if a is greater than or equal to b 
if(a == b) //if a is equal to b 
if(a != b) //if a is not equal to b 
 
 
Add in the extra code to deal with the other three keys. The keycodes are as follows: 
• 37 is the left arrow 
• 38 is the up arrow 
• 39 is the right arrow 
• 40 is the down arrow 
Once you have done this you should have a moving snake! 
 
Exercise 2: Feeding  
2.1 A Hungry Snake is an Unhappy Snake 
These next steps will turn our program into something playable. We need to add the code 
that allows the snake to eat the food. This will require you to understand how the snake 
moves, as we will change this to allow it to grow. 
Look at snakepage.html, and in particular at the end of the update_snake function, you 
should see the following code: 
var newhead = {x: nx, y: ny}; 
 
snake_array.unshift(newhead); //adds the newhead as  
//the first cell 
snake_array.pop();   //pops out the last cell  
 
The first line creates a new co-ordinate object to represent the new head of the snake. 
The previous code in the function has calculated the positions of this (nx and ny). 
 10 
The second line calls the built in unshift function on the array. This inserts newhead at 
the start of the array (the head of the snake) and moves everything else along. 
The third line calls the built in pop function on the array. This removes the last item of 
the array (the end of the snake’s tail). 
Together this creates the illusion of movement, as new cells are continuously added to 
the head of the snake, as old cells are removed from the tail.  
Old snake:        
        
Newhead added (unshift):        
        
Tail removed (pop):        
        
Explanation: If/else statements 
 
An if/else statement is an extension of an if statement, just like an if statement it performs 
a check, but adds an additional statement that will be executed if the check fails.  
 
if(check) statement1; 
else statement2; 
 
Sometimes we want more than one statement to be executed, we can do this by grouping 
statements together using curly braces: 
 
if(check) { 
   statement1; 
   statement2; 
   ... 
} 
else { 
   statement3; 
   statement4; 
   ... 
} 
 
 
So to make the snake grow we have to change the code to check if the newhead is on a 
food item, and if it is we simply don’t pop the tail.  
To do this you need to use an if/else statement, with a more powerful check using 
something called logical operators.  
Rather than tell you what to type, this time see if you can figure out what to do based on 
the following written description (good luck, and ask for help if you get stuck!): 
1. Check to see whether the newhead is in the same position as the food, you can do 
this by comparing nx and ny to food.x and food.y 
2. If it is we increment the score variable by 1 
3. And then call the create_food() function to create a new item of food (at present 
this will always be in the same place) 
4. If it is not then we can forget about the score and food, and instead we can pop 
the tail (as the code does at the moment) 
 11 
Explanation: Logical conditions 
 
Whenever we perform an if, or an if/else we use a conditional operator such as >, <, 
==, !=. However we can build more complex conditions using logical operators.  For 
example, if we wanted to check if a variable a was between two values min and max we 
could use the && operator: 
 
if(a > min && a < max) statement; 
 
If we wanted to check if the variable b was equal to either c or d we could write: 
 
if(b == c || b == d) statement; 
 
(the | character is called a vertical bar, and it is normally on the same key as the 
backslash \) 
 
Conditional and logical operators combine in all sorts of ways to give us very powerful 
checks, you can use parenthesis () to make precedence clear. E.g: 
 
if((a > min && a < max) || a == b) statement; 
 
2.2 Food that Moves 
You should now have a snake that moves around and eats food to grow. There is one last 
thing to fix in this part, take a look at the create_food function: 
//Lets create the food now 
function create_food() 
{ 
 food = { 
  x: 10,  
  y: 10,  
 }; 
} 
As you can see the function currently always puts the food in the same cell (10,10). We 
need to change this to a random cell, but of course that has to be in a given range (there 
are two variables that store the extent of this range: maxx and maxy, they are defined at 
the top of snakecore.js if you want to take a look). 
Try replacing the fixed position with a random position between 0 and maxx, and 0 and 
maxy. It may help to know the following two built in functions: 
Math.random()generates a random number between 0 and 1. And 
Math.round(variable)will round the value in variable to the nearest whole integer 
(i.e. 2.49 becomes 2, 2.5 becomes 3). 
Don’t be afraid to ask for help if you get stuck! 
 
 
 12 
Exercise 3: The End Game  
3.1 Walled Snake Gardens 
Well done if you have got this far, it is now playable, but it’s not really a game as there is 
no challenge. The final step to making this a proper snake game is to add the two end 
game states, hitting a wall (the edge of the playable area) and hitting yourself (the head 
of the snake runs into the body). 
Let’s start out with the walls. Look in snakepage.html and find the function called 
check_collision, it should look like this: 
//returns true if the snake has hit a wall 
//or if it has hit itself (x and y are in the array) 
function check_collision(x, y, array) 
{ 
 return false; 
}  
 
This function is called every time that update_snake is run, take a quick look at how it 
is called there: 
 
//Now check for game over conditions 
if(check_collision(nx, ny, snake_array)) 
{ 
 //restart game 
 init(); 
 return; 
} 
 
The code uses check_collision as a check within an if statement, just like we did 
with conditional operators before (a > b etc.). It can do this because 
check_collision returns true or false. If it returns true this indicates that a collision 
has happened and that the game should be reset by calling the init function, and 
ending the update_snake function early using the keyword return. 
 
The problem is that the current check_collision function always returns false – 
indicating that a collision never happens. We need to change this. 
 
Alter the check_collision function so that it uses an if statement to see if the snake 
has hit a wall. Remember that the edges of the play area are defined by 0 and maxx, and 
0 and maxy. Helpfully the x and y variables passed into the function will contain the 
current x and y positions of the snake’s head.  
 
Note: It is very easy to get this wrong by one cell! So make sure you playtest your code 
by running the snake around the edge of the play area. Test all four edges. 
 
3.2 Ouroboros2 
 
2 Google is your friend! 
 13 
Almost there! The last piece of the game is to check to see if the snake’s head has hit its 
own body.  
The best way to do this is to use a for loop to check the x and y co-ordinate of each cell in 
the snake, if it is the same as the x and y co-ordinate of the head (i.e. the x and y variables 
passed into the check_collision function) then there has been a collision. 
Try adding a for loop to check_collision to do this. Remember that each slot in the array 
holds an object with an x and y position, so if i is the index you can use array[i].x and 
array[i].y to access them. You still need to check for the walls! 
Explanation: for loops and searching arrays 
 
A loop is a simple structure that repeats one or more lines of code over and over until 
a certain condition is met. There are several different kinds of loop in JavaScript 
including while loops, but for search through an array the most useful kind is a for loop. 
These use the following structure: 
 
for(initialise; check; change)  
{ 
   statement1; 
   statement2; 
   ... 
} 
 
Where initialise is a statement (usually used to set up a variable for counting) check is 
a condition that must remain true for the loop to continue to run, and change is a 
statement (usually to change the counting variable). For example, the following loop 
will run exactly 10 times: 
 
for(var i=0; i < 10; i = i + 1) 
 
So for loops are really useful when you know in advance how many times you want the 
loop to run. This means they are good for searching through arrays, as you know the 
length of the array in advance. It also means that you can use the counting variable (i in 
the example above) as the index for the array. For example: 
 
for(var i=0; i < array.length; i = i + 1)  
{ 
   if(array[i] == target) alert("Target found!"); 
} 
 
 
Extension: Game Design  
Software Engineering is not only about writing code, it is also about understanding the 
sorts of programs that you are writing, Southampton Snake is a game, so this means 
having some knowledge of Game Design.  
 
If you complete the Exercises in the lab (or if you want to carry on at home) then why 
not try and do some basic game design and extend Southampton Snake with new game 
mechanics. We will talk through some of the options in the lab, but if you want help in 
 14 
understanding the impact of your choices why not look at a classic framework for game 
design called Mechanics, Dynamics, Aesthetics (MDA)3.  
 
The core idea is that new Mechanics (rules or extensions you add) give rise to new 
Dynamics (play and system behavior) and impact on the overall Aesthetic (the user 
experience).  The MDA framework can help you think about how changes you make to 
the game impact on the user experience. 
 
You can get a great overview of MDA from the Extra Credits Channel on YouTube 
(although this focuses mainly on aesthetics); this channel is a great resource if you are 
interested in Games Design or the Games Industry: 
 
https://www.youtube.com/watch?v=uepAJ-rqJKA 
 
Thanks for getting this far, and good luck with building your extensions and exploring 
the power of programming! 
 
3 Robin Hunicke , Marc Leblanc , Robert Zubek (2004), MDA: A formal approach to game design and game 
research. In Proceedings of the Challenges in Games AI Workshop, Nineteenth National Conference of 
Artificial Intelligence