贪吃蛇游戏的C语言编程

Python09

贪吃蛇游戏的C语言编程,第1张

#include <windows.h>

#include <ctime>

#include <iostream>

#include <vector>

#include <queue>

using namespace std

#ifndef SNAKE_H

#define SNAKE_H

class Cmp

{

friend class Csnake

int rSign//横坐标

int lSign//竖坐标

public:

// friend bool isDead(const Cmp&cmp)

Cmp(int r,int l){setPoint(r,l)}

Cmp(){}

void setPoint(int r,int l){rSign=rlSign=l}

Cmp operator-(const Cmp &m)const

{

return Cmp(rSign-m.rSign,lSign-m.lSign)

}

Cmp operator+(const Cmp &m)const

{

return Cmp(rSign+m.rSign,lSign+m.lSign)

}

}

const int maxSize = 5//初始蛇身长度

class Csnake

{

Cmp firstSign//蛇头坐标

Cmp secondSign//蛇颈坐标

Cmp lastSign//蛇尾坐标

Cmp nextSign//预备蛇头

int row//列数

int line//行数

int count//蛇身长度

vector<vector<char>>snakeMap//整个游戏界面

queue<Cmp>snakeBody//蛇身

public:

int GetDirections()const

char getSymbol(const Cmp&c)const

//获取指定坐标点上的字符

{

return snakeMap[c.lSign][c.rSign]

}

Csnake(int n)

//初始化游戏界面大小

{

if(n<20)line=20+2

else if(n>30)line=30+2

else line=n+2

row=line*3+2

}

bool isDead(const Cmp&cmp)

{

return ( getSymbol(cmp)=='@' || cmp.rSign == row-1

|| cmp.rSign== 0 || cmp.lSign == line-1 ||

cmp.lSign == 0 )

}

void InitInstance()//初始化游戏界面

bool UpdataGame()//更新游戏界面

void ShowGame()//显示游戏界面

}

#endif // SNAKE_H

using namespace std

//测试成功

void Csnake::InitInstance()

{

snakeMap.resize(line)// snakeMap[竖坐标][横坐标]

for(int i=0i<linei++)

{

snakeMap[i].resize(row)

for(int j=0j<rowj++)

{

snakeMap[i][j]=' '

}

}

for(int m=1m<maxSize+1m++)

{

//初始蛇身

snakeMap[line/2][m]='@'

//将蛇身坐标压入队列

snakeBody.push(Cmp(m,(line/2)))

//snakeBody[横坐标][竖坐标]

}

//链表头尾

firstSign=snakeBody.back()

secondSign.setPoint(maxSize-1,line/2)

}

//测试成功

int Csnake::GetDirections()const

{

if(GetKeyState(VK_UP)<0) return 1//1表示按下上键

if(GetKeyState(VK_DOWN)<0) return 2//2表示按下下键

if(GetKeyState(VK_LEFT)<0) return 3//3表示按下左键

if(GetKeyState(VK_RIGHT)<0)return 4//4表示按下右键

return 0

}

bool Csnake::UpdataGame()

