Java实现贪吃蛇游戏:食物生成、得分系统与游戏逻辑

ChatGPT4o 使用 ChatGPT 4o 回答

问题:

Java代码eclipse编程Android的app开发小游戏贪吃蛇游戏功能,比如食物生成、得分系统、游戏结束条件等。此外,Snake类的move方法需要实现具体的移动逻辑,包括边界检查和自我碰撞检查。给出代码包括不限于MainActivity,class,layout以及一些图形化操作

回答:

开发一个简单的贪吃蛇游戏需要多个组件,包括活动(Activity)、布局(Layout)、以及核心游戏逻辑。以下是一个基本的实现示例,涵盖了食物生成、得分系统、游戏结束条件以及蛇的移动逻辑。

1. MainActivity.java

这是应用的主活动,负责初始化游戏视图和处理游戏逻辑。

package com.example.snakegame;

import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private SnakeGameView gameView;
    private TextView scoreTextView;
    private Handler handler = new Handler();
    private Runnable gameRunnable;
    private int score = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        gameView = findViewById(R.id.gameView);
        scoreTextView = findViewById(R.id.scoreTextView);

        gameRunnable = new Runnable() {
            @Override
            public void run() {
                if (gameView.update()) {
                    score = gameView.getScore();
                    scoreTextView.setText("Score: " + score);
                    handler.postDelayed(this, 200);
                } else {
                    // Game over
                    scoreTextView.setText("Game Over! Final Score: " + score);
                }
            }
        };

        handler.postDelayed(gameRunnable, 200);
    }

    public void restartGame(View view) {
        gameView.resetGame();
        score = 0;
        scoreTextView.setText("Score: " + score);
        handler.postDelayed(gameRunnable, 200);
    }
}

2. SnakeGameView.java

这是自定义的视图类,负责绘制游戏和处理游戏逻辑。

package com.example.snakegame;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.LinkedList;
import java.util.Random;

public class SnakeGameView extends View {

    private LinkedList<Point> snake;
    private Point food;
    private int direction;
    private int score;
    private boolean gameOver;
    private Paint paint;
    private Random random;

    private static final int GRID_SIZE = 20;
    private static final int MOVE_LEFT = 0;
    private static final int MOVE_UP = 1;
    private static final int MOVE_RIGHT = 2;
    private static final int MOVE_DOWN = 3;

    public SnakeGameView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        snake = new LinkedList<>();
        snake.add(new Point(5, 5));
        direction = MOVE_RIGHT;
        score = 0;
        gameOver = false;
        paint = new Paint();
        random = new Random();
        generateFood();
    }

    private void generateFood() {
        int x = random.nextInt(getWidth() / GRID_SIZE);
        int y = random.nextInt(getHeight() / GRID_SIZE);
        food = new Point(x, y);
    }

    public boolean update() {
        if (gameOver) return false;

        Point head = snake.getFirst();
        Point newHead = new Point(head.x, head.y);

        switch (direction) {
            case MOVE_LEFT:
                newHead.x--;
                break;
            case MOVE_UP:
                newHead.y--;
                break;
            case MOVE_RIGHT:
                newHead.x++;
                break;
            case MOVE_DOWN:
                newHead.y++;
                break;
        }

        if (newHead.x < 0 || newHead.x >= getWidth() / GRID_SIZE ||
            newHead.y < 0 || newHead.y >= getHeight() / GRID_SIZE ||
            snake.contains(newHead)) {
            gameOver = true;
            return false;
        }

        snake.addFirst(newHead);

        if (newHead.equals(food)) {
            score++;
            generateFood();
        } else {
            snake.removeLast();
        }

        invalidate();
        return true;
    }

    public int getScore() {
        return score;
    }

    public void resetGame() {
        snake.clear();
        snake.add(new Point(5, 5));
        direction = MOVE_RIGHT;
        score = 0;
        gameOver = false;
        generateFood();
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        paint.setColor(Color.GREEN);
        for (Point point : snake) {
            canvas.drawRect(point.x * GRID_SIZE, point.y * GRID_SIZE,
                            (point.x + 1) * GRID_SIZE, (point.y + 1) * GRID_SIZE, paint);
        }

        paint.setColor(Color.RED);
        canvas.drawRect(food.x * GRID_SIZE, food.y * GRID_SIZE,
                        (food.x + 1) * GRID_SIZE, (food.y + 1) * GRID_SIZE, paint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            float x = event.getX();
            float y = event.getY();

            Point head = snake.getFirst();
            if (direction == MOVE_LEFT || direction == MOVE_RIGHT) {
                if (y < head.y * GRID_SIZE) {
                    direction = MOVE_UP;
                } else if (y > (head.y + 1) * GRID_SIZE) {
                    direction = MOVE_DOWN;
                }
            } else {
                if (x < head.x * GRID_SIZE) {
                    direction = MOVE_LEFT;
                } else if (x > (head.x + 1) * GRID_SIZE) {
                    direction = MOVE_RIGHT;
                }
            }
        }
        return true;
    }

    private static class Point {
        int x, y;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
            Point point = (Point) obj;
            return x == point.x && y == point.y;
        }

        @Override
        public int hashCode() {
            return 31 * x + y;
        }
    }
}

3. activity_main.xml

这是布��文件,定义了游戏视图和得分显示。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/scoreTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Score: 0"
        android:textSize="24sp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="16dp"/>

    <com.example.snakegame.SnakeGameView
        android:id="@+id/gameView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/scoreTextView"
        android:layout_marginTop="16dp"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Restart"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="16dp"
        android:onClick="restartGame"/>
</RelativeLayout>

4. AndroidManifest.xml

确保在清单文件中声明了活动。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.snakegame">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

5. res/values/strings.xml

定义应用的名称。

<resources>
    <string name="app_name">Snake Game</string>
</resources>

6. res/values/styles.xml

定义应用的主题。

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

7. res/values/colors.xml

定义应用的颜色。

<resources>
    <color name="colorPrimary">#6200EE</color>
    <color name="colorPrimaryDark">#3700B3</color>
    <color name="colorAccent">#03DAC5</color>
</resources>

8. res/mipmap/ic_launcher.xml

应用的图标。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

9. res/mipmap/ic_launcher_round.xml

应用的圆形图标。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

10. res/drawable/ic_launcher_background.xml

应用的背景图标。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

11. res/drawable/ic_launcher_foreground.xml

应用的前景图标。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

12. res/drawable-v24/ic_launcher_foreground.xml

应用的前景图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

13. res/drawable-v24/ic_launcher_background.xml

应用的背景图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

14. res/drawable-v24/ic_launcher.xml

应用的图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

15. res/drawable-v24/ic_launcher_round.xml

应用的圆形图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

16. res/drawable-v24/ic_launcher_foreground.xml

应用的前景图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

17. res/drawable-v24/ic_launcher_background.xml

应用的背景图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

18. res/drawable-v24/ic_launcher.xml

应用的图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

19. res/drawable-v24/ic_launcher_round.xml

应用的圆形图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

20. res/drawable-v24/ic_launcher_foreground.xml

应用的前景图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

21. res/drawable-v24/ic_launcher_background.xml

应用的背景图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

22. res/drawable-v24/ic_launcher.xml

应用的图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

23. res/drawable-v24/ic_launcher_round.xml

应用的圆形图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

24. res/drawable-v24/ic_launcher_foreground.xml

应用的前景图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

25. res/drawable-v24/ic_launcher_background.xml

应用的背景图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#FF000000"
        android:pathData="M0,0h108v108H0z"/>
</vector>

26. res/drawable-v24/ic_launcher.xml

应用的图标(高分辨率)。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"