多線程版貪喫蛇
遊戲說明: 本遊戲運行在控制檯中,直接運行SnakeTest.java文件,就能在控制檯看到遊戲畫面,每按一個方向再按回車鍵就能控制蛇移動的方向
a:向左移動
d:向右移動
s:向下移動
w:向上移動
其他字母鍵:暫停
源代碼:
Snake.java
/**
* Created by LIUFANGDA310 on 2018-8-27.
*/
import java.util.LinkedList;
import java.util.Random;
import java.util.Scanner;
/**
* 多線程版本
* @author lfd
*有bug,不完美,比如蛇向左移動時,你讓他向右移動,此時會暫停
*界面剛出來時食物的位置跟你按方向鍵開始玩時的位置不一樣
*/
public class Snake {
private String[][] position = new String[24][30];//遊戲界面的的大小
private volatile LinkedList<String> snakeBody;
private static final int FOOD_NUM = 10;//默認初始化的食物數量
private volatile int speed = 600;//剛開始的移動速度
private static final int INCREASE_SPEED = 15; //每喫一個食物增加的速度
private volatile String operation;//用戶的操作
public Snake() {
initWall();
initSnake();
initFood(FOOD_NUM);
print();
}
public void move() {
MoveThread moveThread = new MoveThread();//創建一個線程
new Thread(moveThread).start();//啓動線程
while(true) {
Scanner sc = new Scanner(System.in);
operation = sc.next();//接收用戶的輸入
if(operation.length()>=2) {
operation = operation.substring(0,1);
}
}
}
//向上移動
public void moveUp() {
if((getX(0)-1 +","+ getY(0)).equals(snakeBody.get(1))) {//判斷蛇頭的方向是否是朝着自己身體的方向
return;
}
if(position[getX(0)-1][getY(0)].equals("■")) {//判斷是不是撞牆
System.out.println("你死了");
System.exit(0);
}
if(position[getX(0)-1][getY(0)].equals("●")) {//判斷有沒有喫到食物
snakeBody.addFirst(getX(0)-1+","+getY(0));
speed -= INCREASE_SPEED;//喫到一個食物,移動速度加快一些
initFood(1);//產生一個食物
}else {
//沒有喫到食物也沒有撞牆
snakeBody.addFirst(getX(0)-1+","+getY(0));//添加蛇頭
position[getX(snakeBody.size()-1)][getY(snakeBody.size()-1)] = " ";//移除蛇尾
snakeBody.removeLast();
}
print();//每次移動後都重新打印界面
}
//向下移動
public void moveDown() {
if((getX(0)+1 +","+ getY(0)).equals(snakeBody.get(1))) {
return;
}
if(position[getX(0)+1][getY(0)].equals("■")) {
System.out.println("你死了");
System.exit(0);
}
if(position[getX(0)+1][getY(0)].equals("●")) {
snakeBody.addFirst(getX(0)+1+","+getY(0));
speed -= INCREASE_SPEED;//喫到一個食物,移動速度加快一些
initFood(1);//產生一個食物
}else {
snakeBody.addFirst(getX(0)+1+","+getY(0));
position[getX(snakeBody.size()-1)][getY(snakeBody.size()-1)] = " ";
snakeBody.removeLast();
}
print();//每次移動後都重新打印界面
}
//向右移動
public void moveRight() {
if((getX(0)+ ","+ (getY(0)+1)).equals(snakeBody.get(1))) {
return;
}
if(position[getX(0)][getY(0)+1].equals("■")) {
System.out.println("你死了");
System.exit(0);
}
if(position[getX(0)][getY(0)+1].equals("●")) {
snakeBody.addFirst(getX(0)+","+(getY(0)+1));
speed -= INCREASE_SPEED;//喫到一個食物,移動速度加快一些
initFood(1);//產生一個食物
}else {
snakeBody.addFirst(getX(0)+","+(getY(0)+1));
position[getX(snakeBody.size()-1)][getY(snakeBody.size()-1)] = " ";
snakeBody.removeLast();
}
print();//每次移動後都重新打印界面
}
//向左移動
public void moveLeft() {
if((getX(0)+","+ (getY(0)-1)).equals(snakeBody.get(1))) {
return;
}
if(position[getX(0)][getY(0)-1].equals("■")) {
System.out.println("你死了");
System.exit(0);
}
if(position[getX(0)][getY(0)-1].equals("●")) {
snakeBody.addFirst(getX(0)+","+(getY(0)-1));
speed -= INCREASE_SPEED;
initFood(1);//產生一個食物
}else {
snakeBody.addFirst(getX(0)+","+(getY(0)-1));
position[getX(snakeBody.size()-1)][getY(snakeBody.size()-1)] = " ";
snakeBody.removeLast();
}
print();//每次移動後都重新打印界面
}
//得到某節蛇身的x座標
public int getX(int index) {
return Integer.parseInt(snakeBody.get(index).split(",")[0]);
}
//得到某節蛇身的y座標
public int getY(int index) {
return Integer.parseInt(snakeBody.get(index).split(",")[1]);
}
public void print() {
for(int i = 0; i< snakeBody.size(); i++) {
int x = getX(i);
int y = getY(i);
if(i==0) {
position[x][y] = "□"; //蛇頭是□
continue;
}
position[x][y] = "■";//身體是■
}
for(int i = 0;i<position.length;i++) {
System.out.println();
for(int j=0;j<position[i].length;j++) {
System.out.print(position[i][j]+" ");
}
}
}
//初始化牆
public void initWall() {
for(int i = 0;i<position.length;i++) {
for(int j=0;j<position[i].length;j++) {
position[i][j] = " ";
}
}
//初始化第一列和最後一列
for(int i=0;i<position.length;i++) {
position[i][0] = "■";
position[i][position[0].length-1] = "■";
}
//初始化第一行和最後一行
for(int i=0;i<position[0].length;i++) {
position[0][i] = "■";
position[position.length-1][i] = "■";
}
//在界面中產生一道牆
for(int i=0;i<position.length/2;i++) {
position[(position.length/4)+i][position[0].length/4] = "■";
}
}
//初始化蛇的位置
public void initSnake() {
snakeBody = new LinkedList<>();
snakeBody.add(position.length/2 + "," + (position[0].length/2));
snakeBody.add(position.length/2 + "," + (position[0].length/2+1));
snakeBody.add(position.length/2 + "," + (position[0].length/2+2));
snakeBody.add(position.length/2 + "," + (position[0].length/2+3));
}
/**
* 初始化食物數量
* @param number 食物數量
*/
public void initFood(int number) {
int flag = 0;
while(flag != number) {
int x = new Random().nextInt(position.length-1) + 1;
int y = new Random().nextInt(position[0].length-1) + 1;
if(position[x][y] == " ") {
position[x][y] = "●";
flag++;
}else {
continue;
}
}
}
//實現自動移動的線程類
class MoveThread implements Runnable{
@Override
public void run() {
while(true) {
if("w".equals(operation)) {//若用戶輸入的是w,向上移動
moveUp();
}else if("s".equals(operation)) {//若用戶輸入的是s,向下移動
moveDown();
}else if("a".equals(operation)) {//若用戶輸入的是a,向左移動
moveLeft();
}else if("d".equals(operation)) {//若用戶輸入的是d,向上移動
moveRight();
}else{
Thread.yield();//輸入除asdw之外的其他字母,暫停移動
}
try {
Thread.sleep(speed);//每次移動後讓線程睡眠一段時間
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
SnakeTest.java
public class SnakeTest {
public static void main(String[] args) {
Snake snake = new Snake();
snake.move();
}
}