{

//-----------------------------------------------

//初始化得分0

static int score=0

//获取用户按键信息

int choice

choice=GetDirections()

cout<<"Total score: "<<score<<endl

//随机产生食物所在坐标

int r,l

//开始初始已经吃食,产生一个食物

static bool eatFood=true

//如果吃了一个,才再出现第2个食物

if(eatFood)

{

do

{

//坐标范围限制在(1,1)到(line-2,row-2)对点矩型之间

srand(time(0))

r=(rand()%(row-2))+1//横坐标

l=(rand()%(line-2))+1//竖坐标

//如果随机产生的坐标不是蛇身,则可行

//否则重新产生坐标

if(snakeMap[l][r]!='@')

{snakeMap[l][r]='*'}

}while (snakeMap[l][r]=='@')

}

switch (choice)

{

case 1://向上

//如果蛇头和社颈的横坐标不相同,执行下面操作

if(firstSign.rSign!=secondSign.rSign)nextSign.setPoint(firstSign.rSign,firstSign.lSign-1)

//否则,如下在原本方向上继续移动

else nextSign=firstSign+(firstSign-secondSign)

break

case 2://向下

if(firstSign.rSign!=secondSign.rSign)nextSign.setPoint(firstSign.rSign,firstSign.lSign+1)

else nextSign=firstSign+(firstSign-secondSign)

break

case 3://向左

if(firstSign.lSign!=secondSign.lSign)nextSign.setPoint(firstSign.rSign-1,firstSign.lSign)

else nextSign=firstSign+(firstSign-secondSign)

break

case 4://向右

if(firstSign.lSign!=secondSign.lSign)nextSign.setPoint(firstSign.rSign+1,firstSign.lSign)

else nextSign=firstSign+(firstSign-secondSign)

break

default:

nextSign=firstSign+(firstSign-secondSign)

}

//----------------------------------------------------------

if(getSymbol(nextSign)!='*' &&!isDead(nextSign))

//如果没有碰到食物(且没有死亡的情况下),删除蛇尾,压入新的蛇头

{

//删除蛇尾

lastSign=snakeBody.front()

snakeMap[lastSign.lSign][lastSign.rSign]=' '

snakeBody.pop()

//更新蛇头

secondSign=firstSign

//压入蛇头

snakeBody.push(nextSign)

firstSign=snakeBody.back()

snakeMap[firstSign.lSign][firstSign.rSign]='@'

//没有吃食

eatFood=false

return true

}

//-----吃食-----

else if(getSymbol(nextSign)=='*' &&!isDead(nextSign))

{

secondSign=firstSign

snakeMap[nextSign.lSign][nextSign.rSign]='@'

//只压入蛇头

snakeBody.push(nextSign)

firstSign=snakeBody.back()

eatFood=true

//加分

score+=20

return true

}

//-----死亡-----

else {cout<<"Dead"<<endlcout<<"Your last total score is "<<score<<endlreturn false}

}

void Csnake::ShowGame()

{

for(int i=0i<linei++)

{

for(int j=0j<rowj++)

cout<<snakeMap[i][j]

cout<<endl

}

Sleep(1)

system("cls")

}

int main()

{

Csnake s(20)

s.InitInstance()

//s.ShowGame()

int noDead

do

{

s.ShowGame()

noDead=s.UpdataGame()

}while (noDead)

system("pause")

return 0

}

这个代码可以运行的,记得给分啦

// <Copyright liaoqb>

#include <windows.h>

#include <stdlib.h>

#include <time.h>

const int LENGTH = 40

const int WIDTH = 10

const int RANGE = 50

const int BeginLength = 5

const int speed = 300

#define SNAKE_COLOR RGB(176, 196, 222)

#define BACKGROUND_COLOR RGB(255, 255, 0)

#define DRAW_SNAKE(x) (x) * WIDTH

enum IsSnake {isSnake, isNotSnake, isFood}

IsSnake map[LENGTH][LENGTH]

struct snake {

  int x

  int y

  snake* next

  snake(int x, int y, snake* n = NULL) {

    this -> x = x

this -> y = y

next = n

  }

}  // snake

typedef struct snake Snake

Snake* head = NULL  // queue

Snake* tail = NULL  // queue

int direct = 0  // direction

RECT playground  // district

TCHAR szAppName[] = TEXT("-*- snake game -* ")  // The project name

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM)  // message function

void Initializer()

void Controller(Snake*,LPVOID)  // control the snake

void Move(HWND)

