用了一整天时间,终于做出了双人对战的贪吃蛇,找了几个同学试了试,还是很有趣的。在做这些小游戏的时候学会了不少知识,有机会我会多尝试的。下面就把代码发出来,我用的是VS2013,把代码复制过去应该可以直接编译运行。
学完系统网络编程的我再回来看了看,感觉如果有时间可以做成局域网的,而且游戏的内容也因为多线程的加入变得更加丰富。
#include<windows.h>
#include<conio.h>
#include<time.h>
#include<string>
using namespace std;
/*=============== all the structures ===============*/
typedef struct Frame
{
COORD position[2];//位置
int flag;
}Frame;//帧
/*=============== all the functions ===============*/
void SetPos(COORD a)// set cursor 设置光标
{
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(out, a);
}
/* set cursor设置光标*/void SetPos(int i, int j)
{
COORD pos = { i, j };
SetPos(pos);
}
void HideCursor()
{
CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
//把第y行,[x1, x2) 之间的坐标填充为 ch
void drawRow(int y, int x1, int x2, char ch)
{
SetPos(x1, y);
for (int i = 0; i <= (x2 - x1); i++)
cout << ch;
}
//在a, b 纵坐标相同的前提下,把坐标 [a, b] 之间填充为 ch
void drawRow(COORD a, COORD b, char ch)
{
if (a.Y == b.Y)
drawRow(a.Y, a.X, b.X, ch);
else
{
SetPos(0, 25);
cout << "error code 01:无法填充行,因为两个坐标的纵坐标(x)不相等";
system("pause");
}
}
//把第x列,[y1, y2] 之间的坐标填充为 ch
void drawCol(int x, int y1, int y2, char ch)
{
int y = y1;
while (y != y2 + 1)
{
SetPos(x, y);
cout << ch;
y++;
}
}
//在a, b 横坐标相同的前提下,把坐标 [a, b] 之间填充为 ch
void drawCol(COORD a, COORD b, char ch)
{
if (a.X == b.X)
drawCol(a.X, a.Y, b.Y, ch);
else
{
SetPos(0, 25);
cout << "error code 02:无法填充列,因为两个坐标的横坐标(y)不相等";
system("pause");
}
}
//左上角坐标、右下角坐标、用row填充行、用col填充列
void drawFrame(COORD a, COORD b, char row, char col)
{
drawRow(a.Y, a.X + 1, b.X - 1, row);
drawRow(b.Y, a.X + 1, b.X - 1, row);
drawCol(a.X, a.Y + 1, b.Y - 1, col);
drawCol(b.X, a.Y + 1, b.Y - 1, col);
}
//点覆盖
void drawFrame(COORD a, char r)
{
SetPos(a.X, a.Y);
cout << r;
}
void drawFrame(int x1, int y1, int x2, int y2, char row, char col)
{
COORD a = { x1, y1 };
COORD b = { x2, y2 };
drawFrame(a, b, row, col);
}
void drawFrame(Frame frame, char row, char col)
{
COORD a = frame.position[0];
COORD b = frame.position[1];
drawFrame(a, b, row, col);
}
void drawPlaying()
{
drawFrame(0, 0, 48, 24, '=', '|');// draw map frame;
drawFrame(49, 0, 77, 24, '-', '|');// draw output frame
SetPos(52, 6);
cout << "玩家1长度:";
SetPos(52, 8);
cout << "玩家2长度:";
SetPos(52, 14);
cout << "操作方式:";
SetPos(52, 16);
cout << " 玩家1 上下左右";
SetPos(52, 17);
cout << " 玩家2 a,s,d,w";
SetPos(52, 19);
cout << " p 暂停游戏。";
SetPos(52, 20);
cout << " esc 退出游戏。";
}
//在[a, b)之间产生一个随机整数
int random(int a, int b)
{
int c = (rand() % (a - b)) + a;
return c;
}
//在两个坐标包括的矩形框内随机产生一个坐标
COORD random(COORD a, COORD b)
{
int x = random(a.X, b.X);
int y = random(a.Y, b.Y);
COORD c = { x, y };
return c;
}
//判断是否撞到蛇身或者墙壁 点对点
bool judgeCoordSnake(COORD spot1, COORD spot2)
{
if (spot1.X == spot2.X)
if (spot1.Y == spot2.Y)
return true;
if (spot1.X == 0 || spot1.X == 48 || spot1.Y == 0 || spot1.Y == 24)
return true;
return false;
}
//判断是否撞到蛇身或者墙壁 头对身子
bool judgeCoordSnake(COORD spot1, COORD *snake1, COORD *snake2)
{
for (int i = 1; i < 250; i++)
{
if (spot1.X == snake1[i].X)
if (spot1.Y == snake1[i].Y)
return false;
if (spot1.X == snake2[i].X)
if (spot1.Y == snake2[i].Y)
return false;
if (spot1.X == 0 || spot1.X == 48 || spot1.Y == 0 || spot1.Y == 24)
return false;
}
return true;
}
bool judgeCoordSnakeFood(COORD spot1, COORD spot2, COORD spot3,int& a)
{
if (spot1.X == spot2.X)
if (spot1.Y == spot2.Y)
{
a = 0;
return true;
}
if (spot1.X == spot3.X)
if (spot1.Y == spot3.Y)
{
a = 1;
return true;
}
return false;
}
//因为在判断时头部的问题所以单列出来
void printCoord(COORD a)
{
cout << "( " << a.X << " , " << a.Y << " )";
}
int drawMenu()
{
SetPos(30, 1);
cout << "贪吃的大蟒蛇";
drawRow(3, 0, 79, '-');
drawRow(5, 0, 79, '-');
SetPos(28, 4);
cout << "w 和 s 选择, k 确定";
SetPos(15, 11);
cout << "开始游戏";
SetPos(15, 13);
cout << "结束游戏";
drawRow(20, 0, 79, '-');
drawRow(22, 0, 79, '-');
SetPos(47, 11);
cout << "本游戏为双人游戏:";
SetPos(51, 13);
cout << "wasd和ijkl控制";
SetPos(24, 21);
cout << "制作: 威微游戏制造厂厂长 唐宇威";
int j = 11;
SetPos(12, j);
cout <<"->";
while (1)
{
if (_kbhit())
{
char x = _getch();
switch (x)
{
case 'w':
{
if (j == 13)
{
SetPos(12, j);
cout << " ";
j = 11;
SetPos(12, j);
cout << "->";
SetPos(51, 13);
cout << " ";
SetPos(47, 11);
cout << "准备好了吗?";
SetPos(51, 13);
cout << "wasd和ijkl控制";
}
break;
}
case 's':
{
if (j == 11)
{
SetPos(12, j);
cout << " ";
j = 13;
SetPos(12, j);
cout << "->";
SetPos(51, 13);
cout << " ";
SetPos(47, 11);
cout << "结束游戏:";
SetPos(51, 13);
cout << "要走了吗?";
}
break;
}
case 'k':
{
if (j == 11)
return 1;
else exit(0);
}
}
}
}
}
/*
DWORD WINAPI MusicFun(LPVOID lpParamte)
{
//DWORD OBJ;
sndPlaySound(TEXT("bgm.wav"), SND_FILENAME|SND_ASYNC);
return 0;
}
*/
/*================== the Game Class ==================*/
class Game
{
public:
COORD snake1[250];
COORD snake2[250];
COORD food[2];
int length1;
int length2;
int direction1;//蛇1的头 1上2下3左4右
int direction2;//蛇2的头 1上2下3左4右
string title;
//初始化所有
void initFood();
COORD randomFood();
//初始化其中一个
//void initThisBullet( COORD );
//void initThisEnemy( Frame );
void Playing();
void Pause();
void judgeSnake();
void GameOver();
void snake1ChangeDirection(char x);
void snake2ChangeDirection(char x);
void drawSnake1(int direction);
void drawSnake2(int direction);
void drawSnake1ToNull();
void drawSnake2ToNull();
void drawFood();
void drawFoodToNull();
Game()
{
direction1 = 1,direction2 = 1;
snake1[0] = { 8, 15 }, snake1[1] = { 8, 16 }, snake1[2] = { 8, 17 };
snake2[0] = { 40, 15 }, snake2[1] = { 40, 16 }, snake2[2] = { 40, 17 };
length1 = 3, length2 = 3;
for (int i = 3; i < 249; i++)
{
snake1[i] = { 0, 0 };
snake2[i] = { 0, 0 };
}
}
};
//画第一条蛇
void Game::drawSnake1(int direction)
{
for (int i = 0; i<240; i++)
{
SetPos(snake1[i]);
if (i != 0)
cout << "O";
else if (i == 0)
{
if (direction==1)
{
cout << "^";
}
else if(direction == 2)
{
cout << "v";
}
else if (direction == 3)
{
cout << "<";
}
else if (direction == 4)
{
cout << ">";
}
}
}
}
void Game::drawSnake2(int direction)
{
for (int i = 0; i<240; i++)
{
SetPos(snake2[i]);
if (i != 0)
cout << "X";
else if (i == 0)
{
if (direction == 1)
{
cout << "^";
}
else if (direction == 2)
{
cout << "v";
}
else if (direction == 3)
{
cout << "<";
}
else if (direction == 4)
{
cout << ">";
}
}
}
}
//把第一条蛇消失,行动时使用,只让蛇头蛇尾消失,这样不会一闪一闪
void Game::drawSnake1ToNull()
{
SetPos(snake1[0]);
cout << " ";
SetPos(snake1[length1]);
cout << " ";
}
void Game::drawSnake2ToNull()
{
/*for (int i = length2; i<240; i++)
{
SetPos(snake2[i]);
cout << " ";
}*/
SetPos(snake2[0]);
cout << " ";
SetPos(snake2[length2]);
cout << " ";
}
//初始食物
void Game::initFood()
{
COORD a = { 2, 2 };
COORD b = { 24,12 };
COORD c = { 25, 2 };
COORD d = { 47,14 };
food[0] = random(a, b);
food[1] = random(c, d);
}
//随机食物,如果有墙需要修改。
COORD Game::randomFood()
{
COORD food;
COORD a = { 2, 2 };
COORD b = { 47, 23 };
while (1)
{
food = random(a, b);
if (judgeCoordSnake(food, snake1, snake2))
return food;
}
}
//画出食物
void Game::drawFood()
{
for (int i = 0; i<2; i++)
drawFrame(food[i], '@');
}
//判断蛇是否吃到东西
/*不用这个也行,蛇吃过了就没了*/void Game::drawFoodToNull()
{
for (int i = 0; i<2; i++)
{
drawFrame(food[i], ' ');
}
}
//暂停游戏
void Game::Pause()
{
SetPos(61, 2);
cout << " ";
SetPos(61, 2);
cout << "暂停中...";
char c = _getch();
while (c != 'p')
c = _getch();
SetPos(61, 2);
cout << " ";
}
void Game::snake1ChangeDirection(char x)
{
if (x == 'w')//是上箭头;
{
if (direction1!=2)
direction1 = 1;
}
else if (x == 's') //是 下箭头;
{
if (direction1 != 1)
direction1 = 2;
}
else if (x == 'a') //是 左箭头;
{
if (direction1 != 4)
direction1 = 3;
}
else if (x == 'd') // 是 右箭头;
{
if (direction1 != 3)
direction1 = 4;
}
}
void Game::snake2ChangeDirection(char x)
{
if (x == 'i')//是上箭头;
{
if (direction2 != 2)
direction2 = 1;
}
else if (x == 'k') //是 下箭头;
{
if (direction2 != 1)
direction2 = 2;
}
else if (x == 'j') //是 左箭头;
{
if (direction2 != 4)
direction2 = 3;
}
else if (x == 'l') // 是 右箭头;
{
if (direction2 != 3)
direction2 = 4;
}
}
void Game::judgeSnake()
{
for (int i = 0; i < 250; i++)
{
if (judgeCoordSnake(snake1[0], snake1, snake2) == false )
{
for (int i = 1; i < 500; i++)
{
Sleep(2);
SetPos(random(1,79), random(1,24));
cout << "玩家一输了";
}
Sleep(1000);
GameOver();
break;
}
if (judgeCoordSnake(snake2[0], snake1, snake2) == false)
{
for (int i = 1; i < 500; i++)
{
Sleep(2);
SetPos(random(1, 79), random(1, 24));
cout << "玩家二输了";
}
Sleep(1000);
GameOver();
break;
}
}
}
void Game::Playing()
{
//HANDLE MFUN;
//MFUN= CreateThread(NULL, 0, MusicFun, NULL, 0, NULL);
drawSnake1(direction1);
drawSnake2(direction2);
initFood();
drawFood();
int numfood;
while (1)
{
Sleep(10);
SetPos(52, 7);
cout << length1;
SetPos(52, 9);
cout << length2;
drawSnake1ToNull();
drawSnake2ToNull();
if (_kbhit())
{
char x = _getch();
if ('a' == x || 's' == x || 'd' == x || 'w' == x)
{
snake1ChangeDirection(x);
}
else if ('p' == x)
Pause();
else if ('j' == x || 'k' == x || 'l' == x || 'i' == x)
{
snake2ChangeDirection(x);
}
else if (27 == x)
{
//CloseHandle(MFUN);
GameOver();
break;
}
}
if(judgeCoordSnakeFood(snake1[0], food[0], food[1],numfood)==true)
{
if (direction1 == 1)
{
for (int i = length1; i > 0; i--)
snake1[i+1] = snake1[i];
snake1[0].Y--;
length1++;
}
if (direction1 == 2)
{
for (int i = length1; i >= 0; i--)
snake1[i+1] = snake1[i];
snake1[0].Y++;
length1++;
}
if (direction1 == 3)
{
for (int i = length1; i >= 0; i--)
snake1[i+1] = snake1[i];
snake1[0].X--;
length1++;
}
if (direction1 == 4)
{
for (int i = length1; i >= 0; i--)
snake1[i+1] = snake1[i];
snake1[0].X++;
length1++;
}
food[numfood] = randomFood();
drawFood();
}
else
{
if (direction1 == 1)
{
for (int i = length1; i > 0; i--)
snake1[i] = snake1[i - 1];
snake1[0].Y--;
}
if (direction1 == 2)
{
for (int i = length1; i > 0; i--)
snake1[i] = snake1[i - 1];
snake1[0].Y++;
}
if (direction1 == 3)
{
for (int i = length1; i > 0; i--)
snake1[i] = snake1[i - 1];
snake1[0].X--;
}
if (direction1 == 4)
{
for (int i = length1; i > 0; i--)
snake1[i] = snake1[i - 1];
snake1[0].X++;
}
judgeSnake();
}
if (judgeCoordSnakeFood(snake2[0], food[0], food[1], numfood) == true)
{
if (direction2 == 1)
{
for (int i = length2; i > 0; i--)
snake2[i + 1] = snake2[i];
snake2[0].Y--;
length2++;
}
if (direction2 == 2)
{
for (int i = length2; i >= 0; i--)
snake2[i + 1] = snake2[i];
snake2[0].Y++;
length2++;
}
if (direction2 == 3)
{
for (int i = length2; i >= 0; i--)
snake2[i + 1] = snake2[i];
snake2[0].X--;
length2++;
}
if (direction2 == 4)
{
for (int i = length2; i >= 0; i--)
snake2[i + 1] = snake2[i];
snake2[0].X++;
length2++;
}
food[numfood] = randomFood();
drawFood();
}
else
{
if (direction2 == 1)
{
for (int i = length2; i > 0; i--)
snake2[i] = snake2[i - 1];
snake2[0].Y--;
}
if (direction2 == 2)
{
for (int i = length2; i > 0; i--)
snake2[i] = snake2[i - 1];
snake2[0].Y++;
}
if (direction2 == 3)
{
for (int i = length2; i > 0; i--)
snake2[i] = snake2[i - 1];
snake2[0].X--;
}
if (direction2 == 4)
{
for (int i = length2; i > 0; i--)
snake2[i] = snake2[i - 1];
snake2[0].X++;
}
judgeSnake();
}
drawSnake1(direction1);
drawSnake2(direction2);
}
}
void Game::GameOver()
{
system("cls");
COORD p1 = { 28, 9 };
COORD p2 = { 53, 15 };
drawFrame(p1, p2, '=', '|');
SetPos(36, 12);
string str = "Game Over!";
for (int i = 0; i<str.size(); i++)
{
Sleep(80);
cout << str[i];
}
Sleep(1000);
system("cls");
drawFrame(p1, p2, '=', '|');
SetPos(31, 11);
cout << "玩家一长度:" ;
SetPos(31, 12);
cout << length1;
SetPos(31, 13);
cout << "玩家二长度:";
SetPos(31, 14);
cout << length2;
SetPos(30, 16);
Sleep(1000);
cout << "继续? 是(y)| 否(n)";
as:
char x = _getch();
if (x == 'n')
exit(0);
else if (x == 'y')
{
system("cls");
Game game;
int a = drawMenu();
system("cls");
drawPlaying();
game.Playing();
}
else goto as;
}
/*================== the main function ==================*/
int main()
{
//游戏准备
srand((int)time(0)); //随机种子
HideCursor(); //隐藏光标
Game game;
int a = drawMenu();
system("cls");
drawPlaying();
game.Playing();
}```
****