#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
}