MFC-贪吃蛇

项目代码:

https://yunpan.cn/cYvqi5UmBdJEJ (提取码:05a6)


// 定义一个贪吃蛇的其中之一
typedef struct ty_snake {
int x;
int y;
COLORREF color;
} snake;

// 游戏区域左侧与顶部
const int GAME_SIDE_LEFT = 10;
const int GAME_SIDE_TOP = 10;

// 游戏区域中的一个方块的宽度
const int GAME_WIDTH = 20;

// 游戏区域宽和高有多少个方块
const int NUMT = 20;

// 随机的颜色
#define COLOR_RAND RGB(rand()%200+30,rand()%200+30,rand()%200+30)

// 定义方向
enum DIRECT {UP = -1,DOWN = 1,LEFT = -2,RIGHT = 2};

---------

#pragma once
#include <list>
class CSnake
{
public:
	CSnake();
	~CSnake();
	std::list<snake> m_snake;
	void makeSnake();
	int m_direction;
	void Draw();
	CRect getSnakePos(snake sn);
	void makeOneSnake();
	snake m_onesnake;
	BOOL move();
	void alterDirect(int direct);
	BOOL dealOut(snake sn);
	BOOL haveSnake(snake sn);
};

-----------

#include "stdafx.h"
#include "Snake.h"
#include "time.h"
#include <string>
#include <algorithm>
CSnake::CSnake()
{
	m_direction = UP;
}


CSnake::~CSnake()
{
}


void CSnake::makeSnake()
{
	srand((unsigned)time(0));
	snake sn1 = {NUMT/2,NUMT/2,COLOR_RAND};
	m_snake.push_back(sn1);
	snake sn2 = { NUMT / 2+1,NUMT / 2,COLOR_RAND };
	m_snake.push_back(sn2);
}

void CSnake::makeOneSnake()
{
	srand((unsigned)time(0));
	m_onesnake = { rand()%NUMT,rand() % NUMT,COLOR_RAND };
}

void CSnake::Draw()
{
	CClientDC* dc = (CClientDC*)AfxGetMainWnd()->GetDC();
	dc->FillSolidRect(CRect(GAME_SIDE_LEFT,GAME_SIDE_TOP,GAME_SIDE_LEFT+GAME_WIDTH*NUMT,GAME_SIDE_TOP+GAME_WIDTH*NUMT), RGB(255,255,255));
	std::for_each(m_snake.begin(), m_snake.end(), [=](snake sn) {
		dc->FillSolidRect(getSnakePos(sn), sn.color);
	});
	dc->FillSolidRect(getSnakePos(m_onesnake), m_onesnake.color);
	dc->DeleteDC();
	dc = nullptr;
}


CRect CSnake::getSnakePos(snake sn)
{
	return CRect(GAME_SIDE_LEFT+sn.x*GAME_WIDTH,
		GAME_SIDE_TOP+sn.y*GAME_WIDTH,
		GAME_SIDE_LEFT + (sn.x+1)*GAME_WIDTH,
		GAME_SIDE_TOP + (sn.y+1)*GAME_WIDTH);
}

BOOL CSnake::move()
{
	snake asn;
	switch (m_direction)
	{
	case UP: {
		asn = {m_snake.front().x,m_snake.front().y-1,m_snake.back().color};
		break;
	}
	case DOWN: {
		asn = { m_snake.front().x,m_snake.front().y + 1,m_snake.back().color };
		break;
	}
	case LEFT: {
		asn = { m_snake.front().x-1,m_snake.front().y,m_snake.back().color };
		break;
	}
	case RIGHT: {
		asn = { m_snake.front().x+1,m_snake.front().y,m_snake.back().color };
		break;
	}
	default:
		break;
	}
	if (dealOut(asn)) {
		return FALSE;
	}
	if (haveSnake(asn)) {
		m_snake.push_front(m_onesnake);
		makeOneSnake();
		move();
		return TRUE;
	}
	m_snake.push_front(asn);
	m_snake.pop_back();
	return TRUE;
}


void CSnake::alterDirect(int direct)
{
	if (direct == m_direction) {
		return;
	}
	if (direct == -m_direction) {
		return;
	}
	m_direction = direct;
}


BOOL CSnake::dealOut(snake sn)
{
	if (sn.x < 0 || sn.y < 0 || sn.x >= NUMT || sn.y >= NUMT) {
		return TRUE;
	}
	for (auto e : m_snake) {
		if (sn.x == e.x && sn.y == e.y) {
			return TRUE;
		}
	}
	return FALSE;
}


BOOL CSnake::haveSnake(snake sn)
{
	if (sn.x == m_onesnake.x && sn.y == m_onesnake.y) {
		return TRUE;
	}
	return FALSE;
}

-----------

初始化

m_stop = 1;
	m_start = 0;
	snk = new CSnake;


void CSnakeGameDlg::OnBnClickedOk()
{
	if (!m_start) {
		snk->makeSnake();
		snk->makeOneSnake();
		snk->Draw();
		SetTimer(1002, 500, 0);
		m_start = 1;
		m_stop = 0;
		return;
	}
	if (m_start) {
		if (m_stop) {
			SetTimer(1002, 500, 0);
			m_stop = 0;
		}
		else {
			KillTimer(1002);
			m_stop = 1;
		}
	}
	
	
}


void CSnakeGameDlg::OnBnClickedAgain()
{
	m_stop = 0;
	m_start = 1;
	snk->m_snake.clear();
	snk->makeSnake();
	snk->makeOneSnake();
	snk->Draw();
	SetTimer(1002, 500, 0);
}


void CSnakeGameDlg::OnBnClickedCancel()
{
	
	CDialog::OnCancel();
}


void CSnakeGameDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	switch (nIDEvent)
	{
	case 1002: {
		if (snk->move() == FALSE) {
			KillTimer(nIDEvent);
			m_start = 0;
			m_stop = 1;
			AfxMessageBox(L"游戏结束");
		}
		snk->Draw();
		break;
	}
	default:
		break;
	}
	CDialog::OnTimer(nIDEvent);
}


BOOL CSnakeGameDlg::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类
	if (pMsg->message == WM_KEYDOWN) {
		switch (pMsg->wParam)
		{
		case VK_LEFT: {
			snk->alterDirect(LEFT);
			break;
		}
		case VK_RIGHT: {
			snk->alterDirect(RIGHT);
			break;
		}
		case VK_DOWN: {
			snk->alterDirect(DOWN);
			break;
		}
		case VK_UP: {
			snk->alterDirect(UP);
			break;
		}
		default:
			break;
		}
		return TRUE;
	}
	return CDialog::PreTranslateMessage(pMsg);
}


你可能感兴趣的:(MFC-贪吃蛇)