贪吃蛇代码
大约 5 分钟
C 语言 和 Java 版 贪吃蛇代码
C
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <graphics.h>
#include <mmstream.h>
#pragma comment(lib,"winmm.lib")
/*
内容:贪吃蛇
知识点:结构体、循环、函数、easyx、数组
做界面:创建一个图形,图形窗口
*/
//蛇的最大节数
#define SNAKE_NUM 500
//初识化方向(枚举)
enum DIR
{
UP,
DOWN,
LEFT,
RIGHT,
};
//蛇的结构
struct Snake
{
int size;//蛇的节数
int dir;//蛇的方向
int speed;//蛇的速度
POINT coor[SNAKE_NUM]; //坐标
}snake;
//食物结构
struct Food
{
int x; //食物位置
int y;
int r; //食物大小
int eatgrade;//食物分数
bool flag; //食物是否被吃
DWORD color; //食物颜色
}food;
//死亡提示框
HWND hwnd = NULL;
//数据初始化
void GameInit()
{
//初始化图形窗口initgraph
initgraph(640, 480);
//播放背景音乐
mciSendString("open ./7895.mp3 alias BGM", 0, 0, 0);
mciSendString("play BGM repeat", 0, 0, 0);
//设置随机数种子 GetTickCount()是用来获取系统开机,到现在缩经过的毫秒数
srand(GetTickCount());
//初始化蛇
snake.size = 3;//一开始蛇的节数
snake.speed = 10;
snake.dir=RIGHT;
for (int i = 0; i < snake.size; i++)
{
snake.coor[i].x = 40-10*i;
snake.coor[i].y = 10;
}
//初始化食物
//随机函数:随机生成一个整数,如果没有设置随机的种子,每次生成的都是固定的整数
//设置种子要头文件stdlib.h 一般把时间设置为种子,因为时间是变化的
food.x = rand() % 640;
food.y = rand() % 480;
food.color = RGB(184, 95, 175/*rand() % 256, rand() % 256, rand() % 256*/);
food.r = 6;
food.flag = true;
food.eatgrade = 0;
}
//绘制窗口
void GameDraw()
{
//双缓冲绘图
BeginBatchDraw;
//设置背景颜色
setbkcolor(RGB(65, 131, 168));
cleardevice();
//绘制蛇
for (int i = 0; i < snake.size; i++)
{
/*使蛇和食物变色
setfillcolor(RGB(rand() % 255, rand() % 255, rand() % 255));
*/
solidcircle(snake.coor[i].x, snake.coor[i].y, 5);
}
//绘制食物
if (food.flag)
{
solidcircle(food.x, food.y, food.r);
}
EndBatchDraw();
}
//移动蛇
void snakeMove()
{
//让第2个蛇身跟着第一个移动
for (int i = snake.size - 1; i > 0; i--)
{
snake.coor[i] = snake.coor[i - 1];
}
//蛇头移动发生改变
switch (snake.dir)
{
case UP:
snake.coor[0].y-=snake.speed;
//让蛇可以穿墙回来
if (snake.coor[0].y +10 <= 0)
{
snake.coor[0].y = 480;
}
break;
case DOWN:
snake.coor[0].y+= snake.speed;
if (snake.coor[0].y - 10 >= 480)
{
snake.coor[0].y = 0;
}
break;
case LEFT:
snake.coor[0].x-= snake.speed;
if (snake.coor[0].x + 10 <= 0)
{
snake.coor[0].x = 640;
}
break;
case RIGHT:
snake.coor[0].x+= snake.speed;
if (snake.coor[0].x - 10 >= 640)
{
snake.coor[0].x = 0;
}
break;
}
}
//通过按键改变蛇的方向
void keyControl()
{
//判断有没有按键
if (_kbhit())
{
//上下左右键值分别为:72 80 75 77
switch (_getch())
{
case'w':
case'W':
case 72:
//改变方向,使向上时不能向下
if (snake.dir != DOWN)
{
snake.dir = UP;
}
break;
case's':
case'S':
case 80:
if (snake.dir != UP)
{
snake.dir = DOWN;
}
break;
case'a':
case'A':
case 75:
if (snake.dir != RIGHT)
{
snake.dir = LEFT;
}
break;
case'd':
case'D':
case 77:
if (snake.dir != LEFT)
{
snake.dir = RIGHT;
}
break;
//游戏暂停
case ' ':
while (1)
{
if (_getch() == ' ')
return;
}
break;
}
}
}
//判断是否吃食物
void EatFood()
{
if (food.flag && snake.coor[0].x >= food.x - food.r && snake.coor[0].x <= food.x + food.r
&& snake.coor[0].y >= food.y - food.r && snake.coor[0].y <= food.y + food.r)
{
food.flag = false;
snake.size++;
food.eatgrade += 10;
}
//食物消失,则重新生成食物
if (!food.flag)
{
food.x = rand() % 640;
food.y = rand() % 480;
food.color = RGB(184, 95, 175);
food.r = 6;
food.flag = true;
}
}
//得分
void showGrade()
{
BeginBatchDraw;
char grade[100] = "";
sprintf(grade, "%d", food.eatgrade);
setbkmode(TRANSPARENT);
settextcolor(LIGHTBLUE);
outtextxy(560, 20, "分数:");
outtextxy(560 + 50, 20, grade);
EndBatchDraw();
}
//蛇死亡
int snakeDie()
{
/*用时取消即可
//玩法2,撞墙死
if (snake.coor[0].x > 640 || snake.coor[0].x < 0 ||
snake.coor[0].y>480 || snake.coor[0].y < 0)
{
outtextxy(200, 200,"你撞墙啦!");
MessageBox(hwnd, "Game Over!","撞墙警告", MB_OK);
return 1;
}
*/
//通用代码:自己吃自己
for (int i = 1; i < snake.size; i++)
{
if (snake.coor[0].x == snake.coor[i].x &&
snake.coor[0].y == snake.coor[i].y )
{
outtextxy(200, 200, "你撞到自己啦!");
MessageBox(hwnd, "Game Over!", "自杀警告", MB_OK);
return 1;
}
}
return 0;
}
int main()
{
//调用
GameInit();
//防止卡死
while (1)
{
GameDraw();
if (snakeDie())
{
break;
}
snakeMove();
keyControl();
EatFood();
showGrade();
Sleep(80);
}
getchar;//防止闪屏
return 0;
}
JAVA
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Random;
public class SnakeGame extends JPanel implements ActionListener {
private static final int WIDTH = 400;
private static final int HEIGHT = 400;
private static final int CELL_SIZE = 20;
private static final int INITIAL_SNAKE_LENGTH = 3;
private final ArrayList<Point> snake;
private Point food;
private int direction;
private boolean isGameOver;
private boolean isGameRunning;
private Timer timer;
private final JButton startButton;
private final JButton restartButton;
private int score;
private final Point scorePosition;
public SnakeGame() {
snake = new ArrayList<>();
direction = KeyEvent.VK_UP;
isGameRunning = false;
isGameOver = false;
food = new Point(0, 0);
score = 0;
scorePosition = new Point(10, 20);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setBackground(Color.BLACK);
setFocusable(true);
addKeyListener(new MyKeyAdapter());
startButton = new JButton("Start Game");
restartButton = new JButton("Restart Game");
startButton.addActionListener(e -> startGame());
restartButton.addActionListener(e -> restartGame());
restartButton.setVisible(false);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(startButton, gbc);
gbc.gridy = 1;
add(restartButton, gbc);
}
private void startGame() {
if (!isGameRunning) {
snake.clear();
for (int i = 0; i < INITIAL_SNAKE_LENGTH; i++) {
snake.add(new Point(WIDTH / 2, HEIGHT / 2 + i * CELL_SIZE));
}
spawnFood();
isGameOver = false;
direction = KeyEvent.VK_UP;
score = 0;
isGameRunning = true;
if (timer != null) {
timer.stop();
}
timer = new Timer(100, this);
timer.start();
setFocusable(true);
requestFocusInWindow();
}
startButton.setVisible(false);
}
private void restartGame() {
isGameRunning = false;
isGameOver = false;
snake.clear();
food = new Point(0, 0);
startButton.setVisible(true);
restartButton.setVisible(false);
score = 0;
}
private void spawnFood() {
Random random = new Random();
int x, y;
do {
x = random.nextInt(WIDTH / CELL_SIZE) * CELL_SIZE;
y = random.nextInt(HEIGHT / CELL_SIZE) * CELL_SIZE;
} while (isFoodOnSnake(x, y));
food = new Point(x, y);
}
private boolean isFoodOnSnake(int x, int y) {
for (Point segment : snake) {
if (segment.x == x && segment.y == y) {
return true;
}
}
return false;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (isGameOver) {
gameOver(g);
return;
}
drawSnake(g);
drawFood(g);
drawScore(g);
}
private void drawSnake(Graphics g) {
g.setColor(Color.GREEN);
for (Point segment : snake) {
g.fillRect(segment.x, segment.y, CELL_SIZE, CELL_SIZE);
}
}
private void drawFood(Graphics g) {
g.setColor(Color.RED);
g.fillRect(food.x, food.y, CELL_SIZE, CELL_SIZE);
}
private void drawScore(Graphics g) {
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.BOLD, 16));
g.drawString("Score: " + score, scorePosition.x, scorePosition.y);
}
private void move() {
Point newHead = snake.get(0);
if (direction == KeyEvent.VK_LEFT) {
newHead = new Point(newHead.x - CELL_SIZE, newHead.y);
}
if (direction == KeyEvent.VK_RIGHT) {
newHead = new Point(newHead.x + CELL_SIZE, newHead.y);
}
if (direction == KeyEvent.VK_UP) {
newHead = new Point(newHead.x, newHead.y - CELL_SIZE);
}
if (direction == KeyEvent.VK_DOWN) {
newHead = new Point(newHead.x, newHead.y + CELL_SIZE);
}
snake.add(0, newHead);
if (newHead.equals(food)) {
spawnFood();
score += 1;
} else {
snake.remove(snake.size() - 1);
}
}
private void checkCollision() {
Point head = snake.get(0);
if (head.x < 0 || head.x >= WIDTH || head.y < 0 || head.y >= HEIGHT) {
isGameOver = true;
restartButton.setVisible(true);
}
for (int i = 1; i < snake.size(); i++) {
if (head.equals(snake.get(i))) {
isGameOver = true;
restartButton.setVisible(true);
break;
}
}
}
private void gameOver(Graphics g) {
g.setColor(Color.RED);
g.setFont(new Font("Arial", Font.BOLD, 48));
g.drawString("Game Over", WIDTH / 2 - 120, HEIGHT / 2 - 24);
}
private class MyKeyAdapter extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (!isGameRunning) {
return;
}
if ((key == KeyEvent.VK_LEFT) && (direction != KeyEvent.VK_RIGHT)) {
direction = KeyEvent.VK_LEFT;
}
if ((key == KeyEvent.VK_RIGHT) && (direction != KeyEvent.VK_LEFT)) {
direction = KeyEvent.VK_RIGHT;
}
if ((key == KeyEvent.VK_UP) && (direction != KeyEvent.VK_DOWN)) {
direction = KeyEvent.VK_UP;
}
if ((key == KeyEvent.VK_DOWN) && (direction != KeyEvent.VK_UP)) {
direction = KeyEvent.VK_DOWN;
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (!isGameOver && isGameRunning) {
move();
checkCollision();
repaint();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Snake Game");
SnakeGame snakeGame = new SnakeGame();
frame.add(snakeGame);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}