用C++写一个贪吃蛇游戏(dos界面)
效果大概是这样的:
游戏分为三个模块:(用三个类封装起来)
- 1.墙
- 2.食物
- 3.蛇
关键的函数
-
1
#include<conio.h>
中的_getch();可以不回显的输入w(上)s(下)a(左)d(有)
它的返回值是输入的函数(c++中要加_,c中不需要) -
2
<windows.h>
中的Sleep(时间); -
3
#include<conio.h>
中的_kbhit();用于检查输入缓冲区中有没有内容,有内容返回true,无返回false(c++中要加_,c中不需要) -
4
#include<system.h>
中的:
void gotoxy0(HANDLE hOut0, int x, int y) {
COORD pos;
pos.X = x;//横坐标
pos.Y = y;//纵坐标
SetConsoleCursorPosition(hOut0, pos);
}
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定显示器的句柄变量
用于定义光标位置:
gotoxy(hOut,y,x);
代码如下:
--------------------------------------------------------
/*墙模块*/
//Wall.h
#pragma once
#include<iostream>
using namespace std;
class Wall {
public:
enum{ROW=30,COL=30};
//初始化
void initWall() {
for (int i = 0; i < ROW; ++i) {
for (int j = 0; j < COL; ++j) {
if (0==i||0==j||29==i||29==j) {
wallArray[i][j] = '#';
}
else
wallArray[i][j] = 32;
}
}
}
//画墙
void print();
char getWall(int a,int b);
void setWall(int a,int b,char ch);
private:
char wallArray[ROW][COL];
};
//Wall.cpp
#include"Wall.h"
//画墙
void Wall::print() {
for (int i = 0; i < ROW; ++i) {
for (int j = 0; j < COL; ++j) {
cout<<wallArray[i][j]<<" ";
}
cout << endl;
}
}
char Wall::getWall(int a, int b) {
return wallArray[a][b];
}
void Wall::setWall(int a, int b, char ch) {
wallArray[a][b] = ch;
}
-------------------------------------------------------
--------------------------------------------------------
/*食物模块*/
//Food.h
#pragma once
#include"Wall.h"
#include"Snake.h"
class Food {
public:
Food(Wall& wall);
//初始化(放置食物)
void initFood();
private:
int food_X;
int food_Y;
char ch = '+';
Wall& m_wall;
};
--------------------------------------------------------
//Food.cpp
#include"Food.h"
#include<ctime>
#include<Windows.h>
void gotoxy1(HANDLE hOut1, int x, int y) {
COORD pos;
pos.X = x;//横坐标
pos.Y = y;//纵坐标
SetConsoleCursorPosition(hOut1, pos);
}
HANDLE hOut1 = GetStdHandle(STD_OUTPUT_HANDLE);//定显示器的句柄变量
Food::Food(Wall& wall):m_wall(wall) {
}
//初始化(放置食物)
void Food::initFood() {
//随机数种子
srand((unsigned int)time(NULL));
while(true){
food_X = rand() % 28 + 1;
food_Y = rand() % 28 + 1;
if (32 == m_wall.getWall(food_X, food_Y)) {
m_wall.setWall(food_X, food_Y, ch);
gotoxy1(hOut1, food_Y * 2, food_X);
cout << "+";
break;//如果蛇填满屏幕就会死循环
}
}
}
--------------------------------------------------------
--------------------------------------------------------
/*蛇模块*/
//Snake.h
#pragma once
#include"Wall.h"
#include"Food.h"
class Snake {
public:
Snake(Wall& wall);
//初始化
void initSanke();
//清空结点
void destroyPoint();
//添加结点
void addPoint(int a, int b);
//删除尾结点
void delPoint();
//移动
bool move(char FangXiang);
//设定难度
int getSleepTime();
//获得蛇的长度
int countList();
//分数记录
int getScore();
private:
struct Point {
int x = 0;
int y = 0;
char ch=32;//空格
Point* next;
};
//头指针
Point* head;
Wall* m_wall;
public:
enum {
up = 'w', down = 's', left = 'a', right = 'd'
};
};
--------------------------------------------------------
//Snake.cpp
#include"Snake.h"
#include<Windows.h>
void gotoxy2(HANDLE hOut2, int x, int y) {
COORD pos;
pos.X = x;//横坐标
pos.Y = y;//纵坐标
SetConsoleCursorPosition(hOut2, pos);
}
HANDLE hOut2 = GetStdHandle(STD_OUTPUT_HANDLE);//定显示器的句柄变量
Snake::Snake(Wall& wall):m_wall(&wall),head(NULL) {
}
//初始化
void Snake::initSanke() {
destroyPoint();
addPoint(5, 3);
addPoint(5, 4);
addPoint(5, 5);
//放入
if (NULL != head) {
for (Point* p = head; p;) {
m_wall->setWall(p->x, p->y, p->ch);
p = p->next;
}
}
}
//清空结点
void Snake::destroyPoint() {
if (NULL != head) {
for (Point* p = head; p;) {
Point* Np = p->next;
delete p;
p = Np;
}
head = NULL;
}
}
//添加结点
void Snake::addPoint(int a,int b) {
Point*Np = NULL;
if (NULL == head) {
head= new Point;
head->x = a;
head->y = b;
head->ch = 'O';
head->next = NULL;
Np = head;
}
else {
Point* NewNode=new Point;
NewNode->x = a;
NewNode->y = b;
NewNode->ch = 'O';
head->ch = '*';
m_wall->setWall(head->x, head->y, head->ch);//放入
gotoxy2(hOut2, head->y * 2, head->x);
cout << head->ch;
NewNode->next=head;
head = NewNode;
Np = NewNode;
}
//放入
m_wall->setWall(Np->x, Np->y, Np->ch);
gotoxy2(hOut2, Np->y * 2, Np->x);
cout << Np->ch;
}
//删除尾结点
void Snake::delPoint() {
if (NULL == head || NULL == head->next) {
return;
}
Point* pa = head;
Point* pb = head->next;
while (pb->next != NULL) {
pa = pb;
pb = pb->next;
}
//放入
m_wall->setWall(pb->x, pb->y, 32);
gotoxy2(hOut2, pb->y * 2, pb->x);
cout << " ";
//释放结点空间
delete pb;
pb = NULL;
pa->next = NULL;
}
//移动
bool Snake::move(char FangXiang) {
int x = head->x;
int y = head->y;
switch(FangXiang){
case up:
--x;
break;
case down:
++x;
break;
case left:
y--;
break;
case right:
y++;
break;
default:
break;
};
char c = m_wall->getWall(x, y);
Point* pa = head;//寻找尾结点
while (pa->next != NULL) {
pa = pa->next;
}
if((x==pa->x)&&(y==pa->y)){//判断是否为尾结点
delPoint();
addPoint(x, y);
}
else if ('#' == c || '*' == c || 'O' == c) {//是否
cout << "GEME OVER" << endl;
return false;
}
else if ('+' == c) {
addPoint(x, y);
Food food(*m_wall);
food.initFood();
}
else {
delPoint();
addPoint(x, y);
}
return true;
}
//设定难度
int Snake::getSleepTime() {
int size = countList();
if (size < 5)
return 300;
else if (size < 10)
return 200;
else
return 50;
}
//获得蛇的长度
int Snake::countList() {
int size = 0;
Point* p = head;
while (p) {
p = p->next;
++size;
}
return size-3;
}
//分数记录
int Snake::getScore() {
return countList()*100;
}
--------------------------------------------------------
--------------------------------------------------------
/*主函数*/
//game.cpp
//案例:贪吃蛇
#include<iostream>
#include<Windows.h>
#include<conio.h>
#include"Wall.h"
#include"Snake.h"
#include"Food.h"
using namespace std;
//定位光标
void gotoxy0(HANDLE hOut0, int x, int y) {
COORD pos;
pos.X = x;//横坐标
pos.Y = y;//纵坐标
SetConsoleCursorPosition(hOut0, pos);
}
HANDLE hOut0 = GetStdHandle(STD_OUTPUT_HANDLE);//定显示器的句柄变量
//寻找非法值
bool find(char x,char per_x) {//用于判断是否为有效输入
if (x == Snake::up) {
if (Snake::down == per_x)
return false;
else
return true;
}
else if (x == Snake::down) {
if (Snake::up == per_x)
return false;
else
return true;
}
else if (x == Snake::right) {
if (Snake::left == per_x)
return false;
else
return true;
}
else if(x == Snake::left) {
if (Snake::right == per_x)
return false;
else
return true;
}
else
return false;
}
int main() {
//墙
Wall A;
A.initWall();
Snake S(A);
//初始化(蛇)
S.initSanke();
//食物
Food F(A);
F.initFood();//放置食物
//死亡标识
bool islive = true;
gotoxy0(hOut0, 0, 0);
A.print();//墙
char x = NULL;
char per_x = NULL;
//A.print();//画
while (true) {//等待有效输出
x = _getch();
if (x == Snake::up || x == Snake::down || x == Snake::right) {
islive = S.move(x);
per_x = x;
break;
}
}
while (islive) {
gotoxy0(hOut0, 0, 30);
cout << "得分:"<<S.getScore()<<endl;
//system("cls");//没效果
Sleep(S.getSleepTime());
// islive=move(x);
//是否有输入
if (_kbhit()) {
//移动(蛇)
x = _getch();
//寻找非法值
if (find(x,per_x)) {//判断是否为有效输入
islive = S.move(x);
per_x = x;
}
else {
islive = S.move(per_x);
x = per_x;
continue;
}
}
else {
islive = S.move(x);
}
}
cout << "完成!" << endl;
getchar();
getchar();
return 0;
}
---------------------------------------------------------------