贪吃蛇第2部分——按键移动贪吃蛇

#include <iostream>
#include <graphics.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
using namespace std;

#define BLOCK_SIZE 20//注意,不要等于号=,也不要分号;
#define WIDTH 40
#define HEIGHT 30

//全局变量定义
int Blocks[HEIGHT][WIDTH];//注意二维数组第一格是行号,第二个是列号,所以第一格是HEIGHT而不是WIDTH,这个数组是30行40列的数组
char moveDirection;//方向定义为全局变量

//初始化函数
void startup()//初始化蛇身位置、颜色
{
    int i; 
    Blocks[HEIGHT / 2][WIDTH / 2] = 1;
    for (int i = 1; i < 6; i++)//从中间开始画贪吃蛇,设头部的数值为1.存入数组中,从头到尾依次增大,尾巴数值为4
    {
        Blocks[HEIGHT / 2][WIDTH / 2 - i] = i + 1;
    }
    initgraph(WIDTH * BLOCK_SIZE, HEIGHT * BLOCK_SIZE);
    setlinecolor(RGB(200, 200, 200));//线条颜色设为白色,即格子与格子之间的空隙设为白色,比较好看
    BeginBatchDraw();//批量绘制,防止屏幕闪烁


}

//绘制函数
void show()//把蛇身和其他方格都画出来
{
    cleardevice();//清屏
    for (int i = 0; i < HEIGHT; i++)//一行行遍历
        for (int j = 0; j < WIDTH; j++)
        {
            if (Blocks[i][j] > 0)//遍历数组,数值大于0的就是贪吃蛇身体部分,需要填色
            {
                setfillcolor(HSVtoRGB(Blocks[i][j] * 10, 0.9, 1));/*用数组中存储的连续的数值(从1到4)来为贪吃蛇
                上色就可以得到渐变色,但是1到4之间跨度太小,需要*10,颜色范围为10到40,可得较好看的渐变色*/
            }
            else
                setfillcolor(RGB(150, 150, 150));//数值不大于0则不是贪吃蛇身体,格子设置为灰色
            fillrectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE);//填充颜色
        }
    FlushBatchDraw();
}
void moveSnake()//这个函数只需要实现12345这几个数值的整体向右移一格,然后放入主函数的while(1)中循环,
{
    for (int i = 0; i < HEIGHT; i++)//把蛇身的四个点的数值+1,从蛇头到尾变成23456
        for (int j = 0; j < WIDTH; j++)
            if (Blocks[i][j] > 0)
                Blocks[i][j]++;

    int oldTail_i, oldTail_j, oldHead_i, oldHead_j;//定义变量存储旧的蛇尾蛇头的位置
    int max = 0;
    for (int i = 0; i < HEIGHT; i++)
        for (int j = 0; j < WIDTH; j++)
        {
            if (max < Blocks[i][j])
            {
                max = Blocks[i][j];
                oldTail_i = i;
                oldTail_j = j;//遍历找到最大值,最大值就是旧的蛇尾
            }
            if (Blocks[i][j] == 2)
            {
                oldHead_i = i;
                oldHead_j = j;//遍历找到等于2的值,这就是旧的蛇头的位置
            }
            

        }
    int newHead_i = oldHead_i;
    int newHead_j = oldHead_j;
    newHead_j = oldHead_j + 1;//要做好初始化先,如果用户没有输入方向的话就先默认往右移动
    if (moveDirection == 'w')//向上的话就是行数-1,列数不变
    {
        newHead_i = oldHead_i-1;
        newHead_j = oldHead_j;
    }
    else if (moveDirection == 'a')//向左就是蛇头列数-1,行数不变
    {
        newHead_i = oldHead_i ;
        newHead_j = oldHead_j - 1;
    }
    else if (moveDirection == 's')
    {
        newHead_i = oldHead_i+1;
        newHead_j = oldHead_j ;
    }
    else if (moveDirection == 'd')
    {
        newHead_i = oldHead_i ;
        newHead_j = oldHead_j+1;
    }
     
    Blocks[newHead_i][newHead_j] = 1;//找到之后就把就蛇头的右边那个格子的数值设为1,变为新的蛇头
    Blocks[oldTail_i][oldTail_j] = 0;//就设为的数值设为0
}


//与输入无关的更新
void updateWithouInput()
{
    static int waitIndex = 1;//静态局部变量,初始化时为1
    waitIndex++;//每一帧+1
    if (waitIndex == 30)//如果等于10才执行,这样小蛇每隔10帧移动一次
    {
        moveSnake();//调用小蛇移动函数
        waitIndex = 1;//再变成1
    }
}

//与输入有关的更新
void updateWithInput()
{
    
    if (_kbhit())
    {
        char input=_getch();
        if (input == 'w' || input == 'a' || input == 's' || input == 'd')
        {
            moveDirection = input;
            moveSnake();
        }
    }
}


int _tmain(int argc, _TCHAR* argv[])//主函数
{
    startup();
    while (1)
    {
        show();
        updateWithouInput();
        updateWithInput();
    }
    
    


    _getch();
    closegraph();

    return 0;
}
/*
要实现按键操控小蛇移动:
问题1 怎么改变方向?
贪吃蛇第1部分时让小蛇往右移动是同样的道理。关键只在于蛇头newHead_i,newHead_j怎么变化
问题2 在updateWithInput函数里判断得出的moveDirection怎么传参给moveSnake函数?
直接把moveDirection定义为全局变量,判断完后直接调用moveSnake
问题3 Sleep函数在让画面停顿的同时也会让updateWithInput之类的函数停顿,小蛇的转向可能会不快速,怎么改进?
把updateWithouInput()里的sleep函数丢掉,使得每10帧小蛇才移动一次,如果改成30帧小蛇会移动得更慢,但是没有了sleep的影响,转向还是会很迅速
问题4 为什么updateWithouInput()和updateWithInput()函数都有调用moveSnake?
因为updateWithouInput()就是没有用户输入时也进行的更新,初始化moveDirection向右后,就算用户没有输入,小蛇也会一直向右移动,while(1)会使
函数中的moveSnake函数一直触发。而updateWithInput()会在用户输入后改变小蛇移动方向,所以也要调用moveSnake函数
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值