贪吃蛇,我主要用链表的方式去制作,首先要设置好墙、食物、蛇身、边界的类型,从而能够方便判断蛇碰到不同情况下做出相对应的反应。
基本思想就是分为三种情况,一种是蛇撞墙,蛇吃自己,和蛇吃食物,以及除了以上两种情况。
1蛇在每次开始时都要获得一个方块(有矩阵表示)
无事发生则要把该方块当成自己新的蛇头,然后把蛇尾方块删除
吃食物则不用删去尾部
蛇撞墙则游戏结束
2关于食物生成,就是要用随机生成函数,并且要保证食物不落入墙里面以及蛇的身上,用if语句表示。
3关于蛇的移动,要定义dx和dy然后通过键盘控制,给dx和dy附上相应的值使得蛇身能得到一个新方块,然后把蛇尾删除。
4用刷新频率设置蛇的速度
代码如下:
board文件
#endif // BOARD_H
#include “board.h”
#include
#include
#include
#include
#include
#include
Board::Board(QWidget *parent) :
QWidget(parent)
{
this->setWindowTitle(“贪吃蛇”);
init();//初始化
drawBorder();//画边界
initSnake();//初始化蛇身
moveStep();
generateFood();//初始化完就产生一个食物
connect(&timer, SIGNAL(timeout()), this, SLOT(slotMoveStep()));
timer.start(100); //设置刷新率
}
void Board::init(){ //初始化全部场景
int gridSize = 25;//设置框的大小
for(int x = 0; x < MAX_X; x++){
for(int y = 0; y < MAX_Y; y++){
QLabel *label = new QLabel(this); // ?创建一个标签
label->setStyleSheet(“background:black”);//设置场景颜色
label->setGeometry(x * gridSize, y * gridSize, gridSize - 1, gridSize - 1);
label->hide();//把颜色给去掉隐藏起来
matrix[x][y]= new Node;//创建小格子
matrix[x][y]->label =label;
matrix[x][y]->type = NORMAL_LABEL;//将所有的都初始化成普通label
matrix[x][y]->x = x;
matrix[x][y]->y = y;
}
}
}
void Board::drawBorder(){//画边界
for(int x = 0; x < MAX_X; x++){
for(int y = 0; y < MAX_Y; y++){
if(x == 0 || x == MAX_X - 1 || y == 0 || y == MAX_Y - 1){ //在x及y都为边界时,要画边界
matrix[x][y]->label->show();
matrix[x][y]->type = BORDER_LABEL;//边界label
}
}
}
}
void Board::initSnake(){//画蛇身
int x0 = 5, y0 = 5;
int snakeLen = 5;//初始蛇身长5
dx = 1;
dy = 0;
snake.clear();
for(int x = x0; x < x0 + snakeLen; x++){
snake.append(matrix[x][y0]); //在蛇头添加一个方块,即链表尾端添加一个方块
snake.at(snake.length() - 1)->x = x; //蛇方块x轴位置
snake.at(snake.length() - 1)->y = y0; //蛇方块y轴位置
matrix[x][y0]->type = SNAKE_LABEL;//蛇身label
matrix[x][y0]->label->show(); //展示蛇每个方块
}
}
void Board::moveStep(){
getHeadTail();//获取蛇头和蛇尾指针
Node n = matrix[head->x + dx][head->y + dy];
n->label->show();
//n是即将变成蛇头的那个label
if(n->type == BORDER_LABEL || n->type == SNAKE_LABEL){ //倘若吃到自己或者撞墙
qDebug() << “Game over@!!!”;
timer.stop();
QMessageBox::information(this, “提示”, "** game over ***", QMessageBox::Ok);
}else{
if(n->type == FOOD_LABEL){//倘若蛇已经吃到食物了
n->type = SNAKE_LABEL;
snake.append(n); //在链表尾部添加一个,即在蛇头添加一个
//不移除尾巴
generateFood();//生成下一个食物
}else{
n->type = SNAKE_LABEL;
snake.append(n);
tail->label->hide(); //把后面的蛇尾给隐藏掉
tail->type = NORMAL_LABEL;
snake.removeFirst();//从链表中删除第一个元素即蛇尾
}
}
}
void Board::getHeadTail(){
head = snake.at(snake.length() - 1);//蛇头其实是list的尾巴
tail = snake.at(0);//蛇尾其实是list的第一个元素
// gameover();
}
void Board::slotMoveStep(){
// qDebug() << “movestep”;
moveStep();
}
void Board::keyPressEvent(QKeyEvent *e){
//qDebug() << Qt::Key_up;
qDebug() << e->key();
switch (e->key()) {
case 16777235://上
if(up()){
dy = -1;
dx = 0;
}
break;
case 16777237://下
if(down()){
dy = 1;
dx = 0;
}
break;
case 16777234://左
if(left()){
dx = -1;
dy = 0;
}
break;
case 16777236://右
if(right()){
dx = 1;
dy = 0;
}
break;
default:
break;;
}
}
void Board::generateFood(){//生成食物
int food_x,food_y;
srand((unsigned)time(0));
do{
food_x = rand()%MAX_X; //随机去食物的坐标
food_y = rand()%MAX_Y;
}while(matrix[food_x][food_y]->type != NORMAL_LABEL); //判决条件,倘若食物不是普通情况的地方,如在边界和蛇身上,则重复循环
// matrix[food_x][food_y]->label->setText(“food”);
matrix[food_x][food_y]->type = FOOD_LABEL;
matrix[food_x][food_y]->label->show();
}
bool Board::left(){
if(dy == 0){//向左或向右走
return false;
}
return true;
}
bool Board::right(){
if(dy == 0){//向左或向右走
return false;
}
return true;
}
bool Board::up(){
if(dx == 0){//向上或向下走
return false;
}
return true;
}
bool Board::down(){
if(dx == 0){//向上或向下走
return false;
}
return true;
}
结果演示: