应天论坛

 找回密码
 参与我们

QQ登录

只需一步,快速开始

搜索
查看: 931|回复: 1

数字16拼图游戏完成版--带通关演示功能

[复制链接]

276

主题

303

帖子

3187

积分

管理员

湘南小侠客

Rank: 9Rank: 9Rank: 9

积分
3187

优质服务勋章论坛元老

QQ
发表于 2017-6-27 10:51:58 | 显示全部楼层 |阅读模式
数字16拼图游戏完成版--带通关演示功能
花了点时间做了个完整版,在原代码基础上做了较大的改动,比如不再用二维数组来表示地图数据,取而代之的是一个64位无符号整数。改进了游戏界面,游戏功能得到完善,如增加重玩、通关演示功能,如果游戏者在玩的过程中过不了关,可以看通关演示,电脑将会在推荐的步数里完成游戏。希望本游戏能让各位在枯燥的码代码时带来一丝休闲!
效果图:
20170606_2775c99090ff532b82e5ZEwmSJCGXpSA.jpg

[mw_shl_code=c,true]#include <stdio.h>        
#include <windows.h>      
#include <time.h>         
#include <conio.h>

void setLocate(int x,int y)
{//设置字符显示位置
    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
    COORD loc={x,y};
    SetConsoleCursorPosition(hOut,loc);
}

int getkey()
{//获得键值
    unsigned char a;
    int n=0;
    if(!kbhit())return 0;
    a=getch();
    if(a>127)
    {
        n=a*256;
        a=getch();
    }
    n=n+a;
    return n;
}

void setprint(int x,int y,char *p)
{//将字符串输出到指定位置
    setLocate(x,y);
    printf("%s",p);
}

void drawframe(int x,int y)
{//画外框
    int i;
    setprint(x,y,"┌─┬─┬─┬─┐");
    for(i=0;i<3;i++)
    {
        setprint(x,y+i*2+1,"│  │  │  │  │");
        setprint(x,y+i*2+2,"├─┼─┼─┼─┤");
    }
    setprint(x,y+i*2+1,"│  │  │  │  │");
    setprint(x,y+i*2+2,"└─┴─┴─┴─┘");
}

void drawmap(unsigned _int64 a,int x,int y)
{//画数字地图
    int i,j,k;
    for(i=16;i;i--,a/=16)
    {
        j=a%16;
        setLocate(((i-1)%4)*4+2+x,((i-1)/4)*2+1+y);
        if(j)printf("%2d",j);
        else
        {
            printf("  ");
            k=i-1;
        }
    }
    setLocate((k%4)*4+2+x,(k/4)*2+1+y);
}

unsigned _int64 testmove(unsigned _int64 a,int f)
{//测试移动是否合法并返回移动后的地图数据
    int i,j,x,y,c[16],b[4][2]={-1,0,0,-1,0,1,1,0};
    for(i=16;i;a/=16,i--)
    {
        c[i-1]=(int)(a%16);
        if(!c[i-1])j=i-1;
    }
    x=j/4+b[f][0];
    y=j%4+b[f][1];
    if(!(x<0||x>3||y<0||y>3))
    {
        c[j]=c[x*4+y];
        c[x*4+y]=0;
    }
    for(i=0,a=0;i<16;i++)a=a*16+c;
    return a;
}

unsigned _int64 rndmap(unsigned _int64 *p)
{//产生随机地图
    unsigned _int64 a=1311768467463790320,b;  
    int i,j,k;
    srand((unsigned)time(NULL));
    for(i=0,b=a;i<128;i++)
    {
        while(b==a)b=testmove(a,rand()%4);
        p=a;
        a=b;
    }
    p=a;
    p[i+1]=0;
    for(i=0;i<200&&p;i++)
    {
        for(j=i-1;j>=0&&p!=p[j];j--);
        if(j>=0)
        {//消除重复步数
            for(k=j;p;)p[k++]=p[i++];
            i=j;
            p[k]=0;
        }
    }
    return a;
}

void playmenu(int x,int y)
{//显示游戏菜单
    setprint(x,y+10,"     游戏状态           ");
    setprint(x-18,y+12,"方向键:控制  Esc: 退出  空格:新局  R:重玩  P:过关演示 ");
}

void demoplay(int x,int y,unsigned _int64 *p)
{//过关演示
    int step,gostep,key=57421;
    setprint(x,y+10,"   过关演示状态           ");
    setprint(x-18,y+12,"         前进:→    后退:←     Esc: 退出                        ");
    for(step=gostep=0;p[step];step++);
    while(key!=27)
    {
        if(key==57421&&gostep<step)gostep++;
        if(key==57419&&gostep>1)gostep--;
        if(key)
        {
            setprint(x,y+16,"   已走步数:");
            printf("%3d",gostep);
            drawmap(p[step-gostep],x,y);
        }
        key=getkey();
    }
}

void main()
{
    unsigned _int64 a,b,s[200];  //**gcc编译器可使用unsigned long long取代unsigned _int64**
    int fx=30,fy=2,key=32,step,gostep;
    drawframe(fx,fy);
    while(key!=27)
    {
        if(key==32)
        {
            playmenu(fx,fy);
            a=rndmap(s);
            for(step=0;s[step];step++);
            gostep=0;
            setprint(fx,fy+14,"   推荐步数:");
            printf("%3d",step);
        }
        if(key=='r'||key=='R')
        {
            a=s[step-1];
            gostep=0;
            playmenu(fx,fy);
        }
        if(key=='p'||key=='P')
        {
            demoplay(fx,fy,s);
            playmenu(fx,fy);
        }
        if(a==s[0]&&key)key=0;
        if(key>57415&&key<57425)
        {
            b=a;
            a=testmove(a,(key-57416)/3+(key>57419));
            if(a!=b)gostep++;
            if(a==s[0])setprint(fx,fy+10,"恭喜过关,空格键继续...           ");
        }
        if(key)
        {
            setprint(fx,fy+16,"   已走步数:");
            printf("%3d",gostep);
            drawmap(a,fx,fy);
        }
        key=getkey();
    }
}[/mw_shl_code]
每次见你穿短裤打领带,还穿个拖鞋,下次再这样穿不要从我家门口过了!
http://gsh.yzqz.cn/CassettePlayer/index.html

天之道,损有余而补不足.人之道则不然,损不足以奉有余.孰能有余以奉天下,唯有道者.
回复

使用道具 举报

276

主题

303

帖子

3187

积分

管理员

湘南小侠客

Rank: 9Rank: 9Rank: 9

积分
3187

优质服务勋章论坛元老

QQ
 楼主| 发表于 2017-6-27 11:29:32 | 显示全部楼层
http://bbs.yzqz.cn/thread-261-1-1.html
搜了个A*算法解八数码~

那个代码要用后缀.cpp运行
为了支持某些旧版编译器我把代码修改了一下(我已经说明了出处)~~

[mw_shl_code=c,true]#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NUM 5
typedef struct bgMatrix
{
    int v, w;
    char matrix[NUM][NUM];
    int pre;
    int f;
    int g;
    bool isVisited;
}Matrix;
typedef struct bgQueue
{
    Matrix* data;
    int length;
    int maxLength;
    int head;
    int tail;
}BGQueue;
typedef BGQueue* Queue;
typedef struct bgStack
{
    Matrix* data;
    int top;
}BGStack;
typedef BGStack* Stack;
char srcMatrix[NUM][NUM] =
{
    {'*', '*', '*', '*', '*'},
    {'*', '2', '8', '3', '*'},
    {'*', '1', '6', '4', '*'},
    {'*', '7', '0', '5', '*'},
    {'*', '*', '*', '*', '*'}
};
char dstMatrix[NUM][NUM] =
{
    {'*', '*', '*', '*', '*'},
    {'*', '1', '2', '3', '*'},
    {'*', '8', '0', '4', '*'},
    {'*', '7', '6', '5', '*'},
    {'*', '*', '*', '*', '*'}
};
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};
int cnt = -1;
Queue queue;
Stack stack;
bool astar(Matrix matrix);
int getG(Matrix matrix);
void initQueue(int length);
void putQueue(Matrix matrix);
Matrix getQueue(void);
int isQueueEmpty(void);
int isQueueFull(void);
void initStack(int length);
void pushStack(Matrix matrix);
Matrix popStack(void);
int isStackEmpty(void);
int matrixCmp(char src[][NUM], char dst[][NUM]);
void matrixCpy(char dst[][NUM], char src[][NUM]);
void matrixPrint(char matrix[][NUM]);
int main(int argc, char *argv[]) {
   
    Matrix src;
   
    initQueue(3628800+1);
    initStack(3628800+1);
   
    src.v = 3;
    src.w = 2;
    matrixCpy(src.matrix, srcMatrix);
    src.pre = cnt;
    src.f = 0;
    src.g = getG(src);
    astar(src);
    return 0;
}
bool astar(Matrix matrix)
{
    Matrix t, s;
   
    int v, w;
   
    int direction;
   
    putQueue(matrix);
   
    while (!isQueueEmpty())
    {
        s = getQueue();
      
        cnt++;
      
        for (direction = 0; direction < 4; direction++)
        {
            t = s;
            v = t.v + dx[direction]; w = t.w + dy[direction];
           
            if (srcMatrix[v][w] != '*')
            {
                char c = t.matrix[t.v][t.w];
                t.matrix[t.v][t.w] = t.matrix[v][w];
                t.matrix[v][w] = c;
               
                t.v = v;
                t.w = w;
                t.pre = cnt;
                t.f = s.f + 1;
                t.g = getG(t);
                t.isVisited = false;
               
                int h = 0;
                for (; h < queue->tail; h++)
                {
                    if (matrixCmp(queue->data[h].matrix, t.matrix))
                    {
                        break;
                    }
                }
               
                if (h == queue->tail)
                {
                    putQueue(t);
                  
                    if (matrixCmp(t.matrix, dstMatrix))
                    {
                        pushStack(t);
                       
                        for (int father = t.pre; !matrixCmp(queue->data[father].matrix, srcMatrix); father = queue->data[father].pre)
                        {
                            pushStack(queue->data[father]);
                        }
                       
                        puts("PathFind = ");
                       
                        matrixCpy(t.matrix, srcMatrix);
                        pushStack(t);
                       
                        while (!isStackEmpty())
                        {
                            s = popStack();
                            matrixPrint(s.matrix);
                        }
                       
                        return true;
                    }
                }
            }
        }
    }
   
    return false;
}
int getG(Matrix matrix)
{
    int g = 0;
   
    for (int i = 0; i < NUM; i++)
    {
        for (int j = 0; j < NUM; j++)
        {
            if (matrix.matrix[j] != '*' && matrix.matrix[j] != dstMatrix[j])
            {
                g++;
            }
        }
    }
   
    return g;
}
void initQueue(int length)
{
    queue =(bgQueue* ) malloc(sizeof(BGQueue));
   
    queue->data =(bgMatrix* ) malloc(sizeof(Matrix) * length);
    queue->length = 0;
    queue->maxLength = length;
    queue->head = 0;
    queue->tail = 0;
}
void putQueue(Matrix matrix)
{
    queue->data[queue->tail++] = matrix;
    queue->tail = queue->tail % queue->maxLength;
    queue->length++;
   
    Matrix* a =(bgMatrix* ) malloc(sizeof(Matrix) * queue->maxLength);
    Matrix* b =(bgMatrix* ) malloc(sizeof(Matrix) * queue->maxLength);
   
    int an = 0;
    int bn = 0;
    int i=0;
   
    for (i = 0; i < queue->length; i++)
    {
        if (queue->data.isVisited)
        {
            a[an++] = queue->data;
        }
        else
        {
            b[bn++] = queue->data;
        }
    }
    for (i = 0; i < bn-1; i++)
    {
        for (int j = bn-1; j > i; j--)
        {
            int h1 = b[j-1].f + b[j-1].g;
            int h2 = b[j].f + b[j].g;
           
            if (h1 > h2)
            {
                Matrix t = b[j-1];
                b[j-1] = b[j];
                b[j] = t;
            }
        }
    }
   
    for (i = 0; i < an; i++)
    {
        queue->data = a;
    }
   
    for (i = 0; i < bn; i++)
    {
        queue->data[an+i] = b;
    }
    free(a);
    free(b);
}
Matrix getQueue(void)
{
    queue->data[queue->head].isVisited = true;
   
    Matrix ret;
    ret = queue->data[queue->head++];
    queue->head = queue->head % queue->maxLength;
   
    return ret;
}
int isQueueEmpty(void)
{
    return queue->head == queue->tail;
}
int isQueueFull(void)
{
    return ((queue->tail+1) % queue->maxLength) == queue->head;
}
void initStack(int length)
{
    stack = (bgStack* )malloc(sizeof(BGStack));
   
    stack->data =(bgMatrix* ) malloc(sizeof(Matrix) * length);
    stack->top = 0;
   
}
void pushStack(Matrix matrix)
{
    stack->data[stack->top++] = matrix;
}
Matrix popStack(void)
{
    Matrix ret;
    ret = stack->data[--stack->top];
   
    return ret;
}
int isStackEmpty(void)
{
    return (stack->top == 0);
}
int matrixCmp(char src[][NUM], char dst[][NUM])
{
    int i, j, s, t, ret;
   
    char srcString[30] = {0};
    char dstString[30] = {0};
   
    s = 0;
    t = 0;
   
    for (i = 0; i < NUM; i++)
    {
        for (j = 0; j < NUM; j++)
        {
            srcString[s++] = src[j];
            dstString[t++] = dst[j];
        }
    }
   
    ret = !strcmp(srcString, dstString);
   
    return ret;
}

