活在控制檯的貪喫蛇遊戲
忽然想寫個貪喫蛇小遊戲。
實現起來很簡單,用隊列保存小蛇的身體座標。在位置座標中小蛇頭部的下一步位置激活,尾部位置取消激活實現小蛇移動,實現捕食效果則尾部不取消激活小蛇長度增加。
import java.util.Scanner;
public class SnakeTest {
private Scanner sc;
private int r;// 隨機數值
private int d;// 輸入的數字
private int[][] dir = { { 1, 0 }, { 0, -1 }, { -1, 0 }, { 0, 1 } };// 方向數組,下,左,上,右
private final int width = 5;// 寬
private final int height = 5;// 高
private int[][] pos;// 位置數組
private int head_x, head_y;// 頭部座標
private int snake_length = 2;// 初始場長度
private int cur_dir;// 當前方向
private int food_x, food_y;// 食物座標
MyLink link;// 隊列對象
public static void main(String[] args) {
System.out.println("【貪喫蛇】");
SnakeTest st = new SnakeTest();
st.initGame();
st.runGame();
}
private void initGame() {
sc = new Scanner(System.in);// 實例化輸入類
// 隨機初始化起源點及方向
r = (int) (Math.random() * (width * height));
head_x = r % width;
head_y = r / width;
cur_dir = (int) (Math.random() * 4);
// 初始化座標數組以及實例化自定義的隊列類
pos = new int[width][height];
link = new MyLink(width, height);
// 將第一個座標放進隊列並激活位置座標
link.in(head_y, head_x);
pos[head_y][head_x] = 1;
// 根據起源座標直線延伸至設定長度,因此最大長度爲width或height
for (int i = 1; i < snake_length; i++) {
head_x += dir[cur_dir][1];
head_y += dir[cur_dir][0];
// 檢查並處理數組以及遊戲邊界
check();
link.in(head_y, head_x);
pos[head_y][head_x] = 1;// 激活
}
// 初始化食物座標
randomFood();
}
private void runGame() {
while (true) {
draw();// 打印在控制檯
d = sc.nextInt();
// 0 1 2 3 下 上 右 左
control(d);
head_x += dir[cur_dir][1];
head_y += dir[cur_dir][0];
// 檢查並處理數組以及遊戲邊界
check();
// 如果咬到自己遊戲失敗
if (pos[head_y][head_x] == 8) {// 喫到東西 長度+1
snake_length++;
link.in(head_y, head_x);// 把頭部座標塞進隊列
pos[head_y][head_x] = 1;// 將頭部座標激活
// 是否大滿貫
if (snake_length == width * height) {
draw();
System.out.println("勝利!");
return;
}
randomFood();// 隨機生成食物座標
} else {// 否則隊列操作,實現小蛇移動
int[] tail = link.out();// 隊列將尾部座標移除;
pos[tail[0]][tail[1]] = 0;// 取消激活尾部座標
if (pos[head_y][head_x] == 1) {
System.out.println("咬到自己啦!\n小蛇長度:"+snake_length);
return;
}
link.in(head_y, head_x);// 把頭部座標塞進隊列
pos[head_y][head_x] = 1;// 將頭部座標激活
}
}
}
private void control(int d) {
if (cur_dir != 2 && d == 0)// 當前方向不允許爲向上情況允許向下轉彎,下同
cur_dir = 0;
else if (cur_dir != 3 && d == 1)
cur_dir = 1;
else if (cur_dir != 0 && d == 2)
cur_dir = 2;
else if (cur_dir != 1 && d == 3)
cur_dir = 3;
}
private void check() {
if (head_x < 0)
head_x = width - 1;
else if (head_x == width)
head_x = 0;
if (head_y < 0)
head_y = height - 1;
else if (head_y == height)
head_y = 0;
}
private void draw() {
System.out.println("數字: [0]下,[1]左,[2]上,[3]右");
System.out.printf("頭部座標:第%d行,第%d列\n", head_y + 1, head_x + 1);
System.out.print("當前方向爲:");
switch (cur_dir) {
case 0:
System.out.println("下");
break;
case 1:
System.out.println("左");
break;
case 2:
System.out.println("上");
break;
case 3:
System.out.println("右");
}
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
System.out.printf("%-2s", pos[i][j]);
}
System.out.println();
}
}
private void randomFood() {
while (pos[food_y][food_x] != 0) {
r = (int) (Math.random() * (width * height));
food_y = r / width;
food_x = r % width;
}
pos[food_y][food_x] = 8;
}
}
class MyLink {
private int[][] link;
private int head_index;
private int tail_index;
public MyLink(int x, int y) {
link = new int[x * y][2];
}
public void in(int x, int y) {
link[head_index][0] = x;
link[head_index][1] = y;
head_index++;
head_index %= link.length;
}
public int[] out() {
int[] index = { link[tail_index][0], link[tail_index][1] };
tail_index++;
tail_index %= link.length;
return index;
}
}