键盘方向键控制蛇移动,随机生成身体颜色,食物会闪烁
蛇身及食物的一些属性:
// 坐标属性
struct point
{
int x;
int y;
};
// 蛇的属性
struct Snake
{
vector <point> xy; // 每节坐标
point next; // 为下一节预留的位置
vector <QColor> color; // 每节颜色
int num; // 长度
int position; // 方向
};
// 食物的属性
struct Food
{
point fdxy[10]; // 坐标
int grade; // 分数
int num = 1; // 食物总数
QColor color[10]; // 食物颜色
};
enum position { Up, Down, Left, Right,None }; // 枚举蛇的方向
初始化蛇:
void Widget::initSnake()
{
point xy;
xy.x = 20;
xy.y = 0;
snake.xy.push_back(xy);
snake.color.push_back(QColor(rand() % 256, rand() % 256, rand() % 256)); // 设置一个随机颜色
xy.x = 10;
xy.y = 0;
snake.xy.push_back(xy);
snake.color.push_back(QColor(rand() % 256, rand() % 256, rand() % 256)); // 设置一个随机颜色
xy.x = 0;
xy.y = 0;
snake.xy.push_back(xy);
snake.color.push_back(QColor(rand() % 256, rand() % 256, rand() % 256)); // 设置一个随机颜色
snake.num = 3;
snake.position = None;
timer=new QTimer(this);
timer->start(1);
connect(timer,SIGNAL(timeout()),SLOT(Snake_update()));//每1时间触发一次Snake_update()函数
}
控制蛇的移动:
void Widget::moveSnake()
{
// 将预留节设置为未移动前的尾节
snake.next = snake.xy[snake.num - 1];
// 将除蛇头以外的节移动到它的前面一节
for (int i = snake.num - 1; i >= 1; i--)
snake.xy[i] = snake.xy[i - 1];
// 根据当前移动方向移动蛇头
switch (snake.position)
{
case Right:
snake.xy[0].x += 10;
break;
case Left:
snake.xy[0].x -= 10;
break;
case Up:
snake.xy[0].y -= 10;
break;
case Down:
snake.xy[0].y += 10;
}
}
初始化食物:
void Widget::initFood(int num)
{
food.fdxy[num].x = rand() % 80 * 10;
food.fdxy[num].y = rand() % 60 * 10;
for (int i = 0; i < snake.num; i++)
if (food.fdxy[num].x == snake.xy[i].x && food.fdxy[num].y == snake.xy[i].y) // 避免食物生成在蛇身上
{
food.fdxy[num].x = rand() % 80 * 10;
food.fdxy[num].y = rand() % 60 * 10;
}
}
蛇吃食物:
void Widget::eatFood()
{
for (int i = 0; i <= food.num - 1; i++)
if (snake.xy[0].x == food.fdxy[i].x && snake.xy[0].y == food.fdxy[i].y)
{
snake.num++;
snake.xy.push_back(snake.next); // 新增一个节到预留位置
snake.color.push_back(food.color[i]); // 将新增节的颜色设置为当前吃掉食物的颜色
food.grade += 100;
initFood(i);
if (food.num < 10 && food.grade % 500 == 0 && food.grade != 0)
{
food.num++; // 每得 500 分,增加一个食物,但食物总数不超过 10 个
initFood(food.num - 1); // 初始化新增加的食物
}
break;
}
}
刷新画面:
void Widget::Snake_update()
{
Sleep(150);
moveSnake();
eatFood();
drawFood();
drawSnake();
showgrade();
update();//调用paintEvent函数
}
游戏结束条件:
bool Widget::gameOver()
{
// 撞墙,将墙向外扩展一圈(否则蛇无法到达地图边缘)
if (snake.xy[0].y <= 0 && snake.position == Up) return true;
if (snake.xy[0].y >= 600 && snake.position == Down) return true;
if (snake.xy[0].x <= 0 && snake.position == Left) return true;
if (snake.xy[0].x >= 800 && snake.position == Right) return true;
// 撞自己
for (int i = 1; i < snake.num; i++)
{
if (snake.xy[0].x <= snake.xy[i].x + 10 && snake.xy[0].x >= snake.xy[i].x && snake.xy[0].y == snake.xy[i].y && snake.position == Left)
return true;
if (snake.xy[0].x + 10 >= snake.xy[i].x && snake.xy[0].x + 10 <= snake.xy[i].x + 10 && snake.xy[0].y == snake.xy[i].y && snake.position == Right)
return true;
if (snake.xy[0].y <= snake.xy[i].y + 10 && snake.xy[0].y >= snake.xy[i].y && snake.xy[0].x == snake.xy[i].x && snake.position == Up)
return true;
if (snake.xy[0].y + 10 >= snake.xy[i].y && snake.xy[0].y + 10 <= snake.xy[i].y + 10 && snake.xy[0].x == snake.xy[i].x && snake.position == Down)
return true;
}
return false;
}
键盘监听事件:
void Widget::keyPressEvent(QKeyEvent *event)
{
switch(event->key())
{
case Qt::Key_Up:
if (snake.position != Down)
{
snake.position = Up;
}
break;
case Qt::Key_Down:
if (snake.position != Up)
{
snake.position = Down;
}
break;
case Qt::Key_Right:
if (snake.position != Left)
{
snake.position = Right;
}
break;
case Qt::Key_Left:
if (snake.position != Right)
{
snake.position = Left;
}
break;
default: ;
}
}
paintEvent:
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QPen pen;
QBrush brush;
QFont font("方正舒体",12,QFont::ExtraLight,false);
painter.setRenderHint(QPainter::Antialiasing);
pen.setColor(Qt::black);
//brush.setColor(Qt::green);
brush.setStyle(Qt::SolidPattern);
painter.setPen(pen);
painter.setBrush(brush);
//画蛇
if(snakeTag==1)
{
for (int i = 0; i < snake.num; i++)
{
brush.setColor(snake.color[i]);
painter.setPen(pen);
painter.setBrush(brush);
painter.drawRect(snake.xy[i].x, snake.xy[i].y, 10, 10);
}
snakeTag=0;
}
//画食物
if(foodTag==1)
{
for (int i = 0; i <= food.num - 1; i++)
{
brush.setColor(food.color[i] = QColor(rand() % 256, rand() % 256, rand() % 256));
painter.setPen(pen);
painter.setBrush(brush);
painter.drawRect(food.fdxy[i].x, food.fdxy[i].y,10,10);
}
foodTag=0;
}
//显示分数
if(gradeTag==1)
{
pen.setColor(QColor(147, 112, 219));
painter.setPen(pen);
painter.setFont(font);
painter.drawText(20,20,QString("当前得分:")+QString("%1").arg(food.grade));
gradeTag=0;
}
if(gameOver())
{
timer->stop();
overTag=1;
pen.setColor(QColor(147, 112, 219));
painter.setPen(pen);
painter.setFont(font);
painter.drawText(20,40,QString("Game over!"));
}
}
源代码(点这里)QwQ