void matrixCpy(char dst[][NUM], char src[][NUM])
{
    int i, j;
   
    for (i = 0; i < NUM; i++)
    {
        for (j = 0; j < NUM; j++)
        {
            dst[j] = src[j];
        }
    }
}
void matrixPrint(char matrix[][NUM])
{
    char s[60] = {0};
   
    int i, j, k;
   
    k = 0;
   
    for (i = 0; i < NUM; i++)
    {
        for (j = 0; j < NUM; j++)
        {
            s[k++] = matrix[j];
        }
      
        s[k++] = '\r';
        s[k++] = '\n';
    }
   
    s[k++] = '\r';
    s[k++] = '\n';
   
    puts(s);
   
}  
[/mw_shl_code]
每次见你穿短裤打领带,还穿个拖鞋,下次再这样穿不要从我家门口过了!
http://gsh.yzqz.cn/CassettePlayer/index.html

天之道,损有余而补不足.人之道则不然,损不足以奉有余.孰能有余以奉天下,唯有道者.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 参与我们

本版积分规则

QQ|Archiver|手机版|小黑屋|应天社区 ( 湘ICP备17015224号 )

GMT+8, 2024-4-20 08:52 , Processed in 0.609359 second(s), 30 queries .

Powered by Discuz!

© 2001-2017 Comsenz Inc.


免责声明:
本站所发布的第三方软件及资源(包括但不仅限于文字/图片/音频/视频等仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢某程序或某个资源,请支持正版软件及版权方利益,注册或购买,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To: admin@yzqz.cn

快速回复 返回顶部 返回列表