ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2048游戏系列---功能模块第二稿【键盘输入】

2021-11-09 13:02:12  阅读:239  来源: 互联网

标签:case direction int 键盘输入 --- 2048 key msg dir


2048-具体功能实现二稿-键盘输入

各模块的实现之二-键盘输入

根据流程图可以把其分为以下几个模块:

  • 1-根据 dir 的值对 grid 进行操作
  • 2-键盘输入(本稿实现部分)
  • 3-在随机位置添加数值
  • 4-游戏结束检测
    2048程序流程图

一、目的

简单来说就是我们要造一个“黑盒子”,让我们输入的键盘消息经过这个黑盒子,电脑就知道我们在2048游戏中按下了什么键,要知道,电脑不像人一样聪明,是不能直接识别的

二、前提知识

  1. 一个键,它有3种状态,它被按下(key_msg_down ),它被按着(key_msg_down),它抬起来了(key_msg_up)

    //按键测试程序:
    #include "graphics.h"
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	initgraph(640,480,0);
    	setcaption("按键测试");
    	setbkcolor(WHITE);
    	setcolor(BLACK);
    	setfont(22,0,"楷体");
    	
    	int keyUPCount ,keyDownCount ,keyCharCount;
    	keyUPCount = keyDownCount = keyCharCount = 0;
    	
    	for( ; is_run(); delay_fps(60))
    	{
    		cleardevice();
    		while(kbmsg())									//kbmsg()判断是否有按键按下 
    		{
    			key_msg keyMsg = getkey();					//key_msg 是 EGE 中的按键消息结构体,有 3 个 unsiged int 成员: 
    			switch(keyMsg.msg)							//getkey() 获取键盘输入值(键值)
    			{											//msg---消息类型, key---按键码, flag--辅助按键(判断有没有同时按下 Shift 或 Ctrl) 
    				case key_msg_down:						//检测按键按下,长按会一直加
    									keyDownCount++;
    									break;
    				case key_msg_up:						//检测按键抬起
    									keyUPCount++;	
    									break;
    				case key_msg_char:						//检查是否输入字符: 除了TAB,CAPSLOCK,SHIFT,CTRL,FN,ALT,小键盘数字,Num Lk,小键盘上下左右 
    									keyCharCount++;
    									break;	
    			}
    		}	
    		xyprintf(50, 300, "down计数:%d  up计数:%d  char计数:%d", keyDownCount,keyUPCount,  keyCharCount);	
    	}
    	getch();
    	closegraph(); 
    	return 0;
    }
    
  2. W,A,S,D按键的key值(加上小键盘的上下左右)

    EGE 帮我们用宏定义好了:

    键盘值键值
    W‘W’
    A‘A’
    S‘S’
    D‘D’
    key_up
    key_down
    key_left
    key_right

三、键盘控制四方向模板

while(kbmsg())
{
    key_msg keyMsg = getkey();
    if(keyMsg.msg == key_msg_down)
    {
        switch(keyMsg.key)
        {
            case 'W':case key_up   : direction = 0; break;//上
            case 'S':case key_down : direction = 1; break;//下
            case 'A':case key_left : direction = 2; break;//左
            case 'D':case key_right: direction = 3; break;//右
        }
    }
}
if(direction!=-1)
{
    ...
}

四、根据 direction 的值进行移动(上一篇的内容讲过)

  • 屏幕的坐标轴原点(0, 0)在左上角,以向右为 x 轴,向下为 y 轴

  • 现在的坐标是(x, y),移动逻辑如下

    移动方向direction值运算偏移值
    向上0(x, y)+ (0,-1)(0,-1)
    向下1(x, y)+ (0, 1)(0, 1)
    向左2(x, y)+ (-1,0)(-1, 0)
    向右3(x, y)+ (1, 0)(1, 0)
  • 定义偏移数组:

    int dx = [0,0,-1,1];
    int dy = [1,1,0,0];
    
  • 得到 direction 后统一运算

    x += dx[direction];
    y += dy[direction];
    

    移动方向和 direction的值对应关系可变:在本游戏中:
    请添加图片描述