void PutFood()

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, PSTR szCmdLine, int iCmdShow) {

  MSG msg

  HWND hwnd

  WNDCLASS wndclass

  while (TRUE) {

wndclass.cbClsExtra = 0

wndclass.cbWndExtra = 0

wndclass.hbrBackground = CreateSolidBrush(RGB(255, 255, 255))

wndclass.hCursor = LoadCursor(NULL, IDC_ARROW)

wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION)

wndclass.hInstance = hInstance

wndclass.lpfnWndProc = WndProc

wndclass.lpszClassName = szAppName

wndclass.lpszMenuName = NULL

wndclass.style = CS_HREDRAW | CS_VREDRAW

if (!RegisterClass(&wndclass)) {

 MessageBox(NULL, TEXT("Please try again!!!"), szAppName, MB_ICONERROR)

 return 0

}

break

  }

  hwnd = CreateWindow(szAppName, TEXT("<^_^> Snake Game <^_^>"), WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL)

  ShowWindow(hwnd, SW_NORMAL)

  UpdateWindow(hwnd)

  while (TRUE) {

if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {

 if (msg.message == WM_QUIT)

   break

 TranslateMessage(&msg)

 DispatchMessage(&msg)

} else {

 Move(hwnd)

}

  }

  return msg.wParam

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {

  HDC hdc

  PAINTSTRUCT ps

  HBRUSH hBrush

  switch (message) {

  case WM_DESTROY:

PostQuitMessage(0)

return 0

  case WM_CREATE:

Initializer()

MoveWindow(hwnd, RANGE, RANGE, WIDTH * LENGTH + RANGE * 3, WIDTH * LENGTH + RANGE * 3, TRUE)

return 0

  case WM_KEYDOWN:

switch (wParam) {

case VK_LEFT:

 if (direct != VK_RIGHT)

direct = VK_LEFT

 break

case VK_RIGHT:

 if (direct != VK_LEFT)

direct = VK_RIGHT

 break

case VK_UP:

 if (direct != VK_DOWN)

direct = VK_UP

 break

case VK_DOWN:

 if (direct != VK_UP)

direct = VK_DOWN

 break

default:

 break

}

return 0

  case WM_PAINT:

hdc = BeginPaint(hwnd, &ps)

SetViewportOrgEx(hdc, RANGE, RANGE, NULL)

hBrush = CreateSolidBrush(BACKGROUND_COLOR)

SelectObject(hdc, hBrush)

Rectangle(hdc,playground.left, playground.top, playground.right, playground.bottom)

DeleteObject(hBrush)

hBrush = CreateSolidBrush(SNAKE_COLOR)

SelectObject(hdc,hBrush)

for (int i = 0 i < LENGTH ++i) {

 for (int j = 0 j < LENGTH ++j) {

if (map[i][j] == isSnake || map[i][j] == isFood) {

 Rectangle(hdc, DRAW_SNAKE(i), DRAW_SNAKE(j), DRAW_SNAKE(i + 1), DRAW_SNAKE(j + 1))

}

 }

}

DeleteObject(hBrush)

EndPaint(hwnd, &ps)

  }

  return DefWindowProc(hwnd, message, wParam, lParam)

}

void Initializer() {

  for (int i = 0 i < LENGTH ++i) {

for (int j = 0 j < LENGTH ++j) {

 map[i][j] = isNotSnake

}

  }

  for (i = 0 i < BeginLength ++i) {

if (i == 0) {

 head = tail = new snake(i, 0)

} else {

 snake* temp = new snake(i, 0)

 tail -> next = temp

 tail = temp

}

map[i][0] = isSnake

  }

  playground.left = playground.top = 0

  playground.right = playground.bottom = WIDTH * LENGTH

  direct = VK_RIGHT

  PutFood()

}

void PutFood() {

  srand(static_cast<unsigned>(time(NULL)))

  int x, y

  do {

    x = rand() % LENGTH

y = rand() % LENGTH

  } while (map[x][y] == isSnake)

  map[x][y] = isFood

}  // put food

void Move(HWND hwnd) {

  snake* temp

  switch (direct) {

  case VK_LEFT:

temp = new snake(tail -> x - 1, tail -> y)

break

  case VK_RIGHT:

temp = new snake(tail -> x + 1, tail -> y)

break

  case VK_UP:

temp = new snake(tail -> x, tail -> y - 1)

break

  case VK_DOWN:

temp = new snake(tail -> x, tail -> y + 1)

break

  }

  Controller(temp,hwnd)

  //InvalidateRect(hwnd,NULL,FALSE)

  Sleep(speed)  // control speed

}  // snake moving

