贪吃蛇(gluttonous snake) 基本要求: 完成贪吃蛇游戏,使得游戏具有可玩性,对用户友好的交互性。通过配色与背景的搭配,以及音效的结合,形成游戏的完整要素,体现QT学习的阶段性结果。 玩法介绍: 点击开始进入游戏界面。最初的模式很简单,随着你吃的食物量的增加,它会逐渐变成困难模式,然后继续魔鬼模式。区别在于不同的模式,食物刷新的频率和蛇的速度是不同的,在游戏进行到一半时,如果你想停止,请按空格键,如果你想继续游戏,再按空格键继续。当游戏失败时,按enter键继续游戏。游戏显示你在游戏中的最高分。 Click start to enter the game interface. The initial mode is simple, and as the amount of food you eat increases, it will gradually become difficult mode, and then continue to the devil mode.The difference lies in different modes, the frequency of food refresh and the speed of the snake are different, in the middle of the game, if you want to stop, please press the space bar, if you want to continue the game again press the space bar to continue.When the game fails, press enter to continue the game.The game shows you the highest score in the game. 代码:
#include "form.h"
#include "ui_form.h"
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QDebug>
#include <QTimer>
#include <QTime>
#include <QtMultimedia/QSound>
Form:: Form ( QWidget * parent) :
QWidget ( parent) ,
ui ( new Ui:: Form)
{
time= 100 ;
ui- > setupUi ( this ) ;
gameStart = true ;
QString dir= QCoreApplication :: applicationDirPath ( ) ;
QString filename ( dir+ "/bgm.wav" ) ;
QSound * sound1 = new QSound ( filename, this ) ;
sound1- > play ( ) ;
sound1- > setLoops ( 10000 ) ;
resize ( 1000 , 700 ) ;
snake. append ( QRectF ( 200 , 500 , snakeNodeWidth, snakeNodeHeight) ) ;
addTopRectF ( ) ;
addTopRectF ( ) ;
rewardNode. append ( QRectF ( 100 , 100 , snakeNodeWidth, snakeNodeWidth) ) ;
timer = new QTimer;
connect ( timer, SIGNAL ( timeout ( ) ) , this , SLOT ( timeOut ( ) ) ) ;
timer- > start ( time) ;
rewardTimer = new QTimer;
connect ( rewardTimer, SIGNAL ( timeout ( ) ) , this , SLOT ( rewardTimeOut ( ) ) ) ;
rewardTimer- > start ( time* 30 ) ;
}
Form:: ~ Form ( )
{
delete ui;
}
void Form:: timeOut ( )
{
int flage = 1 ;
for ( int i= 0 ; i< rewardNode. length ( ) ; i++ ) {
if ( rewardNode. at ( i) . contains ( snake. at ( 0 ) . topLeft ( ) + QPointF ( snakeNodeWidth/ 2 , snakeNodeHeight/ 2 ) ) ) {
if ( rewardNode. at ( i) . width ( ) > snakeNodeWidth) {
flage + = 2 ;
}
flage++ ;
rewardNode. removeAt ( i) ;
sound ( 0 ) ;
break ;
}
}
while ( flage-- ) {
switch ( moveFlage) {
case Up:
addTopRectF ( ) ;
break ;
case Down:
addDownRectF ( ) ;
break ;
case Right:
addRightRectF ( ) ;
break ;
case Left:
addLeftRectF ( ) ;
break ;
default :
break ;
}
}
deleteLastRectF ( ) ;
update ( ) ;
}
void Form:: rewardTimeOut ( )
{
qsrand ( QTime ( 0 , 0 , 0 ) . secsTo ( QTime:: currentTime ( ) ) ) ;
if ( rewardNode. length ( ) > 5 ) {
rewardNode. removeAt ( qrand ( ) % 5 ) ;
}
rewardNode. append ( QRectF ( qrand ( ) % ( this - > width ( ) / 20 ) * 20 , qrand ( ) % ( this - > height ( ) / 20 ) * 20 , snakeNodeWidth, snakeNodeWidth) ) ;
if ( qrand ( ) % 5 == 3 ) {
rewardNode. append ( QRectF ( qrand ( ) % ( this - > width ( ) / 20 ) * 20 - 5 , qrand ( ) % ( this - > height ( ) / 20 ) * 20 - 5 , snakeNodeWidth* 2 , snakeNodeWidth* 2 ) ) ;
}
}
void Form:: addTopRectF ( )
{
if ( snake. at ( 0 ) . y ( ) - snakeNodeHeight < 0 ) {
snake. insert ( 0 , QRectF ( QPointF ( snake. at ( 0 ) . x ( ) , this - > height ( ) - snakeNodeHeight) ,
QPointF ( snake. at ( 0 ) . x ( ) + snakeNodeWidth, this - > height ( ) ) ) ) ;
} else {
snake. insert ( 0 , QRectF ( snake. at ( 0 ) . topLeft ( ) + QPointF ( 0 , - snakeNodeHeight) , snake. at ( 0 ) . topRight ( ) ) ) ;
}
}
void Form:: addDownRectF ( )
{
if ( snake. at ( 0 ) . y ( ) + snakeNodeHeight* 2 > this - > height ( ) ) {
snake. insert ( 0 , QRectF ( QPointF ( snake. at ( 0 ) . x ( ) , snakeNodeHeight) ,
QPointF ( snake. at ( 0 ) . x ( ) + snakeNodeWidth, 0 ) ) ) ;
} else {
snake. insert ( 0 , QRectF ( snake. at ( 0 ) . bottomLeft ( ) , snake. at ( 0 ) . bottomRight ( ) + QPointF ( 0 , snakeNodeHeight) ) ) ;
}
}
void Form:: addLeftRectF ( )
{
if ( snake. at ( 0 ) . x ( ) - snakeNodeWidth < 0 ) {
snake. insert ( 0 , QRectF ( QPointF ( this - > width ( ) - snakeNodeWidth, snake. at ( 0 ) . y ( ) ) ,
QPointF ( this - > width ( ) , snake. at ( 0 ) . y ( ) + snakeNodeHeight) ) ) ;
} else {
snake. insert ( 0 , QRectF ( snake. at ( 0 ) . topLeft ( ) + QPointF ( - snakeNodeWidth, 0 ) , snake. at ( 0 ) . bottomLeft ( ) ) ) ;
}
}
void Form:: addRightRectF ( )
{
if ( snake. at ( 0 ) . x ( ) + snakeNodeWidth* 2 > this - > width ( ) ) {
snake. insert ( 0 , QRectF ( QPointF ( 0 , snake. at ( 0 ) . y ( ) ) ,
QPointF ( snakeNodeWidth, snake. at ( 0 ) . y ( ) + snakeNodeHeight) ) ) ;
} else {
snake. insert ( 0 , QRectF ( snake. at ( 0 ) . topRight ( ) , snake. at ( 0 ) . bottomRight ( ) + QPointF ( snakeNodeWidth, 0 ) ) ) ;
}
}
void Form:: deleteLastRectF ( )
{
snake. removeLast ( ) ;
}
void Form:: paintEvent ( QPaintEvent * event)
{
qDebug ( "画图" ) ;
QPainter painter ( this ) ;
QString dir= QCoreApplication :: applicationDirPath ( ) ;
QString filename ( dir+ "/bg.jpg" ) ;
painter. drawPixmap ( rect ( ) , QPixmap ( filename) ) ;
QPen pen;
QBrush brush;
QFont font ( "华文琥珀" , 13 , QFont:: ExtraLight, false ) ;
QFont font1 ( "华文彩云" , 13 , QFont:: ExtraLight, false ) ;
painter. setRenderHint ( QPainter:: Antialiasing) ;
pen. setColor ( Qt:: white) ;
brush. setStyle ( Qt:: SolidPattern) ;
painter. setPen ( pen) ;
painter. setBrush ( brush) ;
for ( int i= 0 ; i< snake. length ( ) ; i++ ) {
if ( i== 0 )
{
brush. setColor ( Qt:: cyan) ;
painter. setBrush ( brush) ;
painter. drawRect ( snake. at ( i) ) ;
}
else {
brush. setColor ( Qt:: gray) ;
painter. setBrush ( brush) ;
painter. drawRect ( snake. at ( i) ) ;
}
}
for ( int i= 0 ; i< rewardNode. length ( ) ; i++ ) {
int flag= i% 5 ;
switch ( flag) {
case 0 : pen. setColor ( Qt:: green) ; brush. setColor ( Qt:: green) ; break ;
case 1 : pen. setColor ( Qt:: red) ; brush. setColor ( Qt:: red) ; break ;
case 2 : pen. setColor ( Qt:: yellow) ; brush. setColor ( Qt:: yellow) ; break ;
case 3 : pen. setColor ( Qt:: white) ; brush. setColor ( Qt:: white) ; break ;
case 4 : pen. setColor ( Qt:: black) ; brush. setColor ( Qt:: black) ; break ;
}
painter. setPen ( pen) ;
painter. setBrush ( brush) ;
painter. drawEllipse ( rewardNode. at ( i) ) ;
}
pen. setColor ( Qt:: white) ;
painter. setPen ( pen) ;
painter. setFont ( font) ;
if ( snake. length ( ) >= 20 && snake. length ( ) < 40 )
{
painter. drawText ( 20 , 35 , QString ( tr ( "模式:Hard Model" ) ) ) ;
if ( time!= 50 )
{
time= 50 ;
timer- > stop ( ) ;
rewardTimer- > stop ( ) ;
gameStart = true ;
timer- > start ( time) ;
rewardTimer- > start ( time* 30 ) ;
gameStart = false ;
}
if ( snake. length ( ) == 20 )
{
painter. setFont ( font1) ;
painter. drawText ( ( this - > width ( ) - 300 ) / 2 , ( this - > height ( ) - 30 ) / 2 , QString ( tr ( " 进入困难模式" ) ) ) ;
painter. setFont ( font) ;
}
}
else if ( snake. length ( ) >= 40 ) {
painter. drawText ( 20 , 35 , QString ( tr ( "模式:Devil Model" ) ) ) ;
if ( time!= 25 )
{
time= 25 ;
timer- > stop ( ) ;
rewardTimer- > stop ( ) ;
gameStart = true ;
timer- > start ( time) ;
rewardTimer- > start ( time* 30 ) ;
gameStart = false ;
}
if ( snake. length ( ) == 40 )
{
painter. setFont ( font1) ;
painter. drawText ( ( this - > width ( ) - 300 ) / 2 , ( this - > height ( ) - 30 ) / 2 , QString ( tr ( " 进入魔鬼模式" ) ) ) ;
painter. setFont ( font) ;
}
}
else {
painter. drawText ( 20 , 35 , QString ( tr ( "模式:Simple Model" ) ) ) ;
if ( snake. length ( ) == 3 )
{
painter. setFont ( font1) ;
painter. drawText ( ( this - > width ( ) - 300 ) / 2 , ( this - > height ( ) - 30 ) / 2 , QString ( tr ( " 进入容易模式" ) ) ) ;
painter. setFont ( font) ;
}
}
painter. drawText ( ( this - > width ( ) - 300 ) / 2 , 35 , QString ( tr ( " 当前得分:" ) ) + QString ( "%1" ) . arg ( snake. length ( ) - 3 ) ) ;
if ( snake. length ( ) - 3 > best)
{
best= snake. length ( ) - 3 ;
}
painter. drawText ( ( this - > width ( ) - 300 ) , 35 , QString ( tr ( " Best Score:" ) ) + QString ( "%1" ) . arg ( best) ) ;
if ( snakeStrike ( ) ) {
QFont font ( tr ( "Showcard Gothic" ) , 33 , QFont:: ExtraLight, false ) ;
painter. setFont ( font) ;
painter. drawText ( ( this - > width ( ) - 300 ) / 2 - 10 , ( this - > height ( ) - 30 ) / 2 , QString ( "GAME OVER!" ) ) ;
QFont font1 ( tr ( "华文行楷" ) , 15 , QFont:: ExtraLight, false ) ;
painter. setFont ( font1) ;
painter. drawText ( ( this - > width ( ) - 300 ) / 2 , ( this - > height ( ) - 30 ) / 2 + 50 , QString ( " 按回车键继续游戏" ) ) ;
timer- > stop ( ) ;
rewardTimer- > stop ( ) ;
gameOver = true ;
}
QWidget:: paintEvent ( event) ;
}
void Form:: keyPressEvent ( QKeyEvent * event)
{
switch ( event- > key ( ) ) {
case Qt:: Key_Up:
if ( moveFlage != Down) {
moveFlage = Up;
}
break ;
case Qt:: Key_Down:
if ( moveFlage != Up) {
moveFlage = Down;
}
break ;
case Qt:: Key_Right:
if ( moveFlage != Left) {
moveFlage = Right;
}
break ;
case Qt:: Key_Left:
if ( moveFlage != Right) {
moveFlage = Left;
}
break ;
case Qt:: Key_Enter:
case Qt:: Key_Return:
if ( gameOver) {
time= 100 ;
snake. clear ( ) ;
rewardNode. clear ( ) ;
moveFlage = Up;
snake. append ( QRectF ( 200 , 500 , snakeNodeWidth, snakeNodeHeight) ) ;
addTopRectF ( ) ;
addTopRectF ( ) ;
rewardNode. append ( QRectF ( 100 , 100 , snakeNodeWidth, snakeNodeWidth) ) ;
timer- > start ( time) ;
rewardTimer- > start ( time* 30 ) ;
gameOver = false ;
}
break ;
case Qt:: Key_Space:
if ( gameStart && ! gameOver) {
timer- > start ( time) ;
rewardTimer- > start ( time* 30 ) ;
gameStart = false ;
} else if ( ! gameStart && ! gameOver) {
timer- > stop ( ) ;
rewardTimer- > stop ( ) ;
gameStart = true ;
}
break ;
default :
break ;
}
}
bool Form:: snakeStrike ( )
{
for ( int i= 0 ; i< snake. length ( ) ; i++ ) {
for ( int j= i+ 1 ; j< snake. length ( ) ; j++ ) {
if ( snake. at ( i) == snake. at ( j) ) {
sound ( 1 ) ;
return true ;
}
}
}
return false ;
}
void Form:: sound ( int type)
{
QString dir= QCoreApplication :: applicationDirPath ( ) ;
if ( type== 0 )
{
QString filename ( dir+ "/eat.wav" ) ;
QSound:: play ( filename ) ;
}
else if ( type== 1 )
{
QString filename ( dir+ "/over.wav" ) ;
QSound:: play ( filename ) ;
}
}