21xrx.com
2024-11-05 16:27:18 Tuesday
登录
文章检索 我的文章 写文章
C++编程教程:制作贪吃蛇游戏
2023-06-26 00:55:13 深夜i     --     --
C++ 编程教程 贪吃蛇 游戏制作 学习编程

贪吃蛇游戏是一款古老但经典的游戏,也是初学者入门编程的良好学习项目。本文将介绍使用C++语言制作贪吃蛇游戏的编程教程。

首先,我们需要准备一些必要的工具,如C++编译器和文本编辑器。建议初学者使用易于操作和功能完善的IDE集成环境,如Visual Studio等,以便更好地进行代码编写和调试。

接下来,我们需要确定游戏的基本规则和交互方式。贪吃蛇游戏的规则非常简单,游戏者需要控制一条小蛇在固定大小的矩形空间内移动,吃到食物得分并变长,但不得撞到自身或矩形边缘。游戏可使用键盘或鼠标进行控制。

然后,我们需要创建一个窗口,用来展示游戏场景和实现交互功能。在C++中,可以使用Windows API或SDL等库实现此功能。这里我们以Windows API为例,在编译过程中需要链接user32.lib库文件。创建窗口的部分代码如下:


#include <windows.h>

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

  WNDCLASSEX wcex;

  HWND hWnd;

  MSG msg;

  TCHAR szWindowClass[] = TEXT("Snake");

  TCHAR szTitle[] = TEXT("Greedy Snake Game");

  wcex.cbSize = sizeof(WNDCLASSEX);

  wcex.style = CS_HREDRAW | CS_VREDRAW;

  wcex.lpfnWndProc = WndProc;

  wcex.cbClsExtra = 0;

  wcex.cbWndExtra = 0;

  wcex.hInstance = hInstance;

  wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);

  wcex.hCursor = LoadCursor(NULL, IDC_ARROW);

  wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

  wcex.lpszMenuName = NULL;

  wcex.lpszClassName = szWindowClass;

  wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);

  if (!RegisterClassEx(&wcex)) {

    MessageBox(NULL, TEXT("Window registration failed!"), TEXT("Greedy Snake Game"), NULL);

    return 1;

  }

  hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);

  if (!hWnd) {

    MessageBox(NULL, TEXT("Window creation failed!"), TEXT("Greedy Snake Game"), NULL);

    return 1;

  }

  ShowWindow(hWnd, nCmdShow);

  UpdateWindow(hWnd);

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

    TranslateMessage(&msg);

    DispatchMessage(&msg);

  }

  return (int) msg.wParam;

}

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

  PAINTSTRUCT ps;

  HDC hdc;

  switch (message) {

    case WM_PAINT:

      hdc = BeginPaint(hWnd, &ps);

      EndPaint(hWnd, &ps);

      break;

    case WM_DESTROY:

      PostQuitMessage(0);

      break;

    default:

      return DefWindowProc(hWnd, message, wParam, lParam);

  }

  return 0;

}

以上代码段创建了一个名为"Greedy Snake Game"的窗口,并注册了一个名为"Snake"的窗口类。在窗口处理函数WndProc中处理了窗口消息处理的部分。现在运行程序,将展示一个大小为640x480的窗口。

接下来,我们需要实现游戏的主要功能和逻辑。贪吃蛇的核心部分是实现蛇的移动和碰撞检测,还需要实现随机生成食物和计分。我们可以使用基本的数据结构,如数组和链表来实现。下面给出核心部分代码示例:


// 定义蛇的结构体

struct SnakeNode {

  int x;

  int y;

  SnakeNode* next;

};

SnakeNode* head; // 蛇头指针

SnakeNode* tail; // 蛇尾指针

int direction;  // 当前方向,1代表上,2代表下,3代表左,4代表右

int score;    // 得分

int food_x;    // 食物的横坐标

int food_y;    // 食物的纵坐标