void Controller(Snake* temp,LPVOID lParam) {

HWND hwnd

hwnd=(HWND)lParam

  if (temp -> x < 0 || temp -> x >= LENGTH || temp -> y < 0 || temp -> y >= LENGTH

|| map[temp -> x][temp -> y] == isSnake) {  // the snake is died

    MessageBox(NULL,TEXT("<Copyright liaoqb> Sorry !!! Game Over !!! <Copyright liaoqb>"),szAppName,0)

delete temp

while (head != NULL) {

 Snake* ptr = head

 head = head -> next

 delete ptr

}

head = tail = temp = NULL

Initializer()

return

  } else if (map[temp -> x][temp -> y] == isNotSnake) {  // move

    map[temp -> x][temp -> y] = isSnake

map[head -> x][head -> y] = isNotSnake

snake* ptr = head

head = head -> next

delete ptr

tail -> next = temp

tail = temp

InvalidateRect(hwnd,NULL,FALSE)

  } else {  // if eat food

    map[temp -> x][temp -> y] = isSnake

tail -> next = temp

tail = temp

PutFood()

//InvalidateRect(hwnd,NULL,FALSE)

  }

}

/*  C语言

program by wlfryq  [email protected]

*/

#include <stdio.h>

#include <stdlib.h>

#include <conio.h>

#include <windows.h>

#include <time.h>

#include <direct.h>

#include <stdbool.h>

#define W 80    //屏幕宽度 

#define H 37    //屏幕高度 

#define SNAKE_ALL_LENGTH 200   //蛇身最长为 

void CALLBACK TimerProc(

HWND hwnd,       

        UINT message,     

        UINT idTimer,     

        DWORD dwTime)

void start()

struct MYPOINT

{

int x

int y

} s[SNAKE_ALL_LENGTH] , head, end, food

int max_count=0 //历史最高分,如果count>max_count, 则max_count=count

int old_max_count=0  //历史最高分,不会变动, 用于死亡时判断max_count是否大于old_max_count,如果大于,则写入文件 

int count=0  //得分 

int len=20   //当前蛇身长度 

int direct=0 //方向: 0-向右, 1-向下, 2-向左, 3-向上

int speed=200  //速度:毫秒 

bool isfood=false //食物是否存在

int timerID

bool stop=false   //暂停 

char* ini_path    //数据文件绝对路径 

void setxy(int x, int y)  //设置CMD窗口光标位置

{

   COORD coord = {x, y}

   SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord)

}

void hide_cursor() //隐藏CMD窗口光标

{

CONSOLE_CURSOR_INFO cci

cci.bVisible = FALSE

cci.dwSize = sizeof(cci)

HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE)

SetConsoleCursorInfo(handle, &cci)

}

void set_food()      //设置食物坐标 

{

if(isfood==true)

{

return

}

int x,y,i

bool flag=false

while(1)

{

flag=false

x=rand()%(W-14)+6

y=rand()%(H-12)+6

for(i=0i<leni++)      //判断食物是否落在蛇身上 

{

if(s[i].x==x && s[i].y==y)

{

flag=true

break

}

}

if(flag==true)

{

continue

}

else

{

food.x=x

food.y=y

break

}

}

setxy(food.x,food.y)

printf("*")

isfood=true

}

void check_board()    //检测蛇身是否越界和相交 

{

int i

if(s[0].x>=W-3 || s[0].x<=2 || s[0].y>=H-1 || s[0].y<=2)

{

setxy(W/2-5,0)

printf("game over\n")

stop=true

if(old_max_count<max_count)

{

char t[5]={'\0'}

sprintf(t,"%d",max_count)

WritePrivateProfileString("MAX_COUNT","max_count",t,ini_path)

}

}

for(i=1i<leni++)

{

if(s[i].x==s[0].x && s[i].y==s[0].y)

{

setxy(W/2-5,0)

printf("game over\n")

stop=true

if(old_max_count<max_count)

{

char t[5]={'\0'}

sprintf(t,"%d",max_count)

WritePrivateProfileString("MAX_COUNT","max_count",t,ini_path)

}

break

}

}

if(stop==true)

{

KillTimer(NULL,timerID)

int c

while(1)

{

fflush(stdin)

c=_getch()

if(c=='n' || c=='N')

{

start()

}

else if(c=='q' || c=='Q')

{

exit(0)

}

else continue

}

}

}

void printf_body(bool is_first)  //打印蛇身 

