GIF 2020-11-6 13-00-38.gif

去年年底写的一个小游戏

玩法:

  1. 方向键控制
  2. 空格随机打乱
  3. 按下字母a自动还原

介绍:

  1. 通过递归实现路径搜索

控制台的简单驱动,(在某坐标写入某字符)

HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;                    //设置控制台用的

void windows_init()
{
    GetConsoleCursorInfo(hOut, &CursorInfo);        //获取控制台光标信息
    CursorInfo.bVisible = false;            //隐藏控制台光标
    SetConsoleCursorInfo(hOut, &CursorInfo);        //设置控制台光标状态

    srand(time(0));
}

void set_colo(char colo)//用于设置字体颜色
{
    SetConsoleTextAttribute(hOut, colo | hig);
}

void colo_print(char colo, const char* p) // 可以设置颜色的显示
{
    SetConsoleTextAttribute(hOut, colo | hig);
    printf(p);
    SetConsoleTextAttribute(hOut, white | hig);
}
void set_y_x(int y, int x)//设置光标位置
{
    COORD pos = { x,y };
    SetConsoleCursorPosition(hOut, pos);
}
void y_x_colo_print(int y, int x, char colo, const char* p)//可以设置坐标以及颜色的文件显示
{
    set_y_x(y, x);
    colo_print(colo, p);
}
char get_key()                    //获得按键键值
{
    char a;
    if (_kbhit() == 1)            //由于单使用 _getch()会导致程序堵塞,所以用先用_kbhit()获得是否有按键按下
    {
        a = _getch();
        return a;
    }
    return 0;

}

long HAL_GetTick()
{
    return clock();

}

void HAL_Delay(long a)
{
    long b;
    b = HAL_GetTick() + a;
    while (b> HAL_GetTick());

}

主代码

#define fram_color  lightblue  //边框颜色
#define d_color     white      //数字颜色

uint8_t num_array[3][3] = { 1,2,3,4,5,6,7,8,0 };
unsigned int step = 0;                                //步数
unsigned char hh = 0, mm = 0, ss = 0;                //时间  时分秒