void StartGame() {

  SnakeNode* newNode = new SnakeNode;

  head = newNode;

  tail = newNode;

  head->x = 10;

  head->y = 10;

  tail->x = 9;

  tail->y = 10;

  tail->next = head;

  direction = 4;

  score = 0;

  srand(time(NULL));

  GenerateFood();

}

void GenerateFood() {

  food_x = rand() % (640 / 10);

  food_y = rand() % (480 / 10);

}

void MoveSnake() {

  SnakeNode* newNode = new SnakeNode;

  newNode->x = head->x;

  newNode->y = head->y;

  switch (direction) {

    case 1:

      head->y--;

      break;

    case 2:

      head->y++;

      break;

    case 3:

      head->x--;

      break;

    case 4:

      head->x++;

      break;

    default:

      break;

  }

  if (head->x == food_x && head->y == food_y) {

    score += 10;

    GenerateFood();

    newNode->next = head;

    head = newNode;

  } else {

    newNode->next = head;

    head = newNode;

    SnakeNode* node = tail;

    while (node->next != head)

      node = node->next;

    

    tail = node;

    tail->next = NULL;

  }

}

bool CheckCollision() {

  SnakeNode* node = head->next;

  while (node) {

    if (node->x == head->x && node->y == head->y)

      return true;

    

    node = node->next;

  }

  if (head->x < 0 || head->y < 0 || head->x >= 640/10 || head->y >= 480/10)

    return true;

  

  return false;

}

以上代码段中定义了蛇的结构体和头和尾的指针,记录了蛇的运动方向、当前得分、食物坐标等信息,并实现了游戏初始化、蛇的移动、食物的生成和碰撞检测等功能。

最后我们需要将游戏画面完善,包括画蛇、画食物、显示得分等部分。我们可以使用Windows API中的GDI库来实现画图功能。最终的代码示例如下:


void PaintGame(HDC hdc) {

  MoveSnake();

  if (CheckCollision()) {

    KillTimer(hWnd, 1);

    char s[50];

    sprintf_s(s, "Game Over! The final score is %d", score);

    MessageBox(NULL, s, "Greedy Snake Game", NULL);

    exit(0);

  }

  Rectangle(hdc, food_x * 10, food_y * 10, food_x * 10 + 10, food_y * 10 + 10);

  SnakeNode* node = head;

  while (node) {

    Rectangle(hdc, node->x * 10, node->y * 10, node->x * 10 + 10, node->y * 10 + 10);

    node = node->next;

  }

  char s[20];

  sprintf_s(s, "Score: %d", score);

  TextOut(hdc, 20, 20, s, strlen(s));

}

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

  PAINTSTRUCT ps;

  HDC hdc;

  switch (message) {

    case WM_PAINT:

      hdc = BeginPaint(hWnd, &ps);

      PaintGame(hdc);

      EndPaint(hWnd, &ps);

      break;

    case WM_DESTROY:

      PostQuitMessage(0);

      break;

    case WM_KEYDOWN:

      switch (wParam) {

        case VK_UP:

          if (direction != 2)

            direction = 1;

          

          break;

        case VK_DOWN:

          if (direction != 1)

            direction = 2;

          

          break;

        case VK_LEFT:

          if (direction != 4)

            direction = 3;

          

          break;

        case VK_RIGHT:

          if (direction != 3)

            direction = 4;

          

          break;

        default:

          break;

      }

      break;

    case WM_TIMER:

      InvalidateRect(hWnd, NULL, TRUE);

      break;

    case WM_CREATE:

      SetTimer(hWnd, 1, 100, NULL);

      StartGame();

      break;

    default:

      return DefWindowProc(hWnd, message, wParam, lParam);

  }

  return 0;

}

最后,我们只需要将以上代码整合到一个完整的C++文件中进行编译和执行,就能够愉快地玩耍我们自己制作的贪吃蛇游戏了。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复