五、补全键盘输入到已写程序中

  • 上篇程序实现概览:
    上篇程序概览

  • 图中蓝色圈出部分是我们指定 dir 的值,现在我们让程序根据键盘输入确定 dir 的值

  • 我们要在 Move函数中加入判断,dir 的值无效则退出执行:

    if(dir==-1)	return;
    //或者:
    //if(dir<0||dir>3)	return;
    
  • EGE 的规范框架:https://xege.org/manual/tutorial/21.htm

    以下是框架简化:

    //基础动画一:规范框架
    #include <graphics.h>
    int main(void)
    {
    	initgraph(640, 480);
    	for ( ; is_run(); delay_fps(60) )
    	{
    		// 清屏
    		cleardevice();
    		
    		// todo: 逻辑更新(数据更新)
    		//
    
    		// todo: 图形更新
    	}
        getch();
    	closegraph();
    	return 0;
    }
    
  • 加入框架后

    #include <iostream>
    #include "graphics.h"
    using namespace std;
    //测试矩阵 
    int grid[4][4] = {
        {0,1,2,3},
        {0,1,2,3},
        {0,1,2,3},
        {0,1,2,3}
    };
    int EmptyBlock = 16;	//空格数 
    //打印函数 
    void PrintGrid()
    {
        for(int i=0; i<4; i++)
        {
            for(int j=0; j<4; j++)
                cout << grid[i][j] << " ";
            cout << endl;
        }
        cout << endl;
    }
    //计算空格函数 
    int CalculateEmpty()
    {
        int cnt = 0;
        for(int i=0; i<4; i++)
            for(int j=0; j<4; j++)
                if(grid[i][j]==0)   cnt++;
        return cnt;
    }
    
    //移动函数 
    int dir;				// 0-左,1-上,2-右,3-下 
    static int x0[4] = {0, 0, 3, 0};
    static int y0[4] = {0, 0, 0, 3};
    static int firstOffset[4][2]  = {{1,0},{0,1},{-1,0},{0,-1}};
    static int secondOffset[4][2] = {{0,1},{1,0},{0,1} ,{1,0}};
    void Move(int dir)
    {
    	if(dir==-1)	return;
        int tx, ty;
        int t1x, t1y;
        int t2x, t2y;
        for(int i=0; i<4; i++)
        {
            tx = x0[dir] + i*secondOffset[dir][0];
            ty = y0[dir] + i*secondOffset[dir][1];
           //cout << "(" << tx << ", " << ty << ")" << endl;
           
            t1x = tx;
            t1y = ty;
            t2x = tx + firstOffset[dir][0]; 
            t2y = ty + firstOffset[dir][1];
            for( ;t2x>=0&&t2x<=3&&t2y>=0&&t2y<=3; t2x+=firstOffset[dir][0],t2y+=firstOffset[dir][1])
            {
                if(grid[t2y][t2x]!=0)
                {
                    if(grid[t1y][t1x]==0)
                    {
                        grid[t1y][t1x] = grid[t2y][t2x];
                        grid[t2y][t2x] = 0;
                    }
                    else if(grid[t1y][t1x]==grid[t2y][t2x])
                    {
                        grid[t1y][t1x]++;
                        grid[t2y][t2x] = 0;
                        t1x += firstOffset[dir][0];
                        t1y += firstOffset[dir][1];
                    }
                    else if(t1x+firstOffset[dir][0]!=t2x||t1y+firstOffset[dir][1]!=t2y)
                    {
                        grid[t1y+firstOffset[dir][1]][t1x+firstOffset[dir][0]] = grid[t2y][t2x];
                        grid[t2y][t2x] = 0;
                        t1x += firstOffset[dir][0];
                        t1y += firstOffset[dir][1];
                    }
                    else
                    {
                        t1x += firstOffset[dir][0];
                        t1y += firstOffset[dir][1];
                    }
                }
                
            }
        }
    }
    
    int main()
    {
    	initgraph(200, 200);
    	cout << "dir = " << dir << endl;
        cout<< "EmptyBlock = " << CalculateEmpty() << endl;
        PrintGrid();
        
        for ( ; is_run(); delay_fps(60) )
    	{
    		dir = -1;
    		cleardevice();
    		
    		// todo: 逻辑更新(数据更新)
    		//按键检测	
    		while(kbmsg())
    		{
    		    key_msg keyMsg = getkey();
    		    if(keyMsg.msg == key_msg_down)
    		    {
    		        switch(keyMsg.key)
    		        {
    		            case 'A':case key_left  : dir = 0; break;//左 
    		            case 'W':case key_up  	: dir = 1; break;//上 
    		            case 'D':case key_right : dir = 2; break;//右 
    		            case 'S':case key_down	: dir = 3; break;//下 
    		        }
    		    }
    		}   
    		// todo: 图形更新
    		if(dir!=-1)
    		{
    			system("cls");
    			cout << "dir = " << dir << endl;
    			switch(dir)
    		        {
    		            case  0: cout << "按下了 A/左 键" << endl; break;//左 
    		            case  1: cout << "按下了 W/上 键" << endl; break;//上 
    		            case  2: cout << "按下了 D/右 键" << endl; break;//右 
    		            case  3: cout << "按下了 S/下 键" << endl; break;//下 
    		        }
    			Move(dir);  
        		cout<< "EmptyBlock = " << CalculateEmpty() << endl;
        		PrintGrid();
    		}
    	}
    	getch();
        closegraph();
        return 0;
    }
    

    运行会弹出两个窗口:控制台窗口 和 100*100(像素)EGE窗口

    鼠标要点一下黑黑的EGE窗口(给控制权),再把输入法调为英文,就可以试试 WASD 和小键盘上下左右了

    F11调试运行–》鼠标点EGE黑框,输入法改为英文—》键入

2048键盘输入测试


OK,本篇内容就到这里了,我们摆脱了直接给 dir 赋值,改用键盘输入

不过,在 GIF 中也看到,当数字合并后,并没有新的数字生生成,后面只有 3,4,5 三个数字移动,

下一篇我们就让它合并或移动后,根据条件生成新的数字

还有:数字的合并逻辑是:相同的合并加 1,如,1,1–》2; 2,2–》3; 4,4–》5,而不是 2,4,8 ,这与我们后面储存图像的逻辑有关,2^1 = 2; 2^2 = 4; 2^3 = 8;2^4 = 16……

请添加图片描述

标签:case,direction,int,键盘输入,---,2048,key,msg,dir
来源: https://blog.csdn.net/apple_52421619/article/details/121225582

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有