void dis_map()
{
    char y, x,buff[1];
    for (y = 0; y < 3; y++)
    {
        for (x = 0; x < 3; x++)
        {
            
            y_x_colo_print(y,x*3,fram_color,"[");
            if (num_array[y][x] != 0)
            {
                sprintf(buff, "%d", num_array[y][x]);
                y_x_colo_print(y, (x * 3) + 1, d_color, buff);
            }
            else
            {
                y_x_colo_print(y, (x * 3) + 1, d_color, " ");
            }
            y_x_colo_print(y, (x * 3) + 2, fram_color, "]");
        }
    }
}
unsigned char zerox;                                //空白的位置
unsigned char zeroy;
void lookupzero()//找空白的位置
{
    char x, y;
    for (y = 0; y < 3; y++)
    {
        for (x = 0; x < 3; x++)
        {
            if (num_array[y][x] == 0)
            {
                zerox = x;
                zeroy = y;
            }
        }
    }
}
int move(char dir, char t)//移动方向,是否真移动
{
    char index;
    if (dir == 0)
    {
        lookupzero();
        if (zeroy != 2)
        {
            if (t == 1)
            {
                num_array[zeroy][zerox] = num_array[zeroy + 1][zerox];
                num_array[zeroy + 1][zerox] = 0;
            }
            return 1;

        }
    }
    if (dir == 1)
    {
        lookupzero();
        if (zeroy != 0)
        {
            if (t == 1)
            {
                num_array[zeroy][zerox] = num_array[zeroy - 1][zerox];
                num_array[zeroy - 1][zerox] = 0;
            }
            return 1;

        }
    }
    if (dir == 2)
    {
        lookupzero();
        if (zerox != 2)
        {
            if (t == 1)
            {
                num_array[zeroy][zerox] = num_array[zeroy][zerox + 1];
                num_array[zeroy][zerox + 1] = 0;
            }
            return 1;

        }
    }
    if (dir == 3)
    {
        lookupzero();
        if (zerox != 0)
        {
            if (t == 1)
            {
                num_array[zeroy][zerox] = num_array[zeroy][zerox - 1];
                num_array[zeroy][zerox - 1] = 0;
            }
            return 1;

        }
    }
    return 0;
}
void randommove(int i)//随机移动i次
{
    int a, b, c;
    for (a = 0; a < i; a++)
    {
        do
        {
            b = rand() % 4;
            c = move(b, 1);
        } while (!c);

    }
}
int checkwin()//检查胜利
{
    if (num_array[0][0] == 1 & num_array[0][1] == 2 & num_array[0][2] == 3 & num_array[1][0] == 4 & num_array[1][1] == 5 & num_array[1][2] == 6 & num_array[2][0] == 7 & num_array[2][1] == 8 & num_array[2][2] == 0)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void dis_data()
{
    char buff[16];
    sprintf(buff, "step:%04d\n time:%02d:%02d:%02d", step,hh,mm,ss);
    y_x_colo_print(4,0,green,buff);

}

/********************/
//自动还原功能,比赛用不到但可以研究一下
unsigned int astepnum = 0;                            //移动步骤
unsigned int cacemap[999][3][3];                    //缓存地图

void goandback(char a) //0前进记录一步   1后退还原一步
{
    char x, y;
    if (a == 0)
    {
        for (y = 0; y < 3; y++)
        {
            for (x = 0; x < 3; x++)
            {
                cacemap[astepnum][y][x] = num_array[y][x];
            }
        }
        astepnum += 1;
    }
    if (a == 1)
    {
        astepnum -= 1;
        for (y = 0; y < 3; y++)
        {
            for (x = 0; x < 3; x++)
            {
                num_array[y][x] = cacemap[astepnum - 1][y][x];
            }
        }


    }
}

int constback(char a)//对方向取个反  防止抽搐
{
    if (a == 0)
    {
        return 1;
    }
    if (a == 1)
    {
        return 0;
    }
    if (a == 2)
    {
        return 3;
    }
    if (a == 3)
    {
        return 2;
    }
}
int dil(char t)   //
{
    char a = 0, b, c;
    char x, y;
    b = 0;
    for (a = 0; a < 4; a++)
    {
        if (a != constback(t) & astepnum <= 25)
        {

            if (move(a, 1))
            {
                goandback(0);
                if (checkwin())
                {
                    return 1;
                }
                else
                {
                    if (dil(a)) { return 1; }
                }
            }
        }
    }

    goandback(1);
    return 0;
}

char autorun()
{
    char a;
    char x, y;
    goandback(0);
    if (dil(0))
    {
        for (a = 0; a < astepnum; a++)
        {
            for (y = 0; y < 3; y++)
            {
                for (x = 0; x < 3; x++)
                {
                    num_array[y][x] = cacemap[a][y][x];
                }
            }
            dis_map();
            step += 1;
            HAL_Delay(400);
            
        }

        return 1;
    }
    else
    {
        return 0;
    }
}

/*******************/

void game_info()
{
    printf("华容道小游戏\n吴文峰\n2019-12-04\n按任意键开始");
    _getch();
    
}
int main()
{
    enum {star,playing,automove,over};
    char run = star,key;
    long second_t=0;                            //时间变量
    //game_info();
    windows_init();
    while (1)
    {
        key= get_key();                    //获得按键键值
        switch (run)
        {
        case star:
            randommove(500);//随机移动n次
            step = 0;
            hh = 0; mm = 0; ss = 0;
            astepnum = 0;
            y_x_colo_print(6, 0, green, "       ");
            run = playing;
            break;
        case playing:
            if (HAL_GetTick() > second_t)
            {
                second_t += 1000;
                ss++;
                if (ss == 60) { ss = 0; mm++; if (mm == 60) { mm = 0; hh++; } }
            }
            if (key == space) { run = star; }
            if (key == dd) { move(1, 1); step++;}
            if (key == ll) { move(2, 1); step++;}
            if (key == uu) { move(0, 1); step++;}
            if (key == rr) { move(3, 1); step++;}
            if (key == 97) { run = automove; }//
            if (checkwin())
            {
                y_x_colo_print(6, 0, green, "you win!");
                run = over;
            }
            dis_data();
            break;
        case over:
            if (key == space) { run = star; }
            break;
        case automove:
            if (autorun())
            {

            }
            else
            {
                y_x_colo_print(6, 0, green, "no");
            }
            run = playing;
            break;
        default:
            break;
        }
        dis_map();
        y_x_colo_print(8, 0, red, "华容道小游戏\n吴文峰\n2019-12-04\n\n方向键移动\n空格随机打乱\n按字母a自动还原");
    }

}

最后修改:2020 年 11 月 06 日
声明:无闻风博客|版权所有,违者必究|如未注明,均为原创| 转载:转载请注明原文链接