java控制檯貪喫蛇小遊戲(多線程版)

 

多線程版貪喫蛇

遊戲說明: 本遊戲運行在控制檯中,直接運行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();
	}
}

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章