{

if(is_first==true)     //如果是第一次打印蛇身 

{

int i

for(i=0i<leni++)

{

setxy(s[i].x,s[i].y)

printf("O")

}

}

else                  //如果不是第一次打印蛇身 

{

setxy(end.x,end.y)

printf(" ")

setxy(s[0].x,s[0].y)

printf("O")

}

if(food.x==s[0].x && food.y==s[0].y)  //如果吃到食物 

{

count++

isfood=false                     //重置食物 

set_food()

len++

KillTimer(NULL,timerID)

if(speed>100) speed-=10

else if(speed>50) speed-=5

else if(speed>30) speed-=2

else if(speed>16) speed-=1

else 

setxy(0,0)

if(max_count<count) max_count=count

printf("  speed : %d ms     score : %d                                   best score:%d  ",speed,count,max_count)

timerID=SetTimer(NULL,001,speed,TimerProc)

}

}

void change_body_pos(int x, int y)   //改变蛇身的坐标数据 

{

end.x=s[len-1].x

end.y=s[len-1].y

int i

for(i=len-1i>0i--)

{

s[i].x=s[i-1].x

s[i].y=s[i-1].y

}

s[0].x=x

s[0].y=y

}

void CALLBACK TimerProc(

HWND hwnd,       

        UINT message,     

        UINT idTimer,     

        DWORD dwTime)

{

switch(direct)

{

case 0:

head.x++

change_body_pos(head.x,head.y)

printf_body(false)

check_board()

break

case 1:

head.y++

change_body_pos(head.x,head.y)

printf_body(false)

check_board()

break

case 2:

head.x--

change_body_pos(head.x,head.y)

printf_body(false)

check_board()

break

case 3:

head.y--

change_body_pos(head.x,head.y)

printf_body(false)

check_board()

break

}

}

void start()

{

int i

KillTimer(NULL,timerID)

count=0  //得分 

len=20   //当前蛇身长度 

direct=0 //方向: 0-向右, 1-向下, 2-向左, 3-向上

speed=200  //速度:毫秒 

isfood=false //食物是否存在

stop=false   //停止 

system("cls")

setxy(1,4)

printf("┌─────────────────────────────────────┐\n")

for(i=0i<33i++)

{

printf(" │                                                                          │\n")

}

printf(" └─────────────────────────────────────┘")

head.x=len-1+5

head.y=H/2

for(i=0i<leni++)

{

s[i].x=head.x-i

s[i].y=head.y

}

setxy(0,0)

printf("  speed : %d:ms     score : %d                                   best score:%d  ",speed,count,max_count)

printf_body(true)

set_food()

timerID=SetTimer(NULL,001,speed,TimerProc)

int c

MSG msg

while(GetMessage(&msg,NULL,0,0))

{

if(stop==true) break

if(_kbhit())   //如果按下的是方向键或功能键, _getch()要调用两次,第一次返回0XE0或0 

{

fflush(stdin)

c=_getch()   //上: 72 下:80  左:75  右:77 

if(c==0XE0 || c==0)

{

c=_getch()

if(c==72 && direct!=1 && direct!=3)

{

direct=3

}

else if(c==80 && direct!=1 && direct!=3)

{

direct=1

}

else if(c==75 && direct!=0 && direct!=2)

{

direct=2

}

else if(c==77 && direct!=0 && direct!=2)

{

direct=0

}

}

else if(c==' ')

{

setxy(W/2-10,0)

system("pause")

setxy(W/2-10,0)

printf("                    ")

}

}

if(msg.message==WM_TIMER)

{

DispatchMessage(&msg)

}

}

}

int main()

{

ini_path=(char*)malloc(sizeof(char)*50)

srand((unsigned)time(0))

getcwd(ini_path,50)//取得当前程序绝对路径

ini_path=strcat(ini_path,"snake.dat")

max_count=GetPrivateProfileInt("MAX_COUNT","max_count",0,ini_path)

old_max_count=max_count

char cmd[50]

sprintf(cmd,"mode con cols=%d lines=%d\0",W,H)

system(cmd)//改变CMD窗口大小

hide_cursor()

start()

return 0

}