开发环境:Ubuntu12.04 Qt4.8
项目概述: 用键盘上下左右控制蛇的方向,寻找食物,食物随机出现,蛇路过食物蛇的身体会变长,蛇不能碰墙壁及自己的身体,蛇不能相撞,两条蛇谁先达到一定的分数谁获得胜利
游戏说明:程序运行后,单击鼠标左键开始游戏
蛇一:方向键上下左右,蛇二WASD上下左右
1.main.cpp
#include <QtGui/QApplication>
#include <QTextCodec>
#include "widget.h"
int main(int argc, char *argv[])
{
//中文乱码处理
QTextCodec *codec=QTextCodec::codecForName("utf-8");
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
2.snakeBoday.h
#ifndef SNAKEBODAY_H
#define SNAKEBODAY_H
#include <QLabel>
#define BodySize (40)
class SnakeBoday : public QLabel
{
Q_OBJECT
public:
explicit SnakeBoday(QWidget *parent = 0);
signals:
public slots:
};
#endif // SNAKEBODAY_H
3.snakeBoday.cpp
#include "snakeBoday.h"
#include <stdio.h>
SnakeBoday::SnakeBoday(QWidget *parent) :
QLabel(parent)
{
// 设置食物的大小
this->resize(BodySize,BodySize);
// 随机设置食物的位置
int x = (rand()%(parent->width()/BodySize))*BodySize;
int y = (rand()%(parent->height()/BodySize))*BodySize;
this->move(x,y);
// 随机设置食物的颜色
char styleSheet[255];
sprintf(styleSheet,"background-color: rgb(%d, %d, %d);",
rand()%256,rand()%256,rand()%256);
this->setStyleSheet(styleSheet);
// 显示食物
this->show();
}
4.widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QList>
#include <QTimer>
#include <QMouseEvent>
#include <QKeyEvent>
#include "snakeBoday.h"
namespace Ui {
class Widget;
}
enum MoveDirection{
UP,
Down,
Left,
Right
};
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
// 按下鼠标左键开始游戏
void mouseReleaseEvent(QMouseEvent *event);
// 改变运动方向
void keyReleaseEvent(QKeyEvent *event);
// 删除身体
void del_snake_body(QList<SnakeBoday*>& snake);
public slots:
void snake1_timeout_slot(void);
void snake2_timeout_slot(void);
private:
Ui::Widget *ui;
//分数
int score1;
int score2;
// 食物
SnakeBoday* food;
// 定时器
QTimer* timer1;
QTimer* timer2;
// 两条蛇
QList<SnakeBoday*> snake1;
QList<SnakeBoday*> snake2;
// 蛇的运动方向
MoveDirection snakeDirection1;
MoveDirection snakeDirection2;
};
#endif // WIDGET_H
5.widget.cpp
#include <QMessageBox>
#include "widget.h"
#include "ui_widget.h"
QString str1;
QString str2;
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
score1=0;
score2=0;
// 初始化随机数
srand(time(NULL));
// 创建蛇1的蛇头
SnakeBoday* head1 = new SnakeBoday(this);
head1->setStyleSheet("background-color: rgb(255, 255, 255);"
"border-color: rgb(0, 0, 0);"
"border-style:solid;"
"border-width:2px;"
);
snake1.push_back(head1);
// 创建蛇2的蛇头
SnakeBoday* head2 = new SnakeBoday(this);
head2->setStyleSheet("background-color: rgb(0, 255, 127);"
"border-color: rgb(0, 0, 0);"
"border-style:solid;"
"border-width:2px;");
snake2.push_back(head2);
// 创建定时器
timer1 = new QTimer;
timer2 = new QTimer;
// 连接定时器的信号
connect(timer1,SIGNAL(timeout()),this,SLOT(snake1_timeout_slot()));
connect(timer2,SIGNAL(timeout()),this,SLOT(snake2_timeout_slot()));
// 随机蛇的运动方向
snakeDirection1 = (MoveDirection)(rand()%4);
snakeDirection2 = (MoveDirection)(rand()%4);
// 创建一个食物
food = new SnakeBoday(this);
}
Widget::~Widget()
{
del_snake_body(snake1);
del_snake_body(snake2);
delete snake1[0];
delete snake2[0];
delete food;
delete ui;
}
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
// 当鼠标左键按下,启动定时器
if(event->button() == Qt::LeftButton)
{
timer1->start(500);
timer2->start(500);
}
}
void Widget::keyReleaseEvent(QKeyEvent *event)
{
// 改变运动方向
switch(event->key())
{
case Qt::Key_Up: snakeDirection1 = UP; break;
case Qt::Key_Down: snakeDirection1 = Down; break;
case Qt::Key_Left: snakeDirection1 = Left; break;
case Qt::Key_Right: snakeDirection1 = Right; break;
case Qt::Key_W: snakeDirection2 = UP; break;
case Qt::Key_S: snakeDirection2 = Down; break;
case Qt::Key_A: snakeDirection2 = Left; break;
case Qt::Key_D: snakeDirection2 = Right; break;
}
}
void Widget::snake1_timeout_slot(void)
{
// 先移动蛇身
for(int i=snake1.size()-1; i>0; i--)
{
snake1[i]->move(snake1[i-1]->x(),snake1[i-1]->y());
}
// 获取蛇头位置
int x = snake1[0]->x() , y = snake1[0]->y();
// 移动蛇头
switch(snakeDirection1)
{
case UP: y -= BodySize; break;
case Down: y += BodySize; break;
case Left: x -= BodySize; break;
case Right: x += BodySize; break;
}
snake1[0]->move(x,y);
// 判断是否撞墙
if(x < 0 || y < 0 || x > width() || y > height())
{
del_snake_body(snake1);
score1=0;
//显示分数
str1.setNum(score1);
ui->label_3->setText(str1);
timer1->start(500);
}
// 是否与对方相撞
for(int i=0; i<snake2.size(); i++)
{
if(x == snake2[i]->x() && y == snake2[i]->y())
{
del_snake_body(snake1);
//显示分数
score1=0;
str1.setNum(score1);
ui->label_3->setText(str1);
timer1->start(500);
}
}
// 判断蛇头是否与食物相遇
if(food->x() == x && food->y() == y)
{
// 食物加入蛇身
snake1.push_back(food);
score1+=1;
//显示分数
str1.setNum(score1);//显示数字
ui->label_3->setText(str1);
// 创建新的食物
food = new SnakeBoday(this);
// 根据蛇身长度调整速度
switch(snake1.size())
{
case 2: timer1->start(450); break;
case 4: timer1->start(400); break;
case 8: timer1->start(350); break;
case 16: timer1->start(300); break;
case 32: timer1->start(250); break;
case 64: timer1->start(200); break;
case 128: timer1->start(150); break;
case 256: timer1->start(100); break;
}
if(score1 == 10)
{
QMessageBox::warning(this,"胜利弹窗","恭喜蛇一玩家获得胜利");
}
}
}
void Widget::snake2_timeout_slot(void)
{
for(int i=snake2.size()-1; i>0; i--)
{
snake2[i]->move(snake2[i-1]->x(),snake2[i-1]->y());
}
int x = snake2[0]->x() , y = snake2[0]->y();
switch(snakeDirection2)
{
case UP: y -= BodySize; break;
case Down: y += BodySize; break;
case Left: x -= BodySize; break;
case Right: x += BodySize; break;
}
snake2[0]->move(x,y);
// 判断是否撞墙
if(x < 0 || y < 0 || x > width() || y > height())
{
del_snake_body(snake2);
score2=0;
str2.setNum(score2);
ui->label_4->setText(str2);
timer2->start(500);
}
// 是否与对方相撞
for(int i=0; i<snake1.size(); i++)
{
if(x == snake1[i]->x() && y == snake1[i]->y())
{
del_snake_body(snake2);
score2=0;
str2.setNum(score2);
ui->label_4->setText(str2);
timer2->start(500);
}
}
if(food->x() == x && food->y() == y)
{
snake2.push_back(food);
score2+=1;
str2.setNum(score2);
ui->label_4->setText(str2);
food = new SnakeBoday(this);
switch(snake2.size())
{
case 2: timer2->start(450); break;
case 4: timer2->start(400); break;
case 8: timer2->start(350); break;
case 16: timer2->start(300); break;
case 32: timer2->start(250); break;
case 64: timer2->start(200); break;
case 128: timer2->start(150); break;
case 256: timer2->start(100); break;
}
if(score2 == 10)
{
QMessageBox::warning(this,"胜利弹窗","恭喜蛇二玩家获得胜利");
}
}
}
// 删除身体
void Widget::del_snake_body(QList<SnakeBoday*>& snake)
{
while(snake.size()>1)
{
delete snake.back();
snake.pop_back();
}
// 随机设置食物的位置
int x = (rand()%(width()/BodySize))*BodySize;
int y = (rand()%(height()/BodySize))*BodySize;
snake[0]->move(x,y);
}