#include<windows.h>
#include <time.h>
#include "resource.h"
#define WIN_WIDTH 830 // 窗口宽度
#define WIN_DEPTH 540 // 窗口长度
#define GAMEZONE_LEFT 10 // 游戏区域左
#define GAMEZONE_TOP 10 // 游戏区域顶
#define GAMEZONE_RIGHT 690 // 游戏区域右
#define GAMEZONE_BUTTOM 490 // 游戏区域底
#define TIPZONE_LEFT 700 // 提示区域左
#define TIPZONE_RIGHT 800 // 提示区域右
#define TIPZONE_TOP 10 // 提示区域顶
#define TIPZONE_BUTTOM 490 // 提示区域底
#define BOXSIZE 10 // 盒子大小
#define LEFT 1001 // 左移
#define RIGHT 1002 // 右移
#define UP 1003 // 上移
#define DOWN 1004 // 下移
#define MAXSIZE 1000 // 最大长度
#define START_X 50 // 开始区域
#define START_Y 50 // 开始区域
#define SCORE_PER_FOOD 10 // 每吃一个食物所得分数
/* 变量声明 */
typedef struct{
int num;
int pos_x, pos_y;
int dir;
int color_r, color_g, color_b;
}SNAKE;
static SNAKE snake[MAXSIZE]; // 蛇数组
static int snake_length = 3; // 蛇开始长度
static BOOL bump_flag = 0; // 撞车标志
static int gameZome[GAMEZONE_RIGHT][WIN_DEPTH]; // 游戏区域
static SNAKE Food; // 食物位置
static int makefoodflag = 1; // 产生食物
HWND hwndBut1,hwndBut2,hwndBut3; // 按钮
HWND hwndEdit1, hwndEdit2, hwndEdit3; // 静态文本框
static int score = 0; // 分数
static int current_speed = 100; // 当前速度
TCHAR szbuf[50] = L"";
//
/****** 函数说明 *******/
void DrawBk(HDC); // 画背景
void AddNode(SNAKE); // 添加结点
SNAKE SetNode(int x,int y, int dir, int r,int g, int b); // 获得一个新接点
void DrawBox(HDC, SNAKE); // 画小方块
void MoveSnake(); // 移动蛇
void DrawSnake(HDC); // 画蛇
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM); // 窗口回调函数
BOOL IsBump(); // 判断是否撞击,如果撞击返回1,否则返回0
void InitGame(); // 初始化游戏
void DrawGameZone(HDC); // 画出游戏区域(test)
BOOL IsBump(); // 判断是否相撞
void MakeFood(); // 随机在游戏区域内产生一个结点
// 主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
HWND hwnd;
MSG msg;
TCHAR szAppName[] = L"Win32";
WNDCLASS wndcls;
wndcls.style = CS_HREDRAW | CS_VREDRAW|CS_NOCLOSE;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
wndcls.hInstance = hInstance;
wndcls.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)); // 手动添加资源
wndcls.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR1)); // 手动添加资源
wndcls.hbrBackground = static_cast<HBRUSH>(GetStockObject(LTGRAY_BRUSH));
wndcls.lpfnWndProc = WinProc;
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = szAppName;
if (!RegisterClass(&wndcls)){
MessageBox(NULL, L"注册窗口失败,该程序必须运行在windows操作系统下!", L"Tips", MB_ICONINFORMATION);
return 0;
}
hwnd = CreateWindow(szAppName,
L"Snake", WS_OVERLAPPEDWINDOW&~WS_MAXIMIZEBOX^WS_THICKFRAME,
50, 50, WIN_WIDTH, WIN_DEPTH, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
HDC hdc;
PAINTSTRUCT ps;
TEXTMETRIC tm;
SNAKE sk;
static HINSTANCE hInstance;
static int time_counter = 0;
static int keydown = 0;
static int cxChar, cyChar, cxCaps;
switch (message){
case WM_CREATE:
srand(time(0));
hwndBut1 = CreateWindow(L"BUTTON", L"新游戏",WS_CHILD | WS_VISIBLE, GAMEZONE_RIGHT + 20, TIPZONE_TOP + 20, 80, 20, hwnd, (HMENU)1, hInstance, NULL);
hwndBut2 = CreateWindow(L"BUTTON", L"暂停",WS_CHILD | WS_VISIBLE, GAMEZONE_RIGHT + 20, TIPZONE_TOP + 60, 80, 20, hwnd, (HMENU)2, hInstance, NULL);
hwndBut3 = CreateWindow(L"BUTTON", L"退出", WS_CHILD | WS_VISIBLE, GAMEZONE_RIGHT + 20, GAMEZONE_TOP + 100, 80, 20, hwnd, (HMENU)3, hInstance, NULL);
hwndEdit1 = CreateWindow(L"EDIT", L"分数:0", WS_CHILD | WS_VISIBLE | ES_READONLY, GAMEZONE_RIGHT + 20, TIPZONE_TOP + 200, 80, 20, hwnd, (HMENU)4, hInstance, NULL);
hwndEdit2 = CreateWindow(L"EDIT", L"关卡:1", WS_CHILD | WS_VISIBLE | ES_READONLY, GAMEZONE_RIGHT + 20, TIPZONE_TOP + 240, 80, 20, hwnd, (HMENU)5, hInstance, NULL);
hwndEdit3 = CreateWindow(L"EDIT", L"时间:0", WS_CHILD | WS_VISIBLE | ES_READONLY, GAMEZONE_RIGHT + 20, TIPZONE_TOP + 280, 80, 20, hwnd, (HMENU)6, hInstance, NULL);
InitGame(); // 初始化游戏区域
hdc = GetDC(hwnd);
SetTimer(hwnd, 1, current_speed, NULL);
ReleaseDC(hwnd, hdc);
return 0;
case WM_COMMAND:{
switch (LOWORD(wParam)){
case 1: {// 新游戏
KillTimer(hwnd, 1);
int sel = MessageBox(hwnd, L"开始新游戏?", L"新游戏", MB_OKCANCEL | MB_ICONQUESTION);
if (sel == IDOK){
memset(snake, 0, sizeof(snake) / sizeof(SNAKE));
RECT rect;
GetClientRect(hwnd, &rect);
InitGame();
score = 0;
SetTimer(hwnd, 1, current_speed, NULL);
SetWindowText(hwndEdit1, L"分数:0");
InvalidateRect(hwnd, &rect, TRUE);
}
else {
SetTimer(hwnd, 1, current_speed, NULL);
SetFocus(hwnd);
}
}break;
case 2:
GetDlgItemText(hwnd, 2, szbuf, 50);
if (lstrcmp(szbuf, L"暂停") == 0){
KillTimer(hwnd, 1);
SetDlgItemText(hwnd, 2, L"开始");
}
else if (lstrcmp(szbuf, L"开始") == 0){
SetTimer(hwnd, 1, current_speed,NULL);
SetDlgItemText(hwnd, 2, L"暂停");
SetFocus(hwnd);
}
break;
case 3:{ // 退出
KillTimer(hwnd, 1);
int sel = MessageBox(hwnd, L"退出游戏?", L"退出", MB_OKCANCEL|MB_ICONINFORMATION);
if (sel == IDOK){
PostQuitMessage(0);
return 0;
}
SetTimer(hwnd, 1, current_speed, NULL);
SetFocus(hwnd);
}break;
case 4:
case 5:
case 6: SetFocus(hwnd); break;
}
}return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
DrawBk(hdc);
GetTextMetrics(hdc, &tm);
SetTextColor(hdc, RGB(57, 50, 244));
SetBkColor(hdc, RGB(22, 123, 22));
cyChar = tm.tmHeight;
TextOut(hdc, GAMEZONE_RIGHT + 13, 390, szbuf, wsprintf(szbuf, L"游戏规则:"));
TextOut(hdc, GAMEZONE_RIGHT + 13, 400 + cyChar, szbuf, wsprintf(szbuf, L" 按↑↓←→"));
TextOut(hdc, GAMEZONE_RIGHT + 13, 400 + 2 * cyChar, szbuf, wsprintf(szbuf, L"来控制蛇移动"));
TextOut(hdc, GAMEZONE_RIGHT + 13, 400 + 3 * cyChar, szbuf, wsprintf(szbuf, L"的方向"));
DrawBox(hdc, Food);
EndPaint(hwnd, &ps);
return 0;
case WM_KEYDOWN:{
if (keydown) break;
switch (wParam){
case VK_LEFT:
if (snake[0].dir != RIGHT){
snake[0].dir = LEFT;
keydown = 1;
}break;
case VK_RIGHT:
if (snake[0].dir != LEFT){
snake[0].dir = RIGHT;
keydown = 1;
}break;
case VK_UP:
if (snake[0].dir != DOWN){
snake[0].dir = UP;
keydown = 1;
}break;
case VK_DOWN:
if (snake[0].dir != UP){
snake[0].dir = DOWN;
keydown = 1;
}break;
}
}return 0;
case WM_TIMER: {
KillTimer(hwnd, 1);
// 如果按键按下置0
if (keydown) keydown = 0;
// 提示游戏时间
static int counter = 1000 / current_speed;
if (counter-- == 0){
counter = 1000 / current_speed;
time_counter++;
wsprintf(szbuf, L"时间:%d", time_counter);
SetWindowText(hwndEdit3, szbuf);
}
// 产生新食物
if (makefoodflag == 1){
makefoodflag = 0;
hdc = GetDC(hwnd);
MakeFood();
DrawBox(hdc, Food);
DeleteDC(hdc);
}
// 判断是否碰撞
if (bump_flag == 1 || bump_flag == 2){
KillTimer(hwnd, 1);
MessageBox(hwnd, L"游戏结束!", L"结束", MB_ICONINFORMATION);
SetDlgItemText(hwnd, 1, L"");Sleep(150);
SetDlgItemText(hwnd, 1, L"新游戏");Sleep(150);
SetDlgItemText(hwnd, 1, L"");Sleep(150);
SetDlgItemText(hwnd, 1, L"新游戏");Sleep(150);
SetDlgItemText(hwnd, 1, L""); Sleep(150);
SetDlgItemText(hwnd, 1, L"新游戏");
return 0;
}
// 移动蛇
hdc = GetDC(hwnd);
MoveSnake();
DrawSnake(hdc);
DeleteDC(hdc);
SetTimer(hwnd, 1, current_speed, NULL);
}return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
// 初始化游戏区域
void InitGame(){
// 清0
memset(gameZome, 0, sizeof(gameZome) / sizeof(int));
// 添加初始结点
SNAKE sk;
sk = SetNode(START_X, START_Y, RIGHT, 255, 0, 0); // 设置头结点
snake[0] = sk;
sk.pos_x = snake[0].pos_x - BOXSIZE;
snake[1] = sk;
sk.pos_x = snake[1].pos_x - BOXSIZE;
sk.color_b = sk.color_g = sk.color_r = 0;
snake[2] = sk;
snake_length = 3;
// 未撞车
bump_flag = 0;
// 左边框
for (int i = 0; i < GAMEZONE_LEFT; i++){
for (int j = 0; j < WIN_DEPTH; j++)
gameZome[i][j] = 1;
}
// 下边框
for (int i = 0; i < GAMEZONE_RIGHT; i++){
for (int j = GAMEZONE_BUTTOM; j < WIN_DEPTH; j++)
gameZome[i][j] = 1;
}
// 上边框
for (int i = 0; i < GAMEZONE_TOP; i++){
for (int j = GAMEZONE_LEFT; j < GAMEZONE_RIGHT; j++)
gameZome[j][i] = 1;
}
// 右边框
for (int j = GAMEZONE_RIGHT-10; j < TIPZONE_LEFT; j++){
for (int i = GAMEZONE_TOP; i < GAMEZONE_BUTTOM; i++)
gameZome[j][i] = 1;
}
}
// 画小盒子
void DrawBox(HDC hdc,SNAKE s){
HPEN pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); // 改变矩形边框的颜色
SelectObject(hdc, pen);
HBRUSH br = CreateSolidBrush(RGB(s.color_r, s.color_g, s.color_b));
SelectObject(hdc, br);
Rectangle(hdc, s.pos_x, s.pos_y, s.pos_x + BOXSIZE, s.pos_y + BOXSIZE);
DeleteObject(pen);
DeleteObject(br);
}
// 添加结点
void AddNode(SNAKE newNode){
// 插入到原来的黑色结点中
snake[snake_length - 1].color_r = newNode.color_r;
snake[snake_length - 1].color_g = newNode.color_g;
snake[snake_length - 1].color_b = newNode.color_b;
// 添加一个黑色结点
snake[snake_length] = snake[snake_length - 1];
snake[snake_length].color_r = snake[snake_length].color_g = snake[snake_length].color_b = 0;
switch (snake[snake_length-1].dir){
case LEFT:snake[snake_length].pos_x += BOXSIZE;break;
case RIGHT:snake[snake_length].pos_x -= BOXSIZE; break;
case UP:snake[snake_length].pos_y += BOXSIZE; break;
case DOWN:snake[snake_length].pos_y -= BOXSIZE; break;
}
// 长度加1
snake_length++;
}
// 获取一个新结点
SNAKE SetNode(int x,int y, int dir, int r, int g, int b){
SNAKE s;
s.pos_x = x;
s.pos_y = y;
s.color_r = r;
s.color_g = g;
s.color_b = b;
s.dir = dir;
return s;
}
// 画背景
void DrawBk(HDC hdc){
HBRUSH brBk;
// 画整个板面
brBk = CreateSolidBrush(RGB(245, 245,245));
SelectObject(hdc, brBk);
Rectangle(hdc, 0, 0, WIN_WIDTH, WIN_DEPTH);
// 画游戏区域
brBk = CreateSolidBrush(RGB(0, 0, 0));
SelectObject(hdc, brBk);
Rectangle(hdc, GAMEZONE_LEFT, GAMEZONE_TOP,GAMEZONE_RIGHT ,GAMEZONE_BUTTOM);
// 画提示区域
HPEN hpen = CreatePen(PS_SOLID, 1, RGB(22,123,22));
SelectObject(hdc, hpen);
for (int i = TIPZONE_TOP; i < TIPZONE_BUTTOM; i++){
MoveToEx(hdc, TIPZONE_LEFT,i, NULL);
LineTo(hdc, TIPZONE_RIGHT,i);
}
DeleteObject(hpen);
DeleteObject(brBk);
}
// 画出蛇
void DrawSnake(HDC hdc){
for (int i = 0; i < snake_length; i++){
DrawBox(hdc, snake[i]);
}
}
// 移动
void MoveSnake(){
for (int i = 0; i < snake_length; i++){
switch (snake[i].dir){
case LEFT:
snake[i].pos_x -= BOXSIZE;
break;
case RIGHT:
snake[i].pos_x += BOXSIZE;
break;
case UP:
snake[i].pos_y -= BOXSIZE;
break;
case DOWN:
snake[i].pos_y += BOXSIZE;
break;
}
}
bump_flag = IsBump();
if (snake[0].pos_x == Food.pos_x && snake[0].pos_y == Food.pos_y)
{
AddNode(Food);
makefoodflag = 1;
score += SCORE_PER_FOOD;
wsprintf(szbuf, L"分数:%d", score);
SetWindowText(hwndEdit1, szbuf);
}
for (int i = snake_length - 1; i >= 1; i--){
snake[i].dir = snake[i - 1].dir;
}
//snake[snake_length - 1].color_b = snake[snake_length - 1].color_g = snake[snake_length - 1].color_r = 0;
}
// 画游戏区域
void DrawGameZone(HDC hdc){
for (int i = 0; i < GAMEZONE_RIGHT; i++){
for (int j = 0; j < WIN_DEPTH;j++)
if (gameZome[i][j] == 1) SetPixel(hdc, i, j, RGB(0, 0, 255));
else if (gameZome[i][j] == 2) SetPixel(hdc, i, j, RGB(255, 0, 0));
else SetPixel(hdc, i, j, RGB(0, 255, 0));
}
}
BOOL IsBump(){
// 判断蛇是否撞
int cur_x = snake[0].pos_x, cur_y = snake[0].pos_y;
if (gameZome[cur_x][cur_y] == 1) return 1;
for (int i = 2; i < snake_length - 1; i++){
if (cur_x == snake[i].pos_x && cur_y == snake[i].pos_y) // ←
return 2;
}
return 0;
}
// 随机在游戏区域内产生一个结点
void MakeFood(){
Food.pos_x = GAMEZONE_LEFT + rand() % (GAMEZONE_RIGHT - GAMEZONE_LEFT-10);
Food.pos_y = GAMEZONE_TOP + rand() % (GAMEZONE_BUTTOM - GAMEZONE_TOP-10);
Food.color_r = 10 + rand() % 255;
Food.color_g = 10 + rand() % 255;
Food.color_b = 10 + rand() % 255;
if (Food.pos_x % 10 != 0){
Food.pos_x += 10 - Food.pos_x % 10;
}
if (Food.pos_y % 10 != 0){
Food.pos_y += 10 - Food.pos_y % 10;
}
// 如果产生的食物被覆盖
for (int i = 0; i < snake_length; i++){
if (Food.pos_x == snake[i].pos_x && Food.pos_y == snake[i].pos_y)
makefoodflag = 1;
}
}
Win32 贪吃蛇游戏
最新推荐文章于 2023-12-06 16:53